1、父傳子
傳遞:當子組件中在父組件中當做標簽使用的時候,給子組件綁定一個自定義屬性,值為需要傳遞的數據
接收:在子組件內部通過props進行接收,props接收的方式有2種:
①通過數組進行接收 props:["屬性"]
②通過對象進行接收 props:{
屬性:{
(1)type:限制數據的類型
(2)default:默認值
(3)required:布爾值,和default二選一
}
}
步驟:
①在父組件中給子組件標簽上添加自定義屬性:
<son :custom="100"></son>
②子組件中通過props接收:
props:["custom"]
③接收到的custom可以直接在標簽中使用 {{custom}}
注意:今后只要看到props就要想到這個屬性是用來接收外部數據的。
2、子傳父
①接收:當子組件在父組件中當做標簽使用的時候,給當前子組件綁定一個自定義事件,值為需要接收值的函數,這個函數不允許加 ()
②傳遞的過程:在子組件內部通過this.$emit("自定義事件名稱",需要傳遞的參數)來進行數據的傳遞
步驟:
①父組件中給需要接收參數的子組件綁定自定義事件,值為需要接收值的函數:
<son @handler="handlerMsg"></son>
methods:{
handlerMsg(value){
console.log(value)// 這個值是通過this.$emit()觸發傳來的
}
}
②子組件中觸發自定義事件:
this.$emit("handler",100);
3、非父子傳遞
第一種方法:通過給vue原型上添加一個公共的vue實例對象(vue實例對象上有$on()和$emit()),需要傳遞的一方調用$emit(),需要接收的一方調用$on()。
步驟:
①main.js中:
Vue.prototype.$observer=new Vue();
②需要傳遞的組件中:
this.$observer.$emit("handler",100);
③需要接收的組件中:
this.$observer.$on("handler",(value)=>{
console.log(value)
});
注意:在掛載前(created)進行$on()綁定,先綁定好,再觸發。
*第二種方法:手動封裝事件訂閱observer
步驟:
①src下新建observer.js:
const eventList={}; const $on=function (eventName,callback) { if(!eventList[eventName]){ eventList[eventName]=[]; } eventList[eventName].push(callback); } const $emit=function(eventName,params){ if(eventList[eventName]){ let arr=eventList[eventName]; arr.forEach((cb)=>{ cb(params); }); } } const $off=function(eventName,callback){ if(eventList[eventName]){ if(callback){ let index=eventList[eventName].indexOf(callback); eventList[eventName].splice(index,1); }else{ eventList[eventName].length=0; } } } export default{ $on, $emit, $off }
②main.js中用手動封裝的observer替代new Vue()
import observer from "./observer.js";
Vue.prototype.$observer=observer;
③在需要傳遞的組件中用this.$observer.$emit()觸發自定義事件:
this.$observer.$emit("customHandler","需要傳遞的值");
④在需要接收的組件中用this.$observer.$on()綁定自定義事件:
this.$observer.$on("customHandler",this.toggle);
第三種方法:事件總線(Eventbus)
步驟:
①先創建一個空實例:
let bus=new Vue();
②通過bus.$on()綁定自定義事件:
bus.$on("customHandler",要觸發的函數);
③通過bus.$emit()來觸發自定義事件:
bus.$emit("customHandler");
*第四種方法:vuex(后續)
注:如果是親兄弟:(父傳子和子傳父)
步驟:
①父組件中聲明data數據 state:true ,將state通過props傳給其中一個子組件:
<two :show="state"></two>
props:show
此時show的值隨着state的變化而變化
②再通過另一個子組件去改變父組件的state:
標簽上綁定自定義事件:
<one @customHandler="toggle"></one>
再在子組件內部通過$emit()觸發customHandler事件:
this.$emit("customHandler");
provide / inject(提供/注入)跨組件傳值,其實就是父傳子
provide / inject:依賴注入。可以實現跨組件傳值,數據的流向只能是向下傳遞,就是大范圍有效的props
provide:這個配置項必須要在父級進行使用,用來定義后代組件所需要的一些屬性和方法。
語法:
provide:{
}
// 推薦
provide(){ return{ } }
inject:這個配置項必須在后代組件中使用,用來獲取根組件定義的跨組件傳值的數據。
語法:
inject:[]
// 推薦
inject:{ key:{ from:"父組件名稱", default:默認值 } }
插槽 slot
作用:默認情況下組件內部包裹的內容是不會顯示的,如果需要進行顯示則需要通過插槽來進行顯示。
1、匿名插槽:沒有名字的插槽(v-slot:default)
v-slot
在組件內部通過<slot></slot>進行接收
步驟:
①App.vue中在組件標簽中添加template標簽(里面可以寫多個標簽),寫上v-slot屬性
<Header>
<template v-slot>
<p>111</p>
<p>222</p>
</template>
</Header>
②在Header.vue組件中通過<slot></slot>開辟一塊空間:
<div class="header">
<slot></slot>
</div>
2、命名插槽:有名字的插槽
v-slot:slotName
在組件內部通過<slot name="slotName"></slot>來進行接收
步驟:
①給插槽指令加上名字:
<template v-slot:slotName>
<p>111</p>
</template>
②slot標簽添加name屬性:
<div class="header">
<slot name="slotName"></slot>
</div>
如果還有匿名插槽template,就在Header.vue中用<slot></slot>再開辟一塊空間接收匿名插槽。
3、插槽作用域:(子傳父)
v-slot:slotName(名字可寫可不寫,如果不寫默認是default)="變量(這個變量是一個對象)"
作用:讓組件來提供自身需要顯示的內容
步驟:
①App.vue中template中設置v-slot="props"(props是一個對象):---------父
<template v-slot="props">
<h2>{{props.info}}</h2>
</template>
②Header.vue中slot標簽綁定自定義屬性info:----------子,info屬性的值提供給父組件中的props.info
<div class="header">
<slot :info="'111'"></slot>
</div>
③在template中可以通過props.info拿到子組件中傳來的值
如果要用命名插槽:
App.vue:直接在v-slot后面加上 :slotName
Header.vue:<slot name="slotName" :info="'111'"></slot>