1、父组件=>子组件,属性传递
父组件:传值
<HelloWorld msg="Welcome to your vue app" />
子组件:接收
props{
msg: String
}
2、父组件=>子组件,使用ref传值
此处使用mounted而不是使用created,因为挂载时子组件才加载完成,才能访问到子组件
父组件先于子组件创建
父组件
<HelloWorld msg="Welcome to Your Vue.js App" ref="hw"/> export default { components: { HelloWorld }, mounted () { this.$refs.hw.foo = 'abcabc' } }
子组件
<div class="hello"> <h1>{{ msg }}</h1> {{foo}} </div> data(){ return{ foo: 'foo' } }
页面的{{ foo }} 部分,会显示abcabc
3、父组件=>子组件,使用$children
mounted(){
this.$children[0].foo = 'dong' // 在此处可以访问到这个子组件
}
页面的{{ foo }} 部分,会显示 dong
这种方式,子元素(this.$children)不保证顺序,也不响应式(只读)---不推荐使用
this.$children中的foo值是响应式的
4、子组件=>父组件,自定义事件
原理:子组件派发事件,父组件监听事件(观察者模式)
// child // foo为派发的事件名,bar为传参 <h1 @click="$emit('foo', 'bar')">test</h1> // parent <HelloWorld @foo="onFoo" /> methods:{ onFoo(){ console.log('onFoo') } } // 有传参的情况(传一个参数) // child <h1 @click="$emit('foo', 'bar')">test</h1> // parent <HelloWorld @foo="onFoo($event)" /> methods:{ onFoo(e){ console.log(e) } } // 有传参的情况(传多个参数) // child <h1 @click="$emit('foo', 'bar', 'dong')">test</h1> // parent <HelloWorld @foo="onFoo(arguments)" /> methods:{ onFoo(arg){ // 此处agr会以数组的形式传入 console.log(arg) } }
事件的派发者是谁,事件的监听者就是谁
5、兄弟组件
通过共同的祖辈搭桥,$parent 或者 $root,(parent找父节点,root找根节点)
// HelloWorld组件中,通过父组件搭桥 <div class="hello" @click="$parent.$emit('mua')"> HelloWorld </div> // Log组件中,监听父组件中的mua事件 created () { this.$parent.$on('mua', () => { console.log('muamua'); }) }
此时点击HelloWorld,会输出 muamua
6、祖先和后代之间(隔代传值)
由于嵌套过多,使用props不切实际,vue提供了provide和inject API来完成该任务(常用于组件库开发)
// 父组件 provide: {dong: 'dong'}, mounted () { } // 子组件 inject: ['dong'], props: { msg: String }
甚至可以将祖先作为this传入
// 父组件 data(){ return{ dong: 'dong' } }, provide(){ return{ dong: this } } // 子组件 <div> {{foo}} - {{dong.dong}} </div> inject: ['dong'], data(){ return{ foo: 'foo' } }
这种方式,只能祖先代给子辈代传值,反过来不行
平常开发时少用,主要用于组件库的开发
如果想改provide中的值,在provide时传入一个set的函数
provide(){
dong: 'dong',
setDong: this.xx
}
子组件通过调用setDong来更改dong的值
7、任意两个组件之间传参(事件总线 or vuex)
(1)事件总线:创建一个Bus类进行事件派发、监听和回调管理
// Bus:事件派发,监听和回调管理 class Bus{ constructor(){ this.callbacks = {} } $on(name, fn){ this.callbacks[name] = this.callbacks[name] || [] this.callbacks[name].push(fn) } $emit(name, args){ if(this.callbacks[name]){ this.callbacks[name].forEach(cb => cb(args)) } } } // main.js Vue.prototype.$bus = new Bus() // 也可以直接 Vue.prototype.$bus = new Vue() // 因为Vue中已经实现了这些 // child1 this.$bus.$on('foo', handle) // child2 this.$bus.$emit('foo')
(2)vuex
创建一个唯一的全局数据管理者store,通过它管理数据并通知组件状态变更