组件间通信:(父子、兄弟组件数据的传递方式)
一、父组件向子组件传递:
1、常见方式:利用属性传递数据
$attrs表示组件中未被注册的属性;可以利用其进行传值;配合v-bind可以将所有属性传递给另一个组件;

//根数据传给组件,通过父组件传给子组件:
var vm = new Vue({
el: "#app",
data: {
content: '我是内容',
title: '我是标题'
},
components: {
myContent: {
// props: ['title', 'content'], //这种方法注册的'content'只是用来传值,没用实际作用
props: ['title'],
created () {//$attrs表示组件中未被注册的属性;可以利用其进行传值;
console.log(this.$attrs)
},
inheritAttrs: false, //设为false,没有被注册的属性不会显示在行间;(本身有的不会消除)
// template: `<div>
// <h3>{{ title }}</h3>
// <my-p :content="content"></my-p>
// </div>`,
template: `<div>
<h3>{{ title }}</h3>
<my-p v-bind="$attrs"></my-p>
</div>`,
components: {
myP: {
props: ['content'],
template: `<p>{{ content }}</p>`
}
}
}
}
})
2、$attrs、
$children:
一般情况下能不用不用,应急时使用(传递较麻烦)
//根数据直接父组件用一部分、子组件用一部分:
var vm1 = new Vue({
el: "#app1",
data: {
content: '我是内容',
title: '我是标题'
},
components: {
myContent: {
created () { //$parent表示父组件的实例;
console.log(this.$parent);
this.title = this.$parent.title
},
mounted () { //$childre表示子组件的实例;
console.log(this.$children)
},
template: `<div>
<h3>{{ title }}</h3>
<my-p> {{ title }}</my-p>
</div>`,
components: {
myP: {
created () {
this.content = this.$parent.$parent.content;
},
template: `<p>{{ content }}</p>`
}
}
}
}
})
3、provide:{}提供值,inject:[]接收值;(一般不用)
//父组件提供值,子组件可以取到;
var vm2 = new Vue({
el: "#app2",
provide: {
content: '我是内容',
title: '我是标题'
},
components: {
myContent: {
inject: ['title'],
template: `<div>
<h3>{{ title }}</h3>
<my-p> {{ title }}</my-p>
</div>`,
components: {
myP: {
inject: ['content'],
template: `<p>{{ content }}</p>`
}
}
}
}
})
二、子向父传递:
1、$children 方式获取到子组件的实例,进行操作(不推荐)
2、$refs:拿到子组件的引用;可以dom上,也可以放到组件上;
const vm3 = new Vue({
el: "#app3",
mounted () {
console.log(this.$refs.dom); //放到dom上;
//这里的dom元素如果初始时有多个且一样,只会打印最后一个;v-for生成的dom会全不打印在[]中;
console.log(this.$refs.cmp); //放到组件上;this.$refs.cmp拿到子组件里的实例;再拿到里面的数据;
console.log(this.$refs.cmp.msg);
this.$refs.cmp.cmpFunc()
},
components: {
myCmp: {
data () {
return {
msg: 'hello'
}
},
methods: {
cmpFunc () {
console.log('cmp')
}
},
template: `<div> i am a cmp </div>`
}
}
})
3、传递函数方式:通过在子组件中执行父组件的函数,向父组件传递数据
方法一:将父组件中的函数当做属性传给子组件执行;
方法二:利用 l i s t e n e r s : 能 够 把 通 过 v − o n 绑 定 的 事 件 放 到 listeners:能够把通过v-on绑定的事件放到 listeners:能够把通过v−on绑定的事件放到listeners里面来;
方法三:利用$emit(’’, );主动触发组件v-on绑定的事件;第二个值可传参用;
//注意:
//当事件绑定很多时,利用v-on给组件内某个dom绑定事件监听(注意通过v-on方法不能传参)
//$listeners与$attrs相似有一个v-on属性,可以将该组件通过v-on绑定的事件传递给另一个组件;
//$listeners和$emit()不仅能触发系统自带的事件,也可以触发自定义事件;
const vm4 = new Vue({
el: "#app4",
methods: {
func (data) {
console.log(data);
},
down (){
console.log('down')
}
},
components: {
myCmp: {
// props: ['func'], //方法一
data () {
return {
msg: 'hello'
}
},
methods: {
cmpFunc () {
console.log('cmp');
},
handleClick () {
// this.func(this.msg); //方法一;
// this.$listeners.click(this.msg); //方法二;
this.$emit('click', this.msg); //方法三;
},
handleMouse () {
this.$emit('mousedown', 4545);
}
},
template: `<div> i am a cmp
<button @click="handleClick" @mousedown="handleMouse">点击</button>
<button v-on="$listeners"> click </button>
</div>`
}
}
})
三、兄弟传递:
enent bus 事件总线: 一个兄弟组触发新的vue实例事件并将数据传参,另一个兄弟组件监听该vue实例事件并取值;
this.bus. $emit(’’, )触发事件;
this.bus. $on(’’, data => {})监听事件;
Vue.prototype.bus = new Vue(); //vue原型上增加属性为一个新的vue实例;
const vm5 = new Vue({
el: "#app5",
components: {
myContent1: { //一个兄弟组触发新的vue实例事件并将数据传参,
data () {
return {
content: '我有值'
}
},
methods: {
handleClick () {
console.log(this)
this.bus.$emit('myClick', this.content); //触发新vue实例的事件
}
},
template: `<div> {{ content }}
<button @click="handleClick">提交</button>
</div>`
},
myContent: { //另一个兄弟组件监听该vue实例事件并取值;
data () {
return {
msg: 123
}
},
created () {
this.bus.$on('myClick', data => { //监听vue实例的事件
this.msg = data;
})
},
template: `<div> {{ msg }}</div>`
},
}})