猛獸總是獨(dú)行,牛羊才成群結(jié)隊(duì)芯勘。 -------魯迅
vue組件通信的重要性無需多言右冻。装蓬。。但是你肯定沒有全部掌握纱扭,所以這第二篇文章應(yīng)運(yùn)而生
props和$emit
props父傳子牍帚,$emit子傳父,看下邊代碼乳蛾,清澈的像少女的眼眸履羞。。屡久。emmm
Vue.component('child',{
data(){
return {
mymessage:this.message
}
},
template:`
<div>
<input type="text" v-model="mymessage"
@input="passData(mymessage)"> </div>
`,
props:['message'],//得到父組件傳遞過來的數(shù)據(jù)
methods:{
passData(val){
//觸發(fā)父組件中的事件
this.$emit('getChildData',val)
}
}
})
┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┅┄*
Vue.component('parent',{
template:`
<div>
<p>this is parent compoent!</p>
<child :message="message"
v-on:getChildData="getChildData"></child>
</div>
`,
data(){
return {
message:'張不慫'
}
},
methods:{
//執(zhí)行子組件觸發(fā)的事件
getChildData(val){
console.log(val)
}
}
})
┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┅┄*
// 掛載
var app=new Vue({
el:'#app',
template:`
<div>
<parent></parent>
</div>
`
})
復(fù)制代碼
中央事件總線new Bus
新建一個(gè)Vue事件bus對象忆首,然后通過bus.$emit
觸發(fā)事件,bus.$on
監(jiān)聽觸發(fā)的事件被环。
Vue.component('brother1',{
data(){
return {
mymessage:'hello brother1'
}
},
template:`
<div>
<p>this is brother1 compoent!</p>
<input type="text" v-model="mymessage"
@input="passData(mymessage)">
</div>
`,
methods:{
passData(val){
//觸發(fā)全局事件globalEvent
bus.$emit('globalEvent',val)
}
}
})
┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┅┄*
Vue.component('brother2',{
template:`
<div>
<p>this is brother2 compoent!</p>
<p>brother1傳遞過來的數(shù)據(jù):{{brothermessage}}</p>
</div>
`,
data(){
return {
mymessage:'hello brother2',
brothermessage:''
}
},
mounted(){
//綁定全局事件globalEvent
bus.$on('globalEvent',(val)=>{
this.brothermessage=val;
})
}
})
┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┅┄*
//中央事件總線
var bus=new Vue();
var app=new Vue({
el:'#app',
template:`
<div>
<brother1></brother1>
<brother2></brother2>
</div>
`
})
復(fù)制代碼
provide和inject
父組件中通過provider來提供變量糙及,然后在子組件中通過inject來注入變量。不論子組件有多深筛欢,只要調(diào)用了inject那么就可以注入provider中的數(shù)據(jù)浸锨。而不是局限于只能從當(dāng)前父組件的prop屬性來獲取數(shù)據(jù),只要在父組件的生命周期內(nèi)版姑,子組件都可以調(diào)用柱搜。
Vue.component('child',{
inject:['parent_var'],//得到父組件傳遞過來的數(shù)據(jù)
data(){
return {
mymessage:this.parent_var
}
},
template:`
<div>
{{ message }}
</div>
})
┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┅┄*
Vue.component('parent',{
template:`
<div>
<child></child>
</div>
`,
provide:{
// 看你想傳遞啥了,這里不寫固定的原因是為了防止限制大家的思維
/*
比如你可以把用戶登錄信息存儲在App.vue中剥险,可以把
provide:{app:this}注入聪蘸,后續(xù)所有組件通過inject:['app'],
就可以直接通過app.userInfo拿到用戶信息
*/
parent_var:'隨便什么都可以(可以是this,可以是data中的數(shù)據(jù))'
},
data(){
return {
message:'hello'
}
}
})
┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┅┄*
var app=new Vue({
el:'#app',
template:`
<div>
<parent></parent>
</div>
`
})
復(fù)制代碼
$attrs
和$listeners
還是多層的場景,App.vue-->A—>B,如果App直接想給B傳遞數(shù)據(jù)該怎么辦表制?Vue 2.4開始提供了[圖片上傳失敗...(image-17bd97-1613815451793)]
listeners來解決這個(gè)問題健爬,能夠讓組件App直接傳遞數(shù)據(jù)給組件B。我將代碼中關(guān)鍵點(diǎn)已經(jīng)標(biāo)注出么介, // ******關(guān)鍵點(diǎn)*****
app.vue引入A組件
<template>
<div id="app">
{{app}}
// ******關(guān)鍵點(diǎn)*****
<A :app="app" @test="doTest"/>
</div>
</template>
<script>
import A from "./components/A";
export default {
name: "App",
data() {
return {
app: "我是App的數(shù)據(jù)"
};
},
components: {
A
},
methods: {
doTest() {
console.log(this.app)
}
}
};
復(fù)制代碼
A.vue引入B組件
<template>
<div class="hello">
<h6>這里是A組件</h6>
<p>$attrs: {{$attrs}}</p>
<p>$listeners: {{$listeners}}</p>
// ******關(guān)鍵點(diǎn)***** v-bind傳遞的都是$attrs,v-on傳遞的都是$listeners
<B v-bind="$attrs" v-on="$listeners"/>
</div>
</template>
<script>
import B from "./B";
export default {
name: "A",
props: {
msg: String
},
components: { B },
mounted() {
console.log(this.$listeners);
}
};
</script>
復(fù)制代碼
B組件
<template>
<div class="hello">
<h6>這里是B組件</h6>
// ******關(guān)鍵點(diǎn)*****
<p>$attrs: {{$attrs}}</p>
</div>
</template>
<script>
export default {
name: "B",
props: {
msg: String
},
mounted() {
// ******關(guān)鍵點(diǎn)*****
// 為啥這里直接能emitApp組件傳遞的test呢娜遵?
// 因?yàn)樵贏組件中有一個(gè)關(guān)鍵操作是 <B v-bind="$attrs" v-on="$listeners"/>
this.$emit("test");
}
};
</script>
復(fù)制代碼
$parent
和$children
分別是獲得父組件和子組件的實(shí)例
Vue.component('child',{
props:{
value:String, //v-model會自動(dòng)傳遞一個(gè)字段為value的prop屬性
},
data(){
return {
mymessage:this.value
}
},
methods:{
changeValue(){
this.$parent.message = this.mymessage;//通過如此調(diào)用可以改變父組件的值
}
},
template:`
<div>
<input type="text" v-model="mymessage" @change="changeValue">
</div>
})
Vue.component('parent',{
template:`
<div>
<p>this is parent compoent!</p>
<button @click="changeChildValue">test</button >
<child></child>
</div>
`,
methods:{
changeChildValue(){
this.$children[0].mymessage = 'hello';
}
},
data(){
return {
message:'hello'
}
}
})
var app=new Vue({
el:'#app',
template:`
<div>
<parent></parent>
</div>
`
})
復(fù)制代碼
v-model
父組件通過v-model傳遞值給子組件時(shí),會自動(dòng)傳遞一個(gè)value的prop屬性壤短,在子組件中通過this.$emit(‘input’,val)自動(dòng)修改v-model綁定的值
Vue.component('child',{
props:{
value:String, //v-model會自動(dòng)傳遞一個(gè)字段為value的prop屬性
},
data(){
return {
mymessage:this.value
}
},
methods:{
changeValue(){
this.$emit('input',this.mymessage); //通過如此調(diào)用可以改變父組件上v-model綁定的值
}
},
template:`
<div>
<input type="text" v-model="mymessage" @change="changeValue">
</div>
})
Vue.component('parent',{
template:`
<div>
<p>this is parent compoent!</p>
<p>{{message}}</p>
<child v-model="message"></child>
</div>
`,
data(){
return {
message:'hello'
}
}
})
var app=new Vue({
el:'#app',
template:`
<div>
<parent></parent>
</div>
`
})
復(fù)制代碼
boradcast和dispatch
vue1.0中提供了這種方式设拟,但vue2.0中沒有慨仿,但很多開源軟件都自己封裝了這種方式,比如min ui纳胧、element ui, broadcast是向特定的父組件镰吆,觸發(fā)事件,dispatch是向特定的子組件觸發(fā)事件躲雅,本質(zhì)上這種方式還是使用遞歸對on和emit的封裝,但在一些基礎(chǔ)組件中卻很實(shí)用骡和。注意:所有組件的名稱不能重復(fù)O嗔蕖!慰于!
function broadcast(componentName, eventName, params) {
this.$children.forEach(child => {
var name = child.$options.componentName;
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params));
} else {
broadcast.apply(child, [componentName, eventName].concat(params));
}
});
}
function dispatch(componentName, eventName, params) {
var parent = this.$parent;
var name = parent.$options.componentName;
while (parent && (!name && name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.componentName;
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
}
export default {
methods: {
dispatch(componentName, eventName, params) {
dispatch.call(this, componentName, eventName, params);
},
broadcast(componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params);
}
}
};
復(fù)制代碼
vuex
對于vuex不再做過多的贅述钮科。。婆赠。
第二章非常全面的講解了vue炒雞重要的一個(gè)技能绵脯,組件通信,我說這一篇全面大家應(yīng)該沒意見吧休里?好了就這樣...
覺得對你有幫助蛆挫,不妨點(diǎn)個(gè)
贊
,后續(xù)持續(xù)輸出這種簡短有效的文章妙黍,幫助你用最短的時(shí)間內(nèi)掌握最多的內(nèi)容悴侵,畢竟誰不喜歡一勞永逸不是? ?(^_-) thank you ~