平时在使用 vue 框架的业务开发中, 组件不仅仅要把模板的内容进行复用, 更重要的是组件之间要进行通信. 组件之间通信分为三种: 父 - 子; 子 - 父; 跨级组件通信. 下面, 就组件间如何通信做一些总结.
1. 父组件到子组件通过 props 通信
在组件中, 使用选项 props 来声明需要从父级组件接受的数据, props 的值可以是两种: 一种是字符串数组, 一种是对象. props 中声明的数据与组件 data 函数 return 的主要区别在于 props 来自父级, 而 data 中的组件是自己的数据, 作用域是组件本身, 这两种数据都可以在模板 template 及计算属性 computed 和方法 methods 中使用. 如以下例子:
- // 父组件 ParentComponent
- <template>
- <div class="parent-component">
- <h2 > 这是一个父组件</h2>
- <ChildComponent :parentMessage="parentMessage"/>
- </div>
- </template>
- <script>
- import ChildComponent from './ChildComponent'
- export default {
- name: "ParentComponent",
- data(){
- return{
- parentMessage:'这是来自父组件的数据'
- }
- },
- components:{
- ChildComponent
- }
- }
- </script>
- // 子组件 ChildComponent
- <template>
- <div class="child-component">
- <h2 > 这是一个子组件</h2>
- <h3>{{parentMessage}}</h3>
- </div>
- </template>
- <script>
- export default {
- name: "ChildComponent",
- props:["parentMessage"]
- }
- </script>
小结: 父组件传递个子组件的数据可以写死, 也可以用父级的动态数据用 v-bind 来绑定 props 的值.
2. 子组件到父组件通过 $emit,$on 通信
当子组件需要向父组件传递数据时, 就要用到自定义事件, v-on 指令除了监听 DOM 事件外, 还可以用于组件间的自定义事件, Vue 组件有一套类似与观察者模式的一套模式, 子组件用 $emit()来触发事件, 父组件用 $on()来监听子组件的事件. 举个例子如下:
- // ParentComponent 父组件
- <template>
- <div class="parent-component">
- <h2 > 这是一个父组件 total:{{total}}</h2>
- <ChildComponent :parentMessage="parentMessage" :total="total" @handleAdd10="getTotal"/>
- </div>
- </template>
- <script>
- import ChildComponent from './ChildComponent'
- export default {
- name: "ParentComponent",
- data(){
- return{
- parentMessage:'这是来自父组件的数据',
- total:10,
- }
- },
- components:{
- ChildComponent
- },
- methods:{
- getTotal(total){
- this.total=total;
- console.log('ParentComponent total:',total);
- }
- }
- }
- </script>
- // ChildComponent 子组件
- <template>
- <div class="child-component">
- <h2 > 这是一个子组件</h2>
- <h3>{{parentMessage}}</h3>
- <button @click="handleAdd10">+10 按钮</button>
- </div>
- </template>
- <script>
- export default {
- name: "ChildComponent",
- props:["parentMessage","total"],
- methods:{
- handleAdd10(){
- let total=this.total+10;
- console.log('ChildComponent $emit:');
- this.$emit('handleAdd10',total);
- }
- }
- }
- </script>
结果:
上面例子中, 子组件有一个按钮, 实现加 10 的效果, 子组件通过 props 项来接收父组件传入的 total 值, 在改变 total 后, 通过 $emit 把它传给父组件, 父组件定义事件 @handleAdd10 方法, 子组件 $emit()方法第一个参数是自定义事件的名称, 后面的参数是要传的数据, 对应的父组件通过 getTotal(total)来接收子组件传递的数据, 由此子组件到父组件通信完成.
3. 表单子组件到父组件通过 v-model 来通信(语法糖)
- // ParentComponent 改动如下
- **
- <h2 > 这是一个父组件 total:{{total}}</h2>
- <ChildComponent :parentMessage="parentMessage" :total="total" @handleAdd10="getTotal"/>
- <InputComponent v-model="total"/>
- **
- <script>
- import InputComponent from './InputComponent'
- </script>
- **
- // InputComponent 子组件
- <template>
- <input type="text" @input="updateValue($event)">
- </template>
- <script>
- export default {
- name: "InputComponent",
- methods:{
- updateValue(evt){
- this.$emit('input',evt.target.value)
- }
- }
- }
- </script>
结果如下:
以上示例中: 因为子组件的石建明是特殊的 input, 在使用组件的父级, 可以通过 v-model 来绑定数据 total, 这种实现方式也可以称作语法糖, 大大减少了父组件代码量.
4. 非父子组件通过中央事件总线 (bus) 来通信
在 vue.js2.x 中推荐使用一个空的 Vue 实例作为中央事件总线(bus), 先看一个例子:
- // ParentComponent 父组件
- <template>
- <div class="parent-component">
- {{message}}
- <br>
- <br>
- <component-a/>
- </div>
- </template>
- <script>
- import Vue from 'vue'
- let bus=new Vue();
- export default {
- name: "ParentComponent",
- data(){
- return{
- message:'',
- }
- },
- components:{
- componentA:{
- template:'<button @click="handleClick">传递事件</button>',
- methods:{
- handleClick(){
- bus.$emit('on-message','来自子组件 component-a 的内容')
- }
- }
- }
- },
- mounted(){
- bus.$on('on-message',(msg)=>{
- this.message=msg;
- });
- }
- }
- </script>
结果如下:
以上例子中: 首先创建了一个 bus 的空 Vue 实例, 里面没有任何内容, 然后全局定义了组件 component-a,, 在父组件 ParentChild 的生命周期 mounted 钩子函数中监听来自 bus 的事件 on-message. 而在组件 component-a 中, 点击按钮会通过 bus 把事件 on-message 发出去, 父组件会接受来自 bus 的事件, 改变 message 的值.
这种方法巧妙轻量的实现了任何组件之间的通信, 包括父子, 兄弟, 跨级组件.
5. 状态管理与 Vuex 与总结
在实际业务中, 经常会有跨组件共享数据的需求, 如果项目不复杂, 使用 bus 就能简单的解决问题, 但是使用 bus 在数据的管理, 维护, 架构设计上还只是一个简单的组件, 在大型单页应用, 多然开发的项目中, Vuex https://vuex.vuejs.org/zh/guide/ 能更加优雅和高效的完成状态管理.
根据以上组件间通信的描述, 用一张图来表示组件间的通信示例, 以上就是个人对于 Vue 组件间通信的实践与理解, 如果有纰漏不足的地方, 请多指正.
来源: https://www.cnblogs.com/peerless1029/p/10005316.html