1.組件間通信基本原則
1) 不要在子組件中直接修改父組件的狀態(tài)數(shù)據(jù)
2) 數(shù)據(jù)在哪, 更新數(shù)據(jù)的行為(函數(shù))就應(yīng)該定義在哪
2.vue 組件間通信方式
1) props
2) vue 的自定義事件
3) 消息訂閱與發(fā)布(如: pubsub 庫(kù))
4) slot
5) vuex(后面單獨(dú)講)
2.1組件間通信 1: props(適用于父子組件傳遞屬性)
step1:父組件
<my-component name='tom' :age='30' :setName='setName'></my-component>
step2:子組件
在組件內(nèi)聲明所有的 props
方法1:只指定名稱
props: ['name', 'age', 'setName']
方式2: 指定名稱和類型
props: {
name: String,
age: Number,
setNmae: Function
}
方式3: 指定名稱/類型/必要性/默認(rèn)值
props: {
name: {type: String, required: true, default:xxx},
}
注意
- 此方式用于父組件向子組件傳遞數(shù)據(jù)
- 所有標(biāo)簽屬性都會(huì)成為組件對(duì)象的屬性, 模板頁(yè)面可以直接引用
- 問(wèn)題:
a. 如果需要向非直接子后代傳遞數(shù)據(jù)必須多層逐層傳遞
b. 兄弟組件間也不能直接 props 通信, 必須借助父組件才可以
2.2組件間通信 2: vue 自定義事件(適用于父子組件傳遞函數(shù),代替props)
step1:父組件中自定義事件
<TodoHeader @addTodo="addTodo"/><!-- 給TodoHeader組件綁定addTodo的事件監(jiān)聽(tīng) -->
step2:子組件中觸發(fā)事件
this.$emit('addTodo', todo) // 此處todo是需要的數(shù)據(jù),可以來(lái)自子組件
注意
- 此方式只用于子組件向父組件發(fā)送消息(數(shù)據(jù))
- 問(wèn)題: 隔代組件或兄弟組件間通信此種方式不合適
2.3組件間通信 3: 消息訂閱與發(fā)布(PubSubJS 庫(kù))
查看是否已經(jīng)存在該庫(kù):
npm info pubsub-js
若不存在,則先安裝
npm install pubsub-js
step1:導(dǎo)入pubsub-js
import PubSub from 'pubsub-js'
發(fā)布消息
PubSub.publish('deleteTodo', index)
step2:導(dǎo)入pubsub-js
import PubSub from 'pubsub-js'
訂閱消息
PubSub.subscribe('deleteTodo', (msg, index) => {
this.deleteTodo(index) // 此處deleteTodo是本組件定義的方法
})
注意
優(yōu)點(diǎn): 此方式可實(shí)現(xiàn)任意關(guān)系組件間通信(數(shù)據(jù))
事件的 2 個(gè)重要操作(總結(jié))
1) 綁定事件監(jiān)聽(tīng) (訂閱消息)
目標(biāo): 標(biāo)簽元素 <button>
事件名(類型): click/focus
回調(diào)函數(shù): function(event){}
2) 觸發(fā)事件 (發(fā)布消息)
DOM 事件: 用戶在瀏覽器上對(duì)應(yīng)的界面上做對(duì)應(yīng)的操作
自定義: 編碼手動(dòng)觸發(fā)
2.4組件間通信 4: slot
此方式用于父組件向子組件傳遞標(biāo)簽數(shù)據(jù)
step1:子組件
<template>
<div>
<slot name="xxx">不確定的標(biāo)簽結(jié)構(gòu) 1</slot>
<div>組件確定的標(biāo)簽結(jié)構(gòu)</div>
<slot name="yyy">不確定的標(biāo)簽結(jié)構(gòu) 2</slot>
</div>
</template>
step2:父組件
<child>
<div slot="xxx">xxx 對(duì)應(yīng)的標(biāo)簽結(jié)構(gòu)</div>
<div slot="yyy">yyyy 對(duì)應(yīng)的標(biāo)簽結(jié)構(gòu)</div>
</child>