Анализ v-модели, синхронизации, $attrs/$lisrener, модификаторов provied/inject во Vue

Vue.js

Высшее благо подобно воде, а вода хороша для всего без борьбы. - «Дао Дэ Цзин»

Введение

При нормальной разработке часто используется некоторая связь между компонентами родитель-потомок, которая часто используетсяprops,vuexПодождите, вот еще три способа записиv-model,syncКак его использовать, и как реализовать, собственноv-model,syncЭто все синтаксический сахар. а также$attrs,$listenerРеализовать связь между родительскими и дочерними компонентами.

Как использовать

v-model

2.2.0+ Новый

v-mode1По сути, это синтаксический сахар, по умолчанию он будет использовать имяvalueизpropsи назвалinputсобытий, но такие элементы ввода, как радиокнопки, флажки и т. д., могут говоритьvalueЧерты используются для разных целей.

v-modelсценарии использования: когдаПодсборкаНеобходимо изменить родительский компонент черезpropsвходящее значение

родительский компонент

  • родительский компонент черезv-modelзначение привязки
  • Согласно сv-modelВходящее значение изменяется и запускает другие обновления, пожалуйста, передайтеwatchвходящее значение

Подсборка

  • утверждениеmodelсобытие набора объектовeventа такжеpropполе
  • пройти черезporpsПринять значение, переданное родительским компонентом
  • Модификация проходит черезthis.$emitтрансляция события

Пример кода:

код родительского компонента

<template>
  <children v-model="message"></children>
</template>
<script>
import children from "./children.vue";
export default {
  components: {
    children
  },
  data() {
    return {
      message: "parent"
    };
  },
  watch: {
    // 监听message变化
    message(newV, oldV) {
      console.log(newV, oldV);
    }
  }
};
</script>

код подкомпонента

<template>
  <h1>{{ message }}</h1>
</template>
<script>
export default {
  model: {
    prop: "message", //这个字段,是指父组件设置 v-model 时,将变量值传给子组件的 msg
    event: "input" //这个字段,是指父组件监听 parent-event 事件
  },
  props: {
    message: String //此处必须定义和model的prop相同的props,因为v-model会传值给子组件
  },
  mounted() {
    //这里模拟异步将msg传到父组件v-model,实现双向控制
    setTimeout(_ => {
      this.$emit("input", "children");
      //将这个值通过 emit 触发parent-event,将some传递给父组件的v-model绑定的变量
    }, 1500);
  }
};
</script>

Приведенный выше пример выполняетсяv-modelРеализовано, следующее не проходитv-modelдобиться такого же эффекта.

Реализовано без v-модели

Пример кода выглядит следующим образом:

Модификация кода родительского компонента

<template>
  <Children :message="message" @input="(event) => { message = event }"/>
</template>
<script>
// 不变
</script>

Модификация кода субкода

<template>
  // 不变
</template>
<script>
export default {
  props: {
    message: String
  },
  mounted() {
    setTimeout(() => {
      this.$emit("input", "children");
    }, 1500);
  }
};
</script>

просто поставьv-modelразделить наpropsа также@inputСобытия, подкомпоненты не нужно настраиватьmodel, просто примиpropsи черезthis.$emitПросто транслируйте событие. Конечно, это относительноv-modelЭтот метод относительно прост, но существует множество проверок гибкости, и выбор зависит от личных предпочтений. Интернет-адрес:

не могу поставитьiframeПросто поставь ссылкуЭтот пример кода

sync

2.3.0+ Новый

В некоторых случаях нам может понадобитьсяpropпровести**«Двусторонняя привязка». К сожалению, настоящийДвусторонняя привязка ** вызовет проблемы с обслуживанием, поскольку дочерний компонент может модифицировать родительский компонент, а очевидного источника изменений в родительском и дочернем компонентах нет.

Вот почему мы рекомендуемupdate:myPropNameСобытие модального триггера заменено. Также возможно пройтиsyncмодификатор для реализации.

Приведенный выше код примерно изменен следующим образом:

родительский компонент

  • Инициировать события, изменяяinputдляupdate:myPropNameдобиться такого же эффекта

Подсборка

  • путем измененияthis.$emit(update:myPropName)

код показывает, как показано ниже:

Модификация кода родительского компонента

  // 修改如下
  <Children :message="message" @update:input="(event) => { message = event }"/>

Модификация кода подкомпонента

  // 其他不变
  this.$emit("update:input", "children");

реализация синхронизации

Приведенный выше код может быть выполнен с помощьюsyncСокращенный до следующего кода:

Модификация кода родительского компонента

  // 修改如下
  <Children :messag.sync="message"/>

Модификация кода подкомпонента

  // 其他不变
  this.$emit("update:messag", "children");

в то же времяsyncОбъекты также поддерживаются, сотрудничатьv-bindРеализация может быть сокращена как:, но обратите внимание на следующие две особенности этого объекта:

Примечание с.syncмодификаторv-bindнельзя использовать с выражениями (например,v-bind:title.sync=”doc.title + ‘!’”это недействительно). Вместо этого вы можете указать только имя свойства, которое хотите связать, напримерv-model. Будуv-bind.syncиспользуется на буквальном объекте, например.v-bind.sync=”{ title: doc.title }”, не будет работать, потому что при анализе такого сложного выражения необходимо учитывать множество пограничных случаев.

attrs、listeners

$attrs

2.4.0 Новый

  • Типы:{ [key: string]: string }
  • только чтение
  • подробно: содержит бездействие в родительской областиpropРаспознанные (и приобретенные) привязки функций (classа такжеstyleКроме). Когда компонент не объявляет никакихprop, это будет включать все привязки родительской области (classа такжеstyleкроме), и может пройтиv-bind="$attrs"Передача внутренних компонентов — полезно при создании высокоуровневых компонентов.

$listeners

2.4.0 Новый

  • Типы:{ [key: string]: Function | Array<Function> }
  • только чтение
  • подробно: Входит в родительскую область (исключая.nativeмодификатор)v-onпрослушиватель событий. это может пройтиv-on="$listeners"Передача внутренних компонентов — полезно при создании компонентов более высокого уровня.

включить связь

Реализовать связь между родительскими и дочерними компонентами

код родительского компонента

<template>
  <div class="parent">
    <Children
      :message="message"
      @upDate="upDate"
      type="del"
      @input="(event) => { message = event }"
    />
  </div>
</template>

<script>
import Children from "./Children";
export default {
  components: {
    Children
  },
  data() {
    return {
      message: "parent",
      type: "del"
    };
  },
  methods: {
    upDate (event) {
      console.log(event);
      this.type = event;
    }
  },
  watch: {
    message: function() {
      console.log("更新message值为" + this.message);
    }
  }
};
</script>

код подкомпонента

<template>
  <div v-bind="$attrs" v-on="$listeners" class="children">{{message}} <span @click="$listeners.upDate('data')">{{$attrs.type}}</span></div>
</template>

<script>
export default {
  props: {
    message: String
  },
  mounted() {
    // console.log(this.$attrs);
    // console.log(this.$listeners);
    setTimeout(() => {
      this.$emit("input", "children");
      this.$emit('upDate', 'add')
    }, 1500);
  }
};
</script>

в то же время$attrs,$listenersОба могут быть междоменными компонентами «родитель-потомок» и могут передаваться между компонентами «родитель-потомок», подобноreactсерединаcontext, но часть концепции дизайна та же.

Суммировать

На самом деле выявляется.syncмодификатор, вcomplierЭтап будет компилироваться и генерировать несколькоprop, генерируя несколько事件. На самом деле вот такинструкция,модификатор,пользовательская директивавсе вvueКомпиляция разбивается наv8исполняемый код.

Будь тоvue,babel,reactизcomplierФаза компиляции условно делится на три этапа:

  • путем лексического разбораparseпорождающая абстракцияASTили抽象代码树
  • оптимизацияAST,Напримерvueпометить статические узлы,babalИзвлечение статического кода изoptimizeили优化AST树
  • существуетASTНа этапе кода генерируется исполняемый код, этот процесс можно назватьcodegen

v-model,syncМожет быть достигнута связь между родительским и дочерним компонентами, и значение, переданное родительским компонентом, может быть изменено в дочернем компоненте. Эти два метода можно использовать при обычном входе в рынок, а выбор конкретного метода зависит от личных предпочтений. существуетelement-uiэтоinputКомпоненты также используют связанные свойства.

Ссылаться на

$attrs

-v-model для пользовательских компонентов

модификатор синхронизации