为什么要进行组件通信?
组件通信的方式有以下几种
父子组件通信
使用props来实现
1. 在父组件的模板中将数据用单项数据绑定的形式,绑定在子组件身上
2. 在子组件的配置项中可以使用一个props配置项来接收这个数据,接收时,props的取值可以使一个数组
Vue.component('Son',{
template: '#son',
props: ['money']
})
3. 在子组件模板中,接收到的属性可以像全局变量一样直接使用
父亲给了我 {{ money }} 钱
问题: 为什么data要定义为一个函数?
1. 组件是一个独立的个体,那么它应该拥有自己的数据,这个数据应该是一个独立的数据
2. 也就是说这个数据应该有独立作用域,也就是有一个独立的使用范围,这个范围就是这个组件内
3. js的最大特征是:函数式编程 , 而函数恰好提供了独立作用域
问题: 为什么data要有返回值?返回值还是一个对象?
1. 因为Vue是通过observer来观察data选项的,所有必须要有返回值
2. 因为Vue要通过es5的Object.defineProperty属性对对象进行getter和setter设置
html结构:
这里是父组件
//注意: 数据绑定时,:后不能用不能驼峰命名,用-命名后面用props中用小驼峰的名字接收,使用。
这里是son组件
父亲给了我 {{ aa }} 钱
{{ maskFlag }}
js结构:
Vue.component('Father', {
template: '#father',
data() { // data定义为函数?
return {
money: 2000,
maskFlag: 10000000000
}
}
})
Vue.component('Son', {
template: '#son',
props: ['aa', 'maskFlag']
})
new Vue({
}).$mount('#app')
子父组件通信
自定义事件
自定义事件
1. 自定义的 通过 $on 定义 $emit触发
2. 通过绑定在组件身上定义,通过 $emit触发
子父通信流程
1. 在父组件的模板中,通过事件绑定的形式,绑定一个自定义事件在子组件身上
//注意: fn是要在父组件配置项methods中定义
2. 在子组件的配置项methods中写一个事件处理程序,在事件处理程序中触发父组件绑定的自定义事件
Vue.component('Son',{
template: '#son',
data () {
return {
hongbao: 500
}
},
methods: {
giveFather () {
//如何进行父组件给子组件的自定义事件触发
this.$emit('give',this.hongbao)
}
}
})
3. 将子组件定义的事件处理程序 giveFather,绑定在子组件的按钮身上
这里是son组件
html结构:
这里father组件
儿子给了我 {{ money }}
这里是son组件
js结构:
Vue.component('Father',{
template: '#father',
data () {
return {
money: 0
}
},
methods: {
getHongbao ( val ) {
this.money = val
}
}
})
Vue.component('Son',{
template: '#son',
data () {
return {
hongbao: 500
}
},
methods: {
giveFather () {
//如何进行父组件给子组件的自定义事件触发
this.$emit('give',this.hongbao)
}
}
})
new Vue({
el: '#app'
})
非父子组件通信
① ref链:可以实现非父子组件的通信,但是如果层级太多,就比较繁琐了
// 通过一个共同的父组件来通信,一个传给父组件 父组件再传给另一个
html结构:
这里是father
father的 n: {{ n }}
这里是 son 1
这里是girl
js结构:
Vue.component('Father',{
template: '#father',
data () {
return {
n: 0
}
},
methods: {
look () {
this.n = this.$refs.son.money
}
}
})
Vue.component('Son',{
template: '#son',
data () {
return {
money: 1000
}
}
})
Vue.component('Girl',{
template: '#girl',
data () {
return {
num: 0
}
},
methods: {
out () {
console.log( this.$attrs.n )
}
}
})
new Vue({
el: '#app'
})
② bus事件总线
bus事件总线,我们是通过 $on来定义事件, 通过 $emit来触发事件
案例: 哥哥揍弟弟,弟弟哭
流程:
1. 在其中一个组件的 挂载钩子函数 上 做事件的声明
Vue.component('Sma',{
template: '#small',
data () {
return {
flag: false
}
},
mounted () { //当前组件挂载结束,也就是我们可以在页面当中看到真实dom
// mounted这个钩子函数的触发条件是组件创建时会自动触发
// 事件的声明
var _this = this // 保存Sma的this
bus.$on( 'aa',function () {
_this.flag = true
console.log( this )//这里是this指的是bus, 但是我们需要的this应该是Sma这个组件
})
}
})
2. 在另一个组件中 通过 bus.$emit('aa')来触发这个自定义事件
html结构:
这里是哥哥组件
这里是弟弟组件
呜呜呜呜呜呜呜呜呜uwuwuwuwu
js结构:
var bus = new Vue() // bus原型上是不是有 $on $emit
Vue.component('Bro',{
template: '#big',
methods: {
hick () {
bus.$emit('aa')
}
}
})
Vue.component('Sma',{
template: '#small',
data () {
return {
flag: false
}
},
mounted () {
var _this = this
bus.$on( 'aa',function () {
_this.flag = true
console.log( this )
})
}
})
new Vue({
el: '#app'
})
多组件状态分享(多个组件共同用一个数据)
这块内容比较多,后面再专门写一次
两种非常规方法
① 业务: 我要进行子父组件通信
理解: 使用自定义事件实现
实现:
父组件将一个方法通过属性绑定的形式给了子组件,子组件先是通过props接收这个方法,在执行这个方法
这个方法不推荐使用(MVVM框架是单向数据流,但是此方法违背了单项数据流)
html结构:
这里是father组件
这里是父组件的n: {{ n }}
s
这里是son组件
js结构:
Vue.component('Father', {
template: '#father',
data() {
return {
n: 0
}
},
methods: {
add(val) {
this.n = val
}
}
})
Vue.component('Son', {
template: '#son',
data() {
return {
money: 1000
}
},
props: ['add']
})
new Vue({
el: '#app'
})
② 父组件传递一个 对象类型给子组件,子组件通过 props 接收。就会发现: 子组件修改这个数据的时候,父组件的数据也随之改变了 ?
因为父组件给子组件的是对象的引用地址
这种方法不推荐使用 , 违背了单向数据流
html结构:
这里是father组件
father: 小金库: {{ xiaojinku.money }}
这里是son组件
son 小金库: {{ xiaojinku.money }}
js结构:
Vue.component('Father',{
template: '#father',
data () {
return {
xiaojinku: {
money: 1000
}
}
}
})
Vue.component('Son',{
template: '#son',
props: ['xiaojinku']
})
new Vue({
el: '#app'
})