vue組件通訊

vue組件通訊分爲橫向和縱向。html

**縱向**vue

1. props 和 $emitnode

props:接收來自父組件的數據app

$emit:觸發事件ide

<!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 觸發,參數爲 事件名,參數
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>
子組件向父組件傳值
一、自定義事件
二、子組件原生事件
三、原生事件的處理函數中經過$emit觸發自定義事件
注:子組件不能修改props中的值,不然報錯,可經過子組件本身的數據接收props中的值來解決
</pre>
</body>
</html>

2. $parent 和 $children函數

後代組件能夠經過$parent.$parent.$parent這種形式跨級通訊ui

父組件能夠經過$children[0].$children[0]這種形式跨級通訊,若是有多個子組件,索引很差控制this

<!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 style="color: red;">{{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 style="color: red;">{{parentMsg}}</p>                   
                    <p style="color: red;">{{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 style="color: red;">{{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
非響應式,若是有多個直接子組件
</pre>
</body>
</html>

3. $attrs 和 $listenersspa

後代組件從$attrs獲取父組件傳給後代組件的數據component

後代組件經過$emit觸發$listeners的事件將數據傳給父組件

<!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只能觸發其父級的事件
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>
一、$attrs收集屬性
二、$listeners收集事件
</pre>
</body>
</html>

4. provide 和 inject

父組件向後代組件單向傳遞數據

<!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綁定並非可響應的, 因此msg的變化不會影響後代組件中已經接收到的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 style="color: red;">{{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 style="color: red;">{{parentMsg}}</p> 
                    <p style="color: red;">{{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. 數據總線 

用一箇中間變量保存數據

  • var bus = new Vue() 

   $on綁定事件

   $emit觸發事件

<!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>
相關文章
相關標籤/搜索