Высшее благо подобно воде, а вода хороша для всего без борьбы. - «Дао Дэ Цзин»
Введение
При нормальной разработке часто используется некоторая связь между компонентами родитель-потомок, которая часто используется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 }”, не будет работать, потому что при анализе такого сложного выражения необходимо учитывать множество пограничных случаев.
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Компоненты также используют связанные свойства.