温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

vue组件通信

发布时间:2020-07-29 18:31:05 来源:网络 阅读:402 作者:yum123 栏目:开发技术

vue组件通信分为横向和纵向。

**纵向**

1. props 和 $emit

props:接收来自父组件的数据

$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>
// 全局组件
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>
子组件向父组件传值
1、自定义事件
2、子组件原生事件
3、原生事件的处理函数中通过$emit触发自定义事件
注:子组件不能修改props中的值,否则报错,可通过子组件自己的数据接收props中的值来解决
</pre>
</body>
</html>

2. $parent 和 $children

后代组件可以通过$parent.$parent.$parent这种形式跨级通信

父组件可以通过$children[0].$children[0]这种形式跨级通信,如果有多个子组件,索引不好控制

<!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
非响应式,如果有多个直接子组件
</pre>
</body>
</html>

3. $attrs 和 $listeners

后代组件从$attrs获取父组件传给后代组件的数据

后代组件通过$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>
1、$attrs收集属性
2、$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 >{{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. 数据总线 

用一个中间变量保存数据

  • 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>


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI