.sync的定义
当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定。 .sync 它会被扩展为一个自动更新父组件属性的 v-on 监听器。
在介绍.sync之前,需要先把props和props中的$emit方法介绍一下。也当作复习了。
1. props(父组件向子组件传值)
官网定义
props 可以是数组或对象,用于接收来自父组件的数据。props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义验证和设置默认值。
自我理解:
props 主要就是用于组件间的通信,主要就是父传子(我自己理解的,子传父应该用通过绑定事件然后及$emit传值,普通组件间传值用全局事件总线 $bus)。
props主要用于组件的传值,他的工作就是为了接收外面传过来的数据,与data、el、ref是一个级别的配置项。
代码
<!-- 父组件 -->
<template>
<div>
<mHome :mlist="list"/>
</div>
</template>
<script>
import mHome from "@/views/Home.vue";
export default {
components: {
mHome,
},
data() {
return {
list: ["小米", "华为", "苹果", "三星"],
};
},
};
</script>
<!-- 子组件 -->
<template>
<div class="home">
<h2>请输入相关手机型号</h2>
<span v-for="(item, index) in mlist" :key="index">{{ item }}</span>
</div>
</template>
<script>
export default {
props: ["mlist"],
};
</script>
注意:
组件中 mlist 是一个prop,当然props中可以放很多prop,多个prop合起来就是props,这就是props的由来,是prop的复数形式,代表多个prop属性的集合。
对上面的代码分析:
就是父组件中有子组件标签,可以在子组件标签中添加属性 :mlist ,其中 :是v-bind的简写,然后就可以把 list 的值传过去。在子组件中,使用props进行接收值(是和data同级)。
然后父组件中的 list 中的值就保存到了子组件中的 mlist ,然后子组件就可以使用list的值了。
2.$emit(子传父)
代码
<!--- 父组件 --->
<template>
<div class="app">
<Student v-on:at="getStudentName" v-on:go="getStudentAge"></Student>
</div>
</template>
<script>
// 引入Student组件
import Student from './components/Student.vue'
// 定义vue组件
export default {
name:'App',
components:{
Student
},
data() {
return {
msg:'你好啊'
}
},
methods: {
getStudentName(name) {
console.log('app收到了学生名',name);
},
getStudentAge(age) {
console.log('app收到了学生年龄',age);
}
}
}
</script>
<!--- 子组件 --->
<template>
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学校年龄:{{age}}</h2>
<button @click="sendStudentName">把学生名给app</button>
<button @click="sendStudentAge">把学生年龄给app</button>
</div>
</template>
<script>
export default {
name:'MyStudent',
data() {
return {
name:'张三',
age:18
}
},
methods: {
sendStudentName() {
// 触发Student组件实例对象vc上的at事件(绑定at事件)
this.$emit('at',this.name)
},
sendStudentAge() {
// 触发Student组件实例对象vc上的go事件(绑定go事件)
this.$emit('go',this.age)
}
}
</script>
代码分析
还是和props一样,都是子组件标签在父组件中,然后不一样的是,这里是在父组件中的子组件标签中用v-on绑定一个事件(v-on简写是@),然后在子组件中使用 this.$emit 绑定事件,然后同时传一个数据给父组件。具体看代码就可以理解了。
3.非父子组件间通信(使用全局事件总线)
假设你有两个Vue组件需要通信: A 和 B ,A组件按钮上面绑定了点击事件,发送一则消息,B组件接收。
1.安装全局事件总线
在vm中安装
// 创建vm
new Vue({
el: '#app',
render:(h) => h(App),
beforeCreate() {
Vue.prototype.$bus = this //安装全局事件总线
}
})
2. A组件发送信息
<template>
<div class="student">
<h2>学生姓名:{{name}}</h2>
<button @click="sendSchoolName">点我把学生姓名传给组件A</button>
</div>
</template>
<script>
export default {
name:'MyStudent',
data() {
return {
name:'张三',
age:18
}
}
methods: {
sendSchoolName() {
this.$bus.$emit('hello',this.name) // 使用全局事件总线发送,用$emit
}
},
}
</script>
3. B组件接受信息
<template>
<div class="school">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
</template>
<script>
export default {
name:'MySchool',
data() {
return {
name:'清华',
address:'北京'
}
},
mounted() {
this.$bus.$on('hello',(data)=>{
console.log('我是School组件,收到了数据',data); // 使用全局事件总线接受信息
})
},
}
</script>
简单理解,全局事件总线其实就是一个中间介质,组件间的相互通信借助于这个中间介质,通过这个中间转换介质,从而完成数据的传递与接收,实现组件间的相互通信。
代码分析
主要就是第一步先在vue原型对象中安装全局事件总线。在vm中安装就是让this.$bus存在。
然后就是 $emit发送和 o n 接收。可以认为发送的信息存放在全局事件总线中,然后 on接收。 可以认为发送的信息存放在全局事件总线中,然后 on接收。可以认为发送的信息存放在全局事件总线中,然后on再把信息取出来。
4. .sync的使用
讲了这么多才到sync的介绍😂
作用:
当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定。 .sync 它会被扩展为一个自动更新父组件属性的 v-on 监听器。
用代码讲解更好理解
1. 使用props进行父传子
<!--- 父组件 --->
<template>
<div id="app">
<myIndex :title="title"></myIndex>
</div>
</template>
<script>
import myIndex from '@/components/index.vue'
export default {
name: 'App',
components: {
myIndex
},
data () {
return {
title: '标题'
}
}
}
</script>
<!--- 子组件 --->
<template>
<div>
{{ title }}
</div>
</template>
<script>
export default {
name: 'myIndex',
props: ['title']
}
</script>
上面就是最简洁的props父传子
然后提需求:在子组件中点击一个按钮,然后改变title值。就是在子组件中之间对父组件的值进行修改。(主要就是在页面上显示的内容改变)
常规改法:
父组件
<template>
<div id="app">
<myIndex :title="title" @update:title="title = $event"></myIndex>
// 这里是绑定事件修改,比较麻烦
</div>
</template>
<script>
import myIndex from '@/components/index.vue'
export default {
name: 'App',
components: {
myIndex
},
data () {
return {
title: '标题'
}
}
}
</script>
子组件
<template>
<div>
{{ title }}
<button @click="newTitle">点击按钮改变title值</button>
</div>
</template>
<script>
export default {
name: 'myIndex',
props: ['title'],
methods: {
newTitle() {
this.$emit('update:title','新标题')
}
}
}
</script>
使用.sync修改
就是把父组件中的子组件标签修改一下就可以了,其他地方不要修改
<myIndex :title="title" @update:title="title = $event"></myIndex>
上面的代码修改为
<myIndex :title.sync="title"></myIndex>
就是把v-on绑定事件修改简洁化了