предисловие
Я считаю, что студенты, которые использовали Vue в реальных проектах, должны быть знакомы с взаимодействием между родительскими и дочерними компонентами в Vue.Vue использует хороший метод передачи данных, чтобы избежать проблем, связанных с взаимодействием компонентов. Сегодня делюсь с вамиСпособ связи, преимущества и недостатки между родительским и дочерним компонентами Vue и сценарии их применения в реальной работе.
Сначала давайте подумаем над этими вопросами
1 Сколько методов связи между родительскими и дочерними компонентами существует в Vue?
2 Как лучше всего общаться между родительскими и дочерними компонентами в Vue?
3 Каков сценарий применения каждого метода связи в Vue?
опора
1 Основное использование
propМетод связи является наиболее распространенным и наиболее часто используемым типом связи между родительскими и дочерними компонентами.Мы можем напрямую связывать свойства и методы с дочерними компонентами в тегах.Для свойств мы можем напрямую объявлять их через дочерние компоненты.propGet, для метода родительского элемента мы можем передатьthis.$emit触发.
Давайте просто напишемpropsСценарий взаимодействия родительско-дочернего компонента
родительский компонент
<template>
<div class="father" >
<input v-model="mes" /> <button @click="send" >对子组件说</button>
<div>子组件对我说:{{ sonMes }}</div>
<son :fatherMes="sendSonMes" @sonSay="sonSay" />
</div>
</template>
<script>
import son from './son'
export default {
name:'father',
components:{
son /* 子组件 */
},
data(){
return {
mes:'',
sendSonMes:'', /* 来自子组件的信息 */
sonMes:'' /* 发送给子组件的信息 */
}
},
methods:{
/* 传递给子组件 */
send(){
this.sendSonMes = this.mes
},
/* 接受子组件信息 */
sonSay(value){
this.sonMes = value
},
},
}
</script>
Нам нужно только передать данные дочерним компонентам здесьfatherMesи методы, предоставляемые дочерним компонентамsonSayПередается дочерним компонентам по метке.
Подсборка
<template>
<div class="son" >
<div> 父组件对我说:{{ fatherMes }} </div>
<input v-model="mes" /> <button @click="send" >对父组件说</button>
</div>
</template>
<script>
export default {
name:'son',
props:{
fatherMes:{
type:String,
default:''
}
},
data(){
return {
mes:''
}
},
methods:{
send(){
this.$emit('sonSay',this.mes)
}
},
}
</script>>
дочерний компонент черезpropsЧтобы определить и принять информацию, переданную родительским компонентом, мы можем напрямую передатьthisПолучено, для событий, переданных родительским компонентом, мы можем передатьthis.$emitдля запуска события.
Различать реактивные реквизиты
здесь иreactизpropsнемного другой,reactОбновления компонентов приходят изpropsобновление и себяstateизмениться, когдаpropsИзменено, обновит компонент по умолчанию. пока вVue, если мы передаем новый из родительского компонентаpropsне сделал этогоКоллекция зависимостей (templateколлекция шаблонов,computedКоллекция вычисляемых свойств), компонент не будет запускать обновление.
Эффект
форматирование данных
если мы хотимpropsdata для форматирования данных, затем используйтеcomputedприниматьpropsи отформатируйте нужный тип данных.
<div class="son" >
<div> 父组件对我说:{{ computedFatherMes }} </div>
<input v-model="mes" /> <button @click="send" >对父组件说</button>
</div>
export default {
name:'son',
props:{
fatherMes:{
type:String,
default:''
}
},
computed:{
computedFatherMes(){
return this.fatherMes + '😄😄'
}
},
}
мониторинг данных
когда мыpropsИзменение не хочет обновлять представление или не хочет обновлять представление немедленно, тогда вы можете использоватьwatchдля прослушивания вызовов от родительского компонентаpropsПеремена.
watch:{
fatherMes(newVaule){
console.log( newVaule)
}
},
2 преимущества
propsПреимущества передачи данных очевидны, гибки и просты, и могут быть использованы дляpropsДанные обрабатываются путем вычисления свойств, мониторинга данных и т. д. Связь между родительским и дочерним компонентами является гибкой и удобной. Это может быть ограничено только родительско-дочерним уровнем.
3 Недостатки
1 реквизит подделает
Мы используем родительский компонент в дочернем компонентеpropsКогда речь идет о присваивании переменных, изменении и других операциях,propsОн был изменен необъяснимым образом, а также были изменены данные родительского компонента, что может привести некоторых учащихся в замешательство.propsНеужели нельзя модифицировать, как тут поменялось?vueсерединаpropsМожно ли его изменить?, Что касается этого вопроса, то ответ нельзя дать прямо, еслиpropsЭто базовый тип данных, когда мы его изменим, он выявит ошибку. Давайте вместе рассмотрим пример.
родительский компонент
<template>
<div>
<div>父组件</div>
<son :fData="sonProps" />
</div>
</template>
<script>
import son from './sTampering'
export default {
name:'father',
components:{
son
},
data(){
return {
sonProps:''
}
},
}
</script>
Подсборка
<template>
<button >改变父组件props</button>
</template>
<script>
export default {
name:'son',
props:{
fData:{
required:true
}
},
methods:{
changFatherProps(){
this.fData = 'hello ,father'
}
}
}
</script>
Когда мы нажмем кнопку напрямую, будет выдано следующее предупреждение.
Но когда мы передаем ссылочный тип данных и изменяем свойство в data.
родительский компонент
data(){
return {
sonProps:{
a:1,
b:2
}
}
},
Подсборка
changFatherProps(){
this.fData.a = 'hello,world'
}
При нажатии на кнопку об ошибке не сообщается.
Итак, мы печатаем родительский компонентsonpropsданные:
Мы обнаружили, что родительский компонентdataДанные были изменены подкомпонентами. Итак, делаем вывод,Хотя дочерний компонент не может напрямую обращаться к родительскому компонентуpropВыполните переназначение, но когда родительский компонент является ссылочным типом, дочерний компонент может изменить родительский компонент.propsследующие свойства. Это очень неприятная вещь.Если первоначальная цель нашего дизайна состоит в том, чтобы данные родительского компонента также изменялись одновременно, этот результат приемлем, но когда мы не хотим никаких изменений в источнике данных родительского компонента. компонента, это серьезная проблема.логикаbug.
Так что этоpropsОдин из рисковых элементов связи.
2 Межуровневая коммуникация, коммуникация между одноуровневыми компонентами затруднена
Для межуровневой связи родительский компонент-дочерний компонент-дочерний компонент дочернего компонента нам, очевидно, необходимо общаться слой за слоем.propСвязывание свойств и методов сложнее реализовать, если вы сталкиваетесь с более сложными ситуациями.
Для связи между родственными компонентамиpropsНеобходимо использовать родительский компонент в качестве моста для реализации режима связи дочерний компонент -> родительский компонент -> дочерний компонент.Если вы хотите использовать родительский компонент в качестве среды, это определенно приведет к повторному рендерингу родительского компонента , а стоимость реализации связи между родственными компонентами относительно высока.
4 сценария применения
propsСценарий приложения очень прост, то есть ненормально взаимодействовать с глубоко вложенными родительско-дочерними компонентами и взаимодействовать с одноуровневыми компонентами с менее сложными отношениями.
2 это.$xxx
Получите непосредственно через данные ниже этогоvueМетод экземпляра более жесток, потому что то, что мы называем компонентом, в конечном итоге будет объектом, в котором хранится различная информация о компоненте, а компонент и компонент проходят через него.this.$childrenиthis.$parentуказатели связаны. Потому что в проекте есть только одинrootКорневой компонент, теоретически, мы можем найти черезthis.$children this.$parentдля доступа к любому компоненту на странице, но как точно сопоставить целевой компонент, действительно очень сложная проблема.
1 Основное использование
родительский компонент
<template>
<div class="father" >
<input v-model="mes" /> <button @click="send" >对子组件说</button>
<son2 v-if="false" />
<div>子组件对我说:{{ sonMes }}</div>
<son />
</div>
</template>
<script>
import son from './son'
import son2 from './son2'
export default {
name:'father',
components:{
son ,/* 子组件 */
son2
},
data(){
return {
mes:'',
sendSonMes:'', /* 来自子组件的信息 */
sonMes:'' /* 发送给子组件的信息 */
}
},
methods:{
/* 传递给子组件 */
send(){
/* 因为son组件是第一个有效组件所以直接去下标为0的组件 */
const currentChildren = this.$children[0]
currentChildren.accept(this.mes)
},
/* 接收子组件的信息 */
accept(value){
this.sonMes = value
}
},
}
</script>
Подсборка
<template>
<div class="son" >
<div> 父组件对我说:{{ fatherMes }} </div>
<input v-model="mes" /> <button @click="send" >对父组件说</button>
</div>
</template>
<script>
export default {
name:'son',
data(){
return {
mes:'',
fatherMes:''
}
},
methods:{
/* 接受父组件内容 */
accept(value){
this.fatherMes = value
},
/* 向父组件发送信息 */
send(){
this.$parent.accept(this.mes)
},
},
}
</script>
Эффект
Мы это ясно видим, иpropsобщение по сравнению сthis.$parent,this.$childrenЭто более лаконично, не нужно привязывать события и свойства к дочерним компонентам, нужно только декларировать методы отправки и получения данных в родительском и дочернем компонентах. Связь между компонентами может быть реализована, что кажется очень удобным, но в реальной эксплуатации будут большие недостатки, иvueСам по себе этот способ общения не пропагандируется. И с этим типом связи связан большой риск, который мы объясним позже.
2 преимущества
легко и удобно
this.$children,this.$parent this.$refsЭтот метод связи упрощает непосредственное получение экземпляра vue, а также непосредственное получение или ссылку на данные и методы в экземпляре vue.
3 Недостатки
1 $this.children не поддается контролю и имеет определенные риски
В приведенном выше примере, если мы внесем небольшое изменение в родительский компонент, об ошибке будет сообщено напрямую.
предыдущий
<son2 v-if="false" />
изменить на
<son2 v-if="true" />
Будет сообщено об указанной выше ошибке, причина ошибки очень проста, мы используем$childrenНижний индекс получен, но одноуровневый компонентson2 v-if = trueПосле этого проходимthis.$children[0]что получаетсяson2компонента, son2 не имеет метода связывания, поэтому делается вывод, что дляv-ifОтображение компонентов динамического управления скрыто, не рекомендуется.this.$childrenиспользование, вместо этого мы можем использоватьrefПолучите экземпляр соответствующего подкомпонента.
Измените его на
<son ref="son" />
Затем получите:
const currentChildren = this.$refs.son
Полностью решил проблему.
2 не способствует компонентизации
Метод прямого получения экземпляра компонента в определенной степени затрудняет компонентную разработку.В процессе компонентной разработки эти методы предоставляются вовне, и эти методы используются внутри.Без предварительной консультации состояние родительского и дочернего компонентов непрозрачный корпус, все естьНеизвестный, поэтому существуют риски, когда разные разработчики получают методы компонента, независимо от того, имеют ли предоставленные методы и свойства компонента некоторую внутреннюю связь. Первоначальная цель идеи разработки компонента состоит не во внесении определенных изменений во внутренние компоненты извне компонента, а во внутренних изменениях для уведомления событий внешнего метода. И наоборот, если он находится внутри дочернего компонента, он активно передает некоторую информацию родительскому компоненту, и невозможно определить, существует ли родительский компонент.
3 Сложность связи между глубоко вложенными компонентами родственных компонентов
Что касается реквизита, если это связь между непосредственными компонентами братьев, родительский компонент необходимо использовать в качестве моста для промежуточной связи, а коммуникацию компонентов глубокого уровня не нужно связывать слой за слоем, как связь реквизита, но есть один момент, он должен постепенно переходить на верхний уровень.Или как точно получить целевой экземпляр с нижнего уровня - очень хлопотная проблема, и каждый раз, когда вы переходите на слой, риск и неопределенность будет постепенно увеличиваться.
4 сценария применения
Способ связи, полученный напрямую через инстанс, подходит дляизвестен,обездвиженТакой метод связи требует, чтобы родительский и дочерний компоненты были в высшей степени прозрачными, чтобы они знали друг друга, и ясно, что родительский и дочерний компоненты имеют эти атрибуты метода и то, для чего они используются. Так что этот способ больше подходитстраницакомпоненты, и не подходит для некоторыхБиблиотека сторонних компонентов,илиобщедоступный компонент.
Три обеспечивают инъекцию
если мы предположимvueсерединаprovideиinject, я бы сначала подумал оreactизcontextВ контексте можно сказать, что две роли в определенной степени очень похожи благодаря родительскому компоненту.provideВыставляйте методы, свойства или их собственные экземпляры, компоненты-потомки, компоненты-слоты и даже компоненты-слоты компонентов-потомков черезinjectпоставить родителейprovideпринести. Предоставьте его для собственного использования, очень классическое приложениеprovideиinjectДело в томelement-uiсерединаel-formиel-form-item
Давайте сначала представим сценарий с вопросами
<el-form label-width="80px" :model="formData">
<el-form-item label="姓名">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="年龄">
<el-input v-model="formData.age"></el-input>
</el-form-item>
</el-form>
Мы видим, чтоel-formиel-form-itemНикакая операция связи не должна быть установлена, тогдаel-formиel-form-itemКак это связано и разделяет состояние? Мы продолжаем смотреть вниз с вопросами.
1 Основное использование
общий путь
Мы используем случай родительский компонент -> дочерний компонент -> внучатый компонент
родительский компонент
<template>
<div class="father" >
<div>子组件对我说:{{ sonMes }}</div>
<div>孙组件对我说:{{ grandSonMes }}</div>
<son />
</div>
</template>
<script>
import son from './son'
export default {
name:'father',
components:{
son /* 子组件 */
},
provide(){
return {
/* 将自己暴露给子孙组件 ,这里声明的名称要于子组件引进的名称保持一致 */
father:this
}
},
data(){
return {
grandSonMes:'', /* 来自子组件的信息 */
sonMes:'' /* 发送给子组件的信息 */
}
},
methods:{
/* 接受孙组件信息 */
grandSonSay(value){
this.grandSonMes = value
},
/* 接受子组件信息 */
sonSay(value){
this.sonMes = value
},
},
}
</script>
Здесь мы проходимprovideразоблачить себя.⚠️⚠️⚠️Объявленное здесь имя должно соответствовать имени, импортированному подкомпонентом
Подсборка
<template>
<div class="son" >
<input v-model="mes" /> <button @click="send" >对父组件说</button>
<grandSon />
</div>
</template>
<script>
import grandSon from './grandSon'
export default {
/* 子组件 */
name:'son',
components:{
grandSon /* 孙组件 */
},
data(){
return {
mes:''
}
},
/* 引入父组件 */
inject:['father'],
methods:{
send(){
this.father.sonSay(this.mes)
}
},
}
</script>
дочерний компонент черезinjectПредставьте экземпляр родительского компонента, а затем вы можете напрямую передатьthis.fatherВы можете напрямую получить родительский компонент и вызвать следующийsonSayметод.
компонент внука
<template>
<div class="grandSon" >
<input v-model="mes" /> <button @click="send" >对爷爷组件说</button>
</div>
</template>
<script>
export default {
/* 孙组件 */
name:'grandSon',
/* 引入爷爷组件 */
inject:['father'],
data(){
return {
mes:''
}
},
methods:{
send(){
this.father.grandSonSay( this.mes )
}
}
}
</script>
Компонент-внук не знает, как работать, и введенный метод такой же, как и у дочернего компонента.
Эффект
2-х слотовый метод
provide , injectТо же самое можно применить и к слотам, немного изменим родительский и дочерний компоненты.
родительский компонент
<template>
<div class="father" >
<div>子组件对我说:{{ sonMes }}</div>
<div>孙组件对我说:{{ grandSonMes }}</div>
<son >
<grandSon/>
</son>
</div>
</template>
<script>
import son from './slotSon'
import grandSon from './grandSon'
export default {
name:'father',
components:{
son, /* 子组件 */
grandSon /* 孙组件 */
},
provide(){
return {
/* 将自己暴露给子孙组件 */
father:this
}
},
data(){
return {
grandSonMes:'', /* 来自子组件的信息 */
sonMes:'' /* 发送给子组件的信息 */
}
},
methods:{
/* 接受孙组件信息 */
grandSonSay(value){
this.grandSonMes = value
},
/* 接受子组件信息 */
sonSay(value){
this.sonMes = value
},
},
}
</script>
Подсборка
<template>
<div class="son" >
<input v-model="mes" /> <button @click="send" >对父组件说</button>
<slot />
</div>
</template>
добиться того же коммуникативного эффекта. Фактически, этот режим слота находится в компоненте, зарегистрированном родительским компонентом, и, наконец, компонент-внук также будет привязан к дочерним компонентам дочернего компонента. Аналогично ситуации выше.
при условии, что другие виды использования
provideПри необходимости может быть открыт не только весь родительский компонент, но и только его часть (некоторые свойства родительского компонента или метод родительского компонента). используется родительский компонент, поэтому мы могли бы просто предоставить два метода связи. Но примечание здесь в том, что если мы предоставляем метод снаружи, если в методе есть операцияthisповедение, требует привязкиthis
родительский компонент
provide(){
return {
/* 将通信方法暴露给子孙组件(注意绑定this) */
grandSonSay:this.grandSonSay.bind(this),
sonSay:this.sonSay.bind(this)
}
},
methods:{
/* 接受孙组件信息 */
grandSonSay(value){
this.grandSonMes = value
},
/* 接受子组件信息 */
sonSay(value){
this.sonMes = value
},
},
Подсборка
/* 引入父组件方法 */
inject:['sonSay'],
methods:{
send(){
this.sonSay(this.mes)
}
},
2 преимущества
1 На связь компонентов не влияет иерархия подкомпонентов
provide injectиспользование иreact.contextочень похожий,provideэквивалентноContext.Provider ,injectэквивалентноContext.Consumer, чтобы на связь родительского компонента не влияли его глубокие дочерние компоненты.
2 для слотов, вложенные слоты
provide injectСделать связь между родительскими и дочерними компонентами, вложенными в слоты, простой, это то, о чем мы говорили в начале, почемуel-formиel-form-itemТо же, что и возможность координировать и управлять состоянием формы. существуетelementв исходном кодеel-formчто будетthisсамprovideвне.
3 Недостатки
1 Не подходит для общения с братом
provide-injectФункция координации заключается в получении статуса, методов, свойств и т. д., предоставляемых родительскими компонентами.Направление потока всегда от родителя к дочернему.provideПредоставленный контент не может быть получен одноуровневыми компонентами, поэтому связь между одноуровневыми компонентами не может быть завершена таким образом.
2 Родительский компонент не может активно взаимодействовать
provide-injectБольше похоже на то, как отец зарабатывает деньги, чтобы тратить их на своего сына: сын может получить условия, предлагаемые отцом, но отец не может ничего требовать от сына. Как и в этой аналогии, родительский компонент ничего не знает о состоянии дочернего компонента. Он также не может активно инициировать связь с подкомпонентами.
4 сценария применения
provide-injectЭтот метод связи больше подходит для глубокого и сложного взаимодействия родитель-потомок.Компоненты-потомки могут совместно использовать состояние родительского компонента.Еще один момент заключается в том, что он подходит дляel-form el-form-itemСценарий типа слота.
Четыре вьюкса
vuexрассматриватьсяvueЛучшее решение для обработки сложной связи компонентов вvueиvuexВышел из чрева матери. иvuexНижний слой также используетсяvueосуществленный. Я считаю, что многие студентыvuexНе незнакомый. Далее мы начинаем знакомить с vuex.
1 Основное использование
файл vuex
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
export default new Vuex.Store({
state:{
fatherMes:'',
sonMes:'',
fatherMesAsync:''
},
mutations:{
sayFaher(state,value){
state.fatherMes = value
},
saySon(state,value){
state.sonMes = value
},
sayAsyncFather(state,value){
state.fatherMesAsync = value
}
},
actions:{
asyncSayFather({ commit },payload){
return new Promise((resolve)=>{
setTimeout(()=>{
resolve(payload)
},2000)
}).then(res=>{
commit('sayAsyncFather',res)
})
}
}
})
существуетstoreфайл, мы объявляем триmutationsсоответственно общаться с родительским компонентомsaySon, родительский компонент связывается с дочерним компонентом, метод синхронизацииsayFaherи асинхронный методsayAsyncFather, в действиях моделируется асинхронная задача, которая выполняется через три секундыasyncSayFather.
main.js
import store from './components/vuex/store'
new Vue({
render: h => h(App),
store
}).$mount('#app')
main.jsввести в магазин
родительский компонент
<template>
<div class="father" >
<input v-model="mes" /> <button @click="send" >同步:对子组件说</button><br/>
<input v-model="asyncMes" /> <button @click="asyncSend" >异步:对子组件说</button><br/>
<div>子组件对我说:{{ sonMes }}</div>
<son />
</div>
</template>
<script>
import son from './son'
export default {
/* 父组件 */
name:'father',
components:{
son ,/* 子组件 */
},
data(){
return {
mes:'',
asyncMes:''
}
},
computed:{
sonMes(){
return this.$store.state.sonMes
}
},
mounted(){
console.log(this.$store)
},
methods:{
/* 触发mutations,传递数据给子组件 */
send(){
this.$store.commit('sayFaher',this.mes)
},
/* 触发actions,传递数据给子组件 */
asyncSend(){
this.$store.dispatch('asyncSayFather',this.asyncMes)
}
},
}
</script>
Родительский компонент запускает синхронные и асинхронные методы соответственно для отправки информации дочернему компоненту. использоватьcomputedпринятьvuexсерединаstate.
Подсборка
<template>
<div class="son" >
<div> 父组件对我说:{{ fatherMes }} </div>
<div> 父组件对我说(异步):{{ fatherMesAsync }} </div>
<input v-model="mes" /> <button @click="send" >对父组件说</button>
</div>
</template>
<script>
export default {
name:'son',
data(){
return {
mes:'',
}
},
computed:{
/* 接受父组件同步消息 */
fatherMes(){
return this.$store.state.fatherMes
},
/* 接受父组件异步消息 */
fatherMesAsync(){
return this.$store.state.fatherMesAsync
}
},
methods:{
/* 向父组件发送信息 */
send(){
this.$store.commit('saySon',this.mes)
},
},
}
</script>
Метод дочернего компонента такой же, как и у родительского компонента.
Эффект
2 преимущества
1 Принципиально решить проблему связи сложных компонентов
vuexрешена в определенной степениvueВ случае сложной связи компонентов нас больше не интересует связь между двумя несвязанными компонентами.
2 Поддержка асинхронной связи компонентов
vuexсерединаactionsпозволяет нам выполнять некоторые асинхронные операции, а затем передаватьcommitданные могут быть переданы в соответствующийmutation, что касаетсяactionsПочему можно выполнять асинхронно, ведь нижний слой проходит черезPromise.resolveВозможность получить статус асинхронного завершения задачи.
3 Недостатки
1 Процесс немного сложнее
vuexПо сравнению с другими методами, метод связи более сложен, и если разные модули, необходимо установить независимыеmodules.
4 сценария применения
В реальных сценариях развития не будетdemoПроецируйте такое простое общение,vuexПоявление этого заключается в решении этих более сложных сценариев связи компонентов. Для средних и крупных проектов,vuexЭто очень хорошая схема управления состоянием и передачи данных.
Пять шин событий Одна шина событий
EventBusавтобус событий,EventBusВсе события отправляются единообразно, существует единый центр управления событиями, один компонент связывает события, другой компонент инициирует события, взаимодействие всех компонентов больше не ограничивается родительскими и дочерними компонентами, а странице нужны данные, связываются события, а затем используется данные Провайдер инициирует соответствующее событие для предоставления данных Этот сценарий связи используется не только вvue, а также относится кreact.
EventBusОсновная идея — привязка и срабатывание событий, то же самое, что и в vue.this.$emitиthis.$onто же самое, это всеEventBusсмысл. Далее мы сосредоточимся на анализе этого процесса.
1 Основное использование
EventBus
export default class EventBus {
es = {}
/* 绑定事件 */
on(eventName, cb) {
if (!this.es[eventName]) {
this.es[eventName] = []
}
this.es[eventName].push({
cb
})
}
/* 触发事件 */
emit(eventName, ...params) {
const listeners = this.es[eventName] || []
let l = listeners.length
for (let i = 0; i < l; i++) {
const { cb } = listeners[i]
cb.apply(this, params)
}
}
}
export default new EventBus()
Это простая шина событий сon,emitдва метода.
родительский компонент
<template>
<div class="father" >
<input v-model="mes" /> <button @click="send" >对子组件说</button>
<div>子组件对我说:{{ sonMes }}</div>
<son />
<brotherSon />
</div>
</template>
<script>
import son from './son'
import brotherSon from './brother'
import EventBus from './eventBus'
export default {
name:'father',
components:{
son ,/* 子组件 */
brotherSon, /* 子组件 */
},
data(){
return {
mes:'',
sonMes:''/* 发送给子组件的信息 */
}
},
mounted(){
/* 绑定事件 */
EventBus.on('sonSay',this.sonSay)
},
methods:{
/* 传递给子组件 */
send(){
EventBus.emit('fatherSay',this.mes)
},
/* 接受子组件信息 */
sonSay(value){
this.sonMes = value
},
},
}
</script>
При инициализации мы передаемEventBusизonпривязка методаsonSayМетоды предоставляются для использования дочерними компонентами. При передаче информации дочерним компонентам передайтеemitЗапустите метод привязки дочерних компонентов, чтобы реализовать взаимодействие родитель-потомок.
Далее мы рассмотрим подкомпоненты.
Подсборка
<template>
<div class="son" >
<div> 父组件对我说:{{ fatherMes }} </div>
<input v-model="mes" /> <button @click="send" >对父组件说</button>
<div>
<input v-model="brotherMes" /> <button @click="sendBrother" >对兄弟组件说</button>
</div>
</div>
</template>
<script>
import EventBus from './eventBus'
export default {
name:'son',
data(){
return {
mes:'',
brotherMes:'',
fatherMes:''
}
},
mounted(){
/* 绑定事件 */
EventBus.on('fatherSay',this.fatherSay)
},
methods:{
/* 向父组件传递信息 */
send(){
EventBus.emit('sonSay',this.mes)
},
/* 向兄弟组件传递信息 */
sendBrother(){
EventBus.emit('brotherSay',this.brotherMes)
},
/* 父组件对我说 */
fatherSay(value){
this.fatherMes = value
}
},
}
</script>
Аналогично логике родительского компонента метод, которому необходимо получить данные, передается черезEventBusПривязка передает информацию наружу, вызывая метод eventBus. Также мы смоделировали сценарий общения между братьями. Мы создаем родственный компонент.
<template>
<div class="son" > 兄弟组件对我说: {{ brotherMes }} </div>
</template>
<script>
import EventBus from './eventBus'
export default {
/* */
name:'brother',
data(){
return {
brotherMes:''
}
},
mounted(){
/* 绑定事件给兄弟组件 */
EventBus.on('brotherSay',this.brotherSay)
},
methods:{
brotherSay(value){
this.brotherMes = value
}
}
}
</script>
Как мы видим, нет никакой разницы между родственными компонентами, обрабатывающими логику, и родительским и дочерним.
Эффект
2 преимущества
1 Простое и гибкое общение отца, сына и брата не ограничено.
Метод связи eventBus проще, чем предыдущие, и на него не влияет уровень компонентов, и он может реализовать связь любых двух компонентов. Передать данныеonПривязать, передать данныеemitкурок.
2 Способ связи не зависит от фреймворка
Способ связи eventBus доступен не только для vue, но и для реагирования и небольших программ, и автор считает, что этот способ связи больше подходит для связи небольших программ, почему он появится позже.
4 Недостатки
1 Техническое обслуживание сложно, и легко вызвать проблемы с цепью
Если мы примем режим связи шины событий, так как все события сильно централизованы и управляются унифицированным образом, ошибка в одном звене в середине вызовет катастрофу, которая повлияет на все тело. тоже очень сложно.
2 Требуется тщательная спецификация команды
Реальный сценарий приложения намного сложнее демонстрационного сценария. В реальном сценарии будет бесчисленное количество пар компонентов «родитель-потомок» и бесчисленное количество пар одноуровневых компонентов. Мы не можем называть каждое событие одним и тем же именем, поэтомуeventBusИменование событий привязки должно быть строго стандартизировано, и нельзя использовать повторяющиеся имена или неправильные имена.
3 не способствует развитию компонентов
eventBusКоммуникационный метод не может использоваться для эффективной разработки компонентов, допустим, на странице в сценарии есть несколько публичных компонентов, нам нужно передать данные только одному из них, но каждый публичный компонент связан с методом получения данных. Как передать данные нужным компонентам?
4 сценария применения
Этот способ реализации шины больше подходит для апплета WeChat и апплета, созданного на основе Vue.Что касается почему, потому что мы все знаем, что апплет использует двухпоточную модель (слой рендеринга + логический уровень) (как показано на рисунке ниже). , слой рендеринга Это небольшая программаwxmlРендеринг в поле нашего зрения, а уровень логики — это логика кода, которую мы написали.Что касается производительности, нам нужно знать, что производительность, потерянная на уровне рендеринга, намного больше, чем накладные расходы производительности выполнения кода на уровне логики.propsВ других методах передачи свойства связаны в теге апплета, поэтому необходимо повторно визуализировать слой представления. Если структура страницы сложная, это может вызвать заикание и т. д., поэтому мы пропускаемeventBusУровень рендеринга можно обойти, а данные могут передаваться непосредственно логическим уровнем, что снижает нагрузку на производительность.
Шесть автобусов событий, два новых Vue
new Vueэтот способ связи иeventBusпримерно так же, с той разницей, чтоvueпример какeventBusцентр, за исключением того, что мы можем использовать$on,$emitКроме того, мы также можем использовать vue подdata,watchи т. д. метод, и мы строим несколько несколькихvue, в качестве моста передачи данных для разных модулей, по сравнению с вышеприведеннымEventBusметод,new VueЭтот метод более эффективен и подходит дляvueСцена проекта. Давайте посмотрим вниз.
1 Основное использование
VueBus
import Vue from 'vue'
export default new Vue()
родительский компонент
<template>
<div class="father" >
<input v-model="mes" /> <button @click="send" >对子组件说</button>
<div>子组件对我说:{{ sonMes }}</div>
<son />
</div>
</template>
<script>
import son from './son'
import VueBus from './vueBus'
export default {
/* 父组件 */
name:'father',
components:{
son ,/* 子组件 */
},
data(){
return {
mes:'',
sonMes:'' /* 发送给子组件的信息 */
}
},
created(){
/* 绑定属性 */
VueBus._data.mes = 'hello,world'
},
mounted(){
/* 绑定事件 */
VueBus.$on('sonSay',this.sonSay)
},
methods:{
/* 传递给子组件 */
send(){
VueBus.$emit('fatherSay',this.mes)
},
/* 接受子组件信息 */
sonSay(value){
this.sonMes = value
},
},
}
</script>
мы проходим$onПривязывается метод приема данных, а данные привязываются к vue_data при инициализации.
Подсборка
<template>
<div class="son" >
<div> 父组件对我说:{{ fatherMes }} </div>
<input v-model="mes" /> <button @click="send" >对父组件说</button><br/>
<button @click="getFatherMes" >获取数据</button>
</div>
</template>
<script>
import VueBus from './vueBus'
export default {
name:'son',
data(){
return {
mes:'',
brotherMes:'',
fatherMes:''
}
},
mounted(){
/* 绑定事件 */
VueBus.$on('fatherSay',this.fatherSay)
},
methods:{
/* 向父组件传递信息 */
send(){
VueBus.$emit('sonSay',this.mes)
},
/* 父组件对我说 */
fatherSay(value){
this.fatherMes = value
},
/* 获取父组件存入vue中的数据 */
getFatherMes(){
console.log( VueBus._data.mes )
}
},
}
</script>
иeventBusКак и шина событий, мы также можем напрямую передать_dataДанные попадают непосредственно в содержимое, переданное родительским компонентом.
Эффект
2 преимущества
1 Простая и гибкая связь между любыми компонентами.
и вышеeventBusКак и метод связи, этот метод связи очень гибок и может легко взаимодействовать между любыми компонентами.
2 В дополнение к связи также можно использоватьwatch , computedи т.д. метод
Если мы используем vue в качестве средства связи, то используйте только$emitи$onЭто действительно немного перебор, так как есть примерvue, мы можем легко использовать vue$watch computedи другие функции.
3 Недостатки
в основномEventBusНедостатки это всеvueТакой вид связи существует.
4 сценария применения
В проекте не учтеноvuexмалых и средних проектов, рассмотреть возможность принятияvueПри использовании метода связи шины событий мы должны обращать внимание на пространство имен и не привязывать повторно имя события. Четко различайте бизнес-модули, чтобы избежать последующих сложностей с обслуживанием.
написать на обороте
мы пишемvueВ проекте конкретный метод связи, который будет использоваться, зависит от конкретного бизнес-сценария, размера проекта и других факторов. В статье представлены преимущества и недостатки метода связи Vue, который может служить ориентиром для вашей реальной работы.
Я смотрел в свободное времяvue2.0иvue3.0Исходный код, есть несколько статей по исходному коду версии 3.0, которые будут постоянно обновляться одна за другой Заинтересованные студенты могут щелкнуть, чтобы прочитать напрямую
VUE3.0 Отзывчивый принцип (Super Deland)
Всесторонний анализ алгоритма сравнения vue3.0
Просмотр Vue3.0 и вычисленный анализ исходного кода (пример диаграммы)
В конце концов, если вы считаете, что это неплохо, ставьте лайк + следите за волной и продолжайте делиться техническими статьями.
Общедоступный номер: Front-end Sharing
Спасибо за просмотр 🙏🙏🙏~~~