父组件向子组件传值
通过props配置向子组件传值
1.在父组件App注册子组件User时通过自定义属性值传值
1
2
3
4
5
<template>
<div id="app">
<User :getUserName='getUserName' name='我是爸爸' age='50'></User>
</div>
</template>
2.子组件User中用props接受属性,该属性会被直接赋予给User组件实例,这样就可以像使用数据对象的方法一样直接使用了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<div>
<div>方法名:</div>
<div>姓名:</div>
<div>年龄:</div>
</div>
</template>
<script>
export default {
name: "User",
props:['getUserName','name','age'],
};
</script>
子组件向父组件传值
子组件props接收函数
子组件props接收父组件的传入函数,函数在子组件中被调用,作用域却在父组件,因而子组件在函数中传入的函数就能在父组件接收,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<div id="app">
// 将函数传递给子组件
<User :getUserName="getUserName"></User>
</div>
</template>
<script>
import User from "./views/User.vue";
export default {
name: "App",
components: {
User,
},
methods: {
// 父类的方法,作为媒介接收来自子组件的值
getUserName(username){
console.log('获取到用户名:'+username)
}
},
};
</script>
子组件接收函数,并将值通过参数传递给父组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<div class="user">
<div>用户姓名:</div>
</div>
</template>
<script>
export default {
name: "User",
// 接收函数
props:['getUserName'],
data() {
return {
name: 'flameking',
};
},
mounted(){
// 传入name
this.getUserName(this.name)
}
};
</script>
自定义事件
(一)第一种定义方式,在标签当中定义
1.首先定义我们的事件和事件被触发的回调函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<div id="app">
// 自定义我们的事件名
// 加上事件修饰符:once,表示事件至多触发一次
<Home @testevent.once="getFamilyAddress"></Home>
</div>
</template>
<script>
import Home from "./views/Home.vue";
export default {
name: "App",
components: {
Home
},
methods: {
// 定义回调函数,接收一个参数,address
getFamilyAddress(address){
console.log('家庭住址:'+address)
}
},
};
2.事件被注册在子组件Home当中,自然就需要在Home当中触发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
export default {
name: "Home",
data() {
return {
address: "湖南 衡阳",
};
},
// 触发事件testevent,并传入参数address
mounted() {
this.$emit("testevent", this.address);
console.log(this);
},
};
</script>
(二)第二种定义方式,直接获取组件实例,并注册事件
1.我们知道事件是被绑定在子组件实例中,第一种定义方式是在标签当中定义事件并与组件一同注册,现在我们优先获取子组件实例,然后注册事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<template>
<div id="app">
// ref配置获取当前组件实例
<Home ref="home"/>
</div>
</template>
<script>
import Home from "./views/Home.vue";
export default {
name: "App",
components: {
Home,
},
methods: {
getFamilyAddress(address,x,y,z) {
console.log("家庭住址:",address,x,y,z);
},
// 接收多个参数,出为首一个参数,其余参数放在a数组中
// getFamilyAddress(address,...a) {
// console.log("家庭住址:",address,a);
// },
},
// 当父组件挂载完成后注册事件testevent,以及事件的回调函数getFamilyAddress
mounted() {
this.$refs.home.$on('testevent',this.getFamilyAddress)
// 事件至多被触发一次
// this.$refs.home.$once('testevent',this.getFamilyAddress)
},
};
</script>
2.子组件如原来方式触发事件,不过有一点需要注意:由于事件是在父组件App被挂载往后才注册的,如果在子组件挂载完后里面触发事件不会有效因为App在所有子组件挂载完成后完成挂载,也就是说子组件内mounted触发的事件压根还未注册
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
<div class="family">
<div>家庭住址:</div>
// 在经过一次点击事件后触发testevent事件
<button @click="sendFamilyAddress">send</button>
</div>
</template>
<script>
export default {
name: "Home",
components: {},
data() {
return {
address: "湖南 衡阳",
};
},
methods: {
// 在sendFamilyAddress方法内触发testevent事件,并传入参数多个参数
sendFamilyAddress(){
this.$emit("testevent", this.address,'中国','湖南','衡阳');
console.log(this);
}
},
mounted() {
},
};
</script>
这种方式下比第一种更加灵活,主要体现在注册事件的时候,例如让事件在App组件挂载完成后3秒后完成注册
1
2
3
4
5
mounted() {
setTimeout(() => {
this.$refs.home.$on('testevent',this.getFamilyAddress)
},3000)
},
解绑自定义事件
如果自定义事件需要解绑,那么也需要在通过事件的组件实例进行解绑,解绑总共三种方法:
- this.$off(‘getUserAge’),解绑一个事件
- this.$off([‘getUserName’,’getUserAge’]),解绑多个事件
- this.$off(),解绑当前组件的所有事件
自定义事件需要注意的点
1.如果销毁当前组件实例,由于实例被销毁,绑定在它身上的所有自定义事件无效,响应式无法再起作用,即页面不会随着数据的修改而动态更新**
1
2
3
destroyComponent(){
this.$destroy()
}
2.回调函数里面的this指向
如果自定义事件的回调函数我们不卸载methods中,而是直接以匿名函数的形式作为参数传入:
1
2
3
4
5
6
7
8
mounted() {
this.$refs.home.$on("testevent", function (address, ...a) {
console.log("家庭住址:", address, a);
// 此时的this不是父组件实例对象而是子组件实例对象
console.log(this)
});
this.$refs.user.$on("getUserAge", this.getUserAge);
}
如何获取到父组件的实例对象呢?
- 使用箭头函数的形式
- 再函数外使用变量保存父组件的实例对象,延长作用域
- 或直接使用原来的形式
3.给组件绑定原生事件
给组件绑定原生事件有两种形式:
第一种:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div id="app">
<div>我是父组件</div>
<Home @click="callNative" ref="home" />
</div>
</template>
<script>
import Home from "./views/Home.vue";
export default {
name: "App",
components: {
Home,
},
methods: {
callNative(){
console.log('绑定原生事件')
}
},
};
</script>
像这种Vue会把click作为自定义事件进行处理
第二种:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div id="app">
<div>我是父组件</div>
// 通过native事件修饰符就可以调用到原生事件
<Home @click.native="callNative" ref="home" />
</div>
</template>
<script>
import Home from "./views/Home.vue";
export default {
name: "App",
components: {
Home,
},
methods: {
callNative(){
console.log('绑定原生事件')
}
},
};
</script>
注意:native事件修饰符只能用在组件当中,并且事件被绑定再了组件的root元素上
兄弟组件互相通信
全局事件总线
全局事件总线与自定义事件模型对比图
全局事件总线将有vm担任