溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

vue組件通信

發(fā)布時(shí)間:2020-07-29 18:31:05 來源:網(wǎng)絡(luò) 閱讀:395 作者:yum123 欄目:開發(fā)技術(shù)

vue組件通信分為橫向和縱向。

**縱向**

1. props 和 $emit

props:接收來自父組件的數(shù)據(jù)

$emit:觸發(fā)事件

<!DOCTYPE?html>
<html?lang="en">
<head>
<meta?charset="UTF-8">
<meta?name="viewport"?content="width=device-width,?initial-scale=1.0">
<meta?http-equiv="X-UA-Compatible"?content="ie=edge">
<title>Document</title>
</head>
<body>
<div?id="app">

</div>
<script?src="./node_modules/vue/dist/vue.js"></script>
<script>
//?全局組件
Vue.component('Parent',?{
data(){
return?{
msg:?'I?am?the?data?of?Parent!',
childToParentData:?'I?am?the?data?of?Parent!',
};
},
template:?`<div>
????????????????????<p>?I?am?the?parent?component!</p>

????????????????????<Child?:childData="msg"?@childHandler="handerFn"/>

????????????????????<p>childToParentData:?{{childToParentData}}</p>
????????????????</div>`,
methods:?{
handerFn(val){
console.log(val);
this.childToParentData?=?val;
},
}
})

Vue.component('Child',?{
data(){
return?{
msg:?'I?am?the?data?of?Child!',
inputVal:?this.childData,
};
},
props:?['childData'],
template:?`<div>
????????????????????<p>?I?am?the?child?component!</p>
????????????????????<p>{{msg}}</p>
????????????????????<input?v-model="inputVal"?@input="changeVal(inputVal)"?/>
????????????????</div>`,
methods:?{
changeVal(val){
//?通過?$emit?觸發(fā),參數(shù)為?事件名,參數(shù)
this.$emit('childHandler',?val);
}
}
})
var?App?=?{
template:?`<div>
????????????????????<Parent?/>
????????????????</div>`,
};
var?vm?=?new?Vue({
el:?'#app',
data(){
return?{
};
},
components:?{
App
},
methods:?{

},
template:?`
????????????<App?/>
????????????`
})
</script>
<pre>
子組件向父組件傳值
1、自定義事件
2、子組件原生事件
3、原生事件的處理函數(shù)中通過$emit觸發(fā)自定義事件
注:子組件不能修改props中的值,否則報(bào)錯(cuò),可通過子組件自己的數(shù)據(jù)接收props中的值來解決
</pre>
</body>
</html>

2. $parent 和 $children

后代組件可以通過$parent.$parent.$parent這種形式跨級(jí)通信

父組件可以通過$children[0].$children[0]這種形式跨級(jí)通信,如果有多個(gè)子組件,索引不好控制

<!DOCTYPE?html>
<html?lang="en">
<head>
<meta?charset="UTF-8">
<meta?name="viewport"?content="width=device-width,?initial-scale=1.0">
<meta?http-equiv="X-UA-Compatible"?content="ie=edge">
<title>Document</title>
</head>
<body>
<div?id="app">

</div>
<script?src="./node_modules/vue/dist/vue.js"></script>
<script>
//?全局組件
Vue.component('Parent',?{
data(){
return?{
msg:?'I?am?the?data?of?Parent!',
grandToParent:?'',
};
},
template:?`<div>
????????????????????<p>?I?am?the?parent?component!</p>
????????????????????<input?v-model="msg"?@input="consoleFn"/>?
????????????????????<p?>{{grandToParent}}</p>?????????????????????
????????????????????<hr?/>
????????????????????<Child/>
????????????????</div>`,
methods:?{
consoleFn(){
this.$children[0].parentMsg?=?this.msg;
},
},
})

Vue.component('Child',?{
data(){
return?{
msg:?'I?am?the?data?of?Child!',
parentMsg:?'',
grandToChild:?'',
};
},
template:?`<div>
????????????????????<p>?I?am?the?child?component!</p>
????????????????????<p>{{msg}}</p>
????????????????????<button?@click="consoleFn">attr</button>?
????????????????????<p?>{{parentMsg}}</p>???????????????????
????????????????????<p?>{{grandToChild}}</p>???????????????????
????????????????????<hr?/>
????????????????????<GrandChild?/>
????????????????</div>`,
methods:?{
consoleFn(){
this.$children[0].childMsg?=?this.msg;
},
},
})

Vue.component('GrandChild',?{
data(){
return?{
msg:?'I?am?the?data?of?GrandChild!',
childMsg:?'',
};
},
template:?`<div>
????????????????????<p>?I?am?the?GrandChild?component!</p>
????????????????????<p>{{msg}}</p>
????????????????????<button?@click="consoleFn"?>attr</button>
????????????????????<p?>{{childMsg}}</p>?
????????????????????<hr?/>
????????????????</div>`,
methods:?{
consoleFn(){
this.$parent.grandToChild?=?this.msg;
this.$parent.$parent.grandToParent?=?this.msg;
},
},
})
var?App?=?{
template:?`<div>
????????????????????<Parent?/>
????????????????</div>`,
};
var?vm?=?new?Vue({
el:?'#app',
data(){
return?{
};
},
components:?{
App
},
methods:?{

},
template:?`
????????????<App?/>
????????????`
})
</script>
<pre>
$parent,?$children,?$root,?$parent.$parent
非響應(yīng)式,如果有多個(gè)直接子組件
</pre>
</body>
</html>

3. $attrs 和 $listeners

后代組件從$attrs獲取父組件傳給后代組件的數(shù)據(jù)

后代組件通過$emit觸發(fā)$listeners的事件將數(shù)據(jù)傳給父組件

<!DOCTYPE?html>
<html?lang="en">
<head>
<meta?charset="UTF-8">
<meta?name="viewport"?content="width=device-width,?initial-scale=1.0">
<meta?http-equiv="X-UA-Compatible"?content="ie=edge">
<title>Document</title>
</head>
<body>
<div?id="app">

</div>
<script?src="./node_modules/vue/dist/vue.js"></script>
<script>
//?全局組件
Vue.component('Parent',?{
data(){
return?{
msg:?'I?am?the?data?of?Parent!',
childToParentData:?'I?am?the?data?of?Parent!',
};
},
template:?`<div>
????????????????????<p>?I?am?the?parent?component!</p>
????????????????????<p>childToParentData:?{{childToParentData}}</p>
????????????????????<button?@click="consoleFn">attr</button>
????????????????????<br?/>
????????????????????<Child?:parentMsg="msg"?@childClick="parentHandler"?v-bind="$attrs"?v-on="$listeners"/>
????????????????</div>`,
//?inheritAttr:?false,
methods:?{
consoleFn(){
console.log(this.$attrs);??//?{}
console.log(this.$listeners);??//?{}
},
parentHandler(data){
console.log(data);
},
},
})

Vue.component('Child',?{
data(){
return?{
msg:?'I?am?the?data?of?Child!',
};
},
template:?`<div>
????????????????????<p>?I?am?the?child?component!</p>
????????????????????<p>{{msg}}</p>
????????????????????<button?@click="consoleFn">attr</button>????????????????????
????????????????????<br?/>
????????????????????<GrandChild?:childMsg="msg"?@grandChildClick="childHandler"?v-bind="$attrs"?v-on="$listeners"/>
????????????????</div>`,
//?inheritAttr:?false,
methods:?{
consoleFn(){
console.log(this.$attrs);??//?{parentMsg:?}
console.log(this.$listeners);??//{childClick:?}
},
childHandler(data){
console.log(data);
},
},
})

Vue.component('GrandChild',?{
data(){
return?{
msg:?'I?am?the?data?of?GrandChild!',
};
},
template:?`<div>
????????????????????<p>?I?am?the?GrandChild?component!</p>
????????????????????<p>{{msg}}</p>
????????????????????<button?@click="consoleFn"?>attr</button>
????????????????????<br?/>
????????????????</div>`,
//?inheritAttr:?false,
methods:?{
consoleFn(){
console.log(this.$attrs);??//?{parentMsg:?,?childMsg:?}
console.log(this.$listeners);???//{childClick:?,?grandChildClick:?}

this.$emit('childClick',?this.msg);??//?如果不收集,$emit只能觸發(fā)其父級(jí)的事件
this.$emit('grandChildClick',?this.msg);?
},
},
})
var?App?=?{
template:?`<div>
????????????????????<Parent?/>
????????????????</div>`,
};
var?vm?=?new?Vue({
el:?'#app',
data(){
return?{
};
},
components:?{
App
},
methods:?{

},
template:?`
????????????<App?/>
????????????`
})
</script>
<pre>
1、$attrs收集屬性
2、$listeners收集事件
</pre>
</body>
</html>

4. provide 和 inject

父組件向后代組件單向傳遞數(shù)據(jù)

<!DOCTYPE?html>
<html?lang="en">
<head>
<meta?charset="UTF-8">
<meta?name="viewport"?content="width=device-width,?initial-scale=1.0">
<meta?http-equiv="X-UA-Compatible"?content="ie=edge">
<title>Document</title>
</head>
<body>
<div?id="app">

</div>
<script?src="./node_modules/vue/dist/vue.js"></script>
<script>
//?全局組件
Vue.component('Parent',?{
data(){
return?{
msg:?'I?am?the?data?of?Parent!',
};
},
provide(){
return?{
parentMsg:?this.msg,
};
},
template:?`<div>
????????????????????<p>?I?am?the?parent?component!</p>
????????????????????<input?v-model="msg"/>??<!--?provide和inject綁定并不是可響應(yīng)的,?所以msg的變化不會(huì)影響后代組件中已經(jīng)接收到的msg的值?-->
????????????????????<button?@click="consoleFn">attr</button>
????????????????????<hr?/>
????????????????????<Child/>
????????????????</div>`,
methods:?{
consoleFn(){
console.log(this);
},
},
})

Vue.component('Child',?{
data(){
return?{
msg:?'I?am?the?data?of?Child!',
};
},
provide:?{
childMsg:?'I?am?the?data?of?Child!',
},
inject:?['parentMsg'],
template:?`<div>
????????????????????<p>?I?am?the?child?component!</p>
????????????????????<p>{{msg}}</p>
????????????????????<button?@click="consoleFn">attr</button>?
????????????????????<p?>{{parentMsg}}</p>???????????????????
????????????????????<hr?/>
????????????????????<GrandChild?/>
????????????????</div>`,
methods:?{
consoleFn(){
console.log(this);
},
},
})

Vue.component('GrandChild',?{
data(){
return?{
msg:?'I?am?the?data?of?GrandChild!',
};
},
inject:?['parentMsg',?'childMsg'],
template:?`<div>
????????????????????<p>?I?am?the?GrandChild?component!</p>
????????????????????<p>{{msg}}</p>
????????????????????<button?@click="consoleFn"?>attr</button>
????????????????????<p?>{{parentMsg}}</p>?
????????????????????<p?>{{childMsg}}</p>?
????????????????????<hr?/>
????????????????</div>`,
methods:?{
consoleFn(){
console.log(this);
},
},
})
var?App?=?{
template:?`<div>
????????????????????<Parent?/>
????????????????</div>`,
};
var?vm?=?new?Vue({
el:?'#app',
data(){
return?{
};
},
components:?{
App
},
methods:?{

},
template:?`
????????????<App?/>
????????????`
})
</script>
<pre>
單向
</pre>
</body>
</html>

**橫向**

1. 數(shù)據(jù)總線?

用一個(gè)中間變量保存數(shù)據(jù)

  • var bus = new Vue()?

? ?$on綁定事件

? ?$emit觸發(fā)事件

<!DOCTYPE?html>
<html?lang="en">
<head>
<meta?charset="UTF-8">
<meta?name="viewport"?content="width=device-width,?initial-scale=1.0">
<meta?http-equiv="X-UA-Compatible"?content="ie=edge">
<title>Document</title>
</head>
<body>
<div?id="app">

</div>
<script?src="./node_modules/vue/dist/vue.js"></script>
<script>
var?bus?=?new?Vue();

//?全局組件
Vue.component('Parent',?{
data(){
return?{
msg:?'I?am?the?data?of?Parent!',
};
},
template:?`<div>
????????????????????<p>?I?am?the?parent?component!</p>
????????????????????<button?@click="consoleFn">button</button>
????????????????????<br?/>
????????????????????<BrotherOne?/>
????????????????????<BrotherTwo?/>
????????????????</div>`,
methods:?{
consoleFn(){
console.log(bus);
},
},
})

Vue.component('BrotherOne',?{
data(){
return?{
msg:?'I?am?the?data?of?BrotherOne!',
fromBrother:?'',
};
},
template:?`<div>
????????????????????<p>?I?am?the?BrotherOne?component!</p>
????????????????????<p>{{msg}}</p>
????????????????????<input?v-model="fromBrother"?@input="transformData"/>???????????????????
????????????????????<br?/>
????????????????</div>`,
methods:?{
transformData(){
bus.$emit('globalBus',?this.fromBrother);
},
},
})

Vue.component('BrotherTwo',?{
data(){
return?{
msg:?'I?am?the?data?of?BrotherTwo!',
fromBrother:?'',
};
},
template:?`<div>
????????????????????<p>?I?am?the?BrotherTwo?component!</p>
????????????????????<p>{{msg}}</p>
????????????????????<p>fromBrother:?{{fromBrother}}</p>
????????????????????<button?@click="consoleFn"?>button</button>
????????????????????<br?/>
????????????????</div>`,
methods:?{
consoleFn(){
console.log(bus);
},
},
mounted(){
bus.$on('globalBus',?val?=>?{
this.fromBrother?=?val;
})
}
})
var?App?=?{
template:?`<div>
????????????????????<Parent?/>
????????????????</div>`,
};
var?vm?=?new?Vue({
el:?'#app',
data(){
return?{
};
},
components:?{
App
},
methods:?{

},
template:?`
????????????<App?/>
????????????`
})
</script>
</body>
</html>
  • var bus = {}

<!DOCTYPE?html>
<html?lang="en">
<head>
<meta?charset="UTF-8">
<meta?name="viewport"?content="width=device-width,?initial-scale=1.0">
<meta?http-equiv="X-UA-Compatible"?content="ie=edge">
<title>Document</title>
</head>
<body>
<div?id="app">

</div>
<script?src="./node_modules/vue/dist/vue.js"></script>
<script>
var?bus?=?{};

//?全局組件
Vue.component('Parent',?{
data(){
return?{
msg:?'I?am?the?data?of?Parent!',
};
},
template:?`<div>
????????????????????<p>?I?am?the?parent?component!</p>
????????????????????<button?@click="consoleFn">button</button>
????????????????????<br?/>
????????????????????<BrotherOne?/>
????????????????????<BrotherTwo?/>
????????????????</div>`,
methods:?{
consoleFn(){
console.log(bus);
},
},
})

Vue.component('BrotherOne',?{
data(){
return?{
msg:?'I?am?the?data?of?BrotherOne!',
fromBrother:?'',
};
},
template:?`<div>
????????????????????<p>?I?am?the?BrotherOne?component!</p>
????????????????????<p>{{msg}}</p>
????????????????????<input?v-model="fromBrother"?@input="transformData"/>???????????????????
????????????????????<br?/>
????????????????</div>`,
methods:?{
transformData(){
bus['brotherOne']?=?{
'fromBrother':?this.fromBrother,
};
},
},
})

Vue.component('BrotherTwo',?{
data(){
return?{
msg:?'I?am?the?data?of?BrotherTwo!',
fromBrother:?'',
};
},
template:?`<div>
????????????????????<p>?I?am?the?BrotherTwo?component!</p>
????????????????????<p>{{msg}}</p>
????????????????????<p>fromBrother:?{{fromBrother}}</p>
????????????????????<button?@click="consoleFn"?>button</button>
????????????????????<br?/>
????????????????</div>`,
methods:?{
consoleFn(){
this.fromBrother?=?bus['brotherOne']['fromBrother'];
},
},
})
var?App?=?{
template:?`<div>
????????????????????<Parent?/>
????????????????</div>`,
};
var?vm?=?new?Vue({
el:?'#app',
data(){
return?{
};
},
components:?{
App
},
methods:?{

},
template:?`
????????????<App?/>
????????????`
})
</script>
</body>
</html>


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI