Vue2 组件通信 ( 12种 )

1.父子组件之间的通信

(1)父给子传参

props

父组件内,在子组件标签里边使用v-bind(简写为 : )绑定属性,在子组件内使用props接收数据.

  

props接收数据有三种形式

数组形式

props: ['count', 'userInfo', 'changeCount'],

对象形式

props: { ​ count: Number, ​ userInfo: Object, ​ changeCount: Function },

配置对象形式

props: 
{ ​ 
count: { ​ type: Number, 
​          required: true, // 必填 ​
          default: 4 // 默认值 
          ​// required 和 default 是互斥的,如果必填还设置默认值没有意义 ​ }, 
​          userInfo: { ​ type: Object, ​ default() { ​ return { ​ name: '老六', ​ age: 22 ​ } ​ } ​ 
       }, ​       
          changeCount: { ​ type: Function, ​ required: true ​ } 
  },

props传参分为函数类型和非函数类型

非函数类型

  • 基本数据类型(数组形式): 子组件不能修改父组件传过来的数据

  • 引用数据类型(对象形式): 子组件不能修改父组件传过来的引用数据类型地址,可以改里面的属性(但是不推荐,违反了单项数据流)

函数数据类型

  • 传函数的目的是为了子组件调用修改父组件的数据

(2)子给父传参

自定义事件

( @change----->$emit )

父组件 ( 使用v-on( 简写为@ ) 绑定事件 )


        

子组件 ( 使用$emit触发父组件绑定的事件 )

  1. 事件类型 - changeCount - 自定义事件是给组件绑定的,自己定义的,名字自己取,有无限个数

  2. 触发机制 - 自己触发的,参数需要自己传递,没有事件对象,使用$emit触发

$emit('changeCount', 9)

参数一:触发的事件类型 参数二: 传递的参数

自定义事件关于$event

函数不加小括号 - 触发的函数中的参数直接是 $emit 传过来的数据

函数加小括号 - 自定义事件是没有事件对象的,$event变成了子组件传过来的参数

原生事件

        
        
        
原生事件
1. 事件类型 - click - 在原生事件中,事件类型一定是有限个数
2. 触发机制 - 浏览器触发的,触发的时候会给函数传一个事件对象,事件对象是浏览器生成的
原生事件关于$event
函数不加小括号 - 默认系统触发原生事件的时候,第一个参数是 事件对象
函数加小括号 - 加小括号的时候,如果需要事件对象必须使用 $event (底层上是当前这个函数外部套了一层函数,套的这个函数形参是$event,我们用的就是这个形参)

2.跨组件通信

(1)全局事件总线

  1. 安装总线

new Vue({

beforeCreate() {

Vue.prototype.$bus = this; // 安装总线

},

}
  1. 接收数据

在接收数据的组件中,绑定事件,留下回调,接收参数

Child2组件 - 接数据

mounted() {

this.$bus.$on('receiveParams', this.receiveParams)

},

methods: {

receiveParams(params) {

console.log('接收到的参数', params);

}

}
  1. 发送数据

在发送数据的组件中,触发事件,传递参数

3.父子组件间的数据同步

(1) v-model

父组件的子组件标签中绑定

   
-----------------------------------------------------------------------------------------------
 data() {
        return {
            keyword: "abc",
        };
    },

在子组件中绑定value和input事件,留下回调触发回调

     
----------------------------------------------------------------------------------------------
     props: ['value'],
     methods: {
        changeValue(e) {
            this.$emit('input', e.target.value);
        }
     }

条件: 必须实现

1. 绑定:value值

2.绑定@input事件

数据的流向:

\1. 通过:value把数据绑定给子组件

\2. 子组件中使用props接收父组件传过来的数据

\3. 修改数据,使用$emit触发自定义事件,把参数传递给父组件

\4. 父组件接收到数据之后,更新keyword的值

\5. keyword值更新之后,又重新通过:value传递给子组件

什么情况下会使用v-model?

封装组件的时候,组件中有表单元素的时候一般会使用v-model

多数用在表单元素上,双向数据绑定,用来收集表达数据

在哪见过?

  • 在element ui 中的 el-input组件使用的就是 v-model

(2).sync

父组件中的子组件标签里使用( :msg(属性名).sync='' )绑定数据

   
----------------------------------------------------------------------------------------------------------
    data() {
        return {
            string: "我爱你",
        };
    },

子组件使用原生事件绑定一个方法,方法内使用( this.$emit('update:msg', "666") )来触发 从而实现父子组件数据同步

  
-----------------------------------------------------------------------------------------------------------
      props: ['msg'],
              methods: {
      changeParentMsg() {
            this.$emit('update:msg', "666")
        }
    }

条件: 必须实现 1. :msg(属性名) 2. @update:msg

  • :msg="msg" 给子组件绑定数据,用于展示

  • @update:msg="changeMsg" 绑定自定义事件

  • 这里 必须使用 @update:msg 冒号后面跟绑定的数据名称

  • 这里的msg是v-bind绑定的属性

在哪见过?

  • 在element UI中的对话框dialog中见过

使用场景(主要是却别v-model)

  • v-model 在封装表单元素的时候实现父子组件数据同步,经常使用v-model

  • .sync 在封装非表单元素的组件时候实现父子组件数据同步,经常使用.sync

数据的流向:

  1. 通过:msg把数据传给子组件

  2. 子组件修改数据,$emit 触发了事件把参数传给父组件,父组件修改数据

  3. 父组件更改msg,再通过 :msg 传给子组件

4.$attrs与$listeners

  • $attrs 可以接收到绑定在组件上的所有属性,除去props接收过的属性、style、class类名

  • $listeners 可以接收到所有绑定在组件上的事件

  
  
        {{ content }}
    

对element ui 组件进行二次封装的时候,把element里面的每个属性往外一个一个暴露,很累

$attrs

$attrs 可以接收到绑定在组件上的所有属性,除去props接收过的属性、style、class类名

在使用的时候使用 v-bind="$attrs" 直接将这个对象绑定到组件上即可

注意: v-bind不能写成 :

$listeners

$listeners 可以接收到所有绑定在组件上的事件

在使用的时候使用 v-on="$listeners" 直接将这个对象绑定到组件上即可

注意: v-on 不能简写成 @

5.$refs & $children & $parent

$refs 可以获取到组件实例,拿到组件实例可以拿到组件中的数据,在标签上使用的时候获取到的是标签

$children 当前组件的所有子组件,得到的是一个数组

$parent 获取当前组件的父组件

只有可以获取到当前的组件实例,就可以获取到数据,修改数据

注意: 这里不推荐使用 $parent, 为什么?

因为父组件不确定是谁

6.mixin

mixin 是混入

组件中有公共提取的时候就需要用到mixin

使用:

首先创建一个mixin.js的文件,

暴露一个对象,这个对象就是vue的配置对象( Vue组件中能配置什么,这里就能配置什么 )

mixin.js 文件
--------------------------------------------------------------------------------------------------------
export default {
    data() {
        return {
        };
    },
​
    computed: {  
    },
​
    mounted() {
        console.log("mixin的挂载");
    },
​
    methods: {
    },
};

然后在需要混入的组件当中 引入并配置 就OK了

     import Mixin from './mixin'
     export default {
         mixins: [Mixin], // 混入的配置项
     }

  • 在mixin中配置的内容(内容包括但不限于数据,方法等),都可以混入到组件当中

  • 如果在组件中有重复的内容,会发生覆盖,组件中的内容会覆盖混入的内容

注意:

钩子函数不会被覆盖,先执行mixin中的钩子,再执行组件中的钩子

7.用户祖先组件和后代组件之间进行通信

(1)Provide、Inject

  • 使用方式类似于props

provide 理解成广播

inject 就是用来接数据的

注意: 广播只广播一次,当数据发生改变的时候,后代组件当中接收不到更新的信息(包含基本数据类型和引用数据类型的地址)

在使用引用数据类型的时候,对象中的属性发生改变,后代组件是可以接收到的

祖先组件-----------------------------------------------------------------------------------------------------------------------------------------------------------------------



子组件



孙组件---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

8.Vuex

使用场景: 多个组件依赖同一数据的时候使用 vuex,

例如说: 一般情况下用户信息会放在store中 (因为权限问题)

vuex使用步骤

  1. 安装 npm i vuex@3 -S

  2. 引入暴露

创建 store.js 文件

import Vue from "vue";
import Vuex from 'vuex';
Vue.use(Vuex);
​
export default new Vuex.Store({ 
    state,
    mutations,
    actions,
    getters,
    modules //模块化
})
  1. 创建vm关联store

    在 main.js 文件中

    //暴露
    import store from '@/store'
    ​
    new Vue({
        render: h => h(App),
        store  //关联
    }).$mount('#app')

模块化

配置 modules 只要开启模块化,state中的数据就是加了一层,而mutations、actions、getters和之前的使用方式一样

state
     $store.state.test.count  //普通写法  
​
    
     ...mapState({     // 辅助函数 - 往computed中映射
         count: state => state.test.count
     })
​
actions
     $store.dispath('increment')   //普通写法   
         //actions怎么写,mutaions就怎么写,只改一个地方dispath改成commit即可  
    
     ...mapActions(['increment'])   // 辅助函数 - 往methods中映射
getters
     $store.getters.dblCount  //普通写法    
     //辅助函数 - 往compouted中映射
     ...mapGetters(['dblCount'])
​
//命名空间
在store当中配置 namespaced: true   //加了命名空间,每一个模块都是独立的
state和开启模块化的时候一样,mutations、actions、getters都多加了一层
state - 还是开启模块化的写法
actions
     $store.dispatch('test/increment')  //普通写法    
 
     ...mapActions('test', ['increment'])       //辅助函数
getters
     $store.getters['test/dblCount']   //普通写法    
​
     ...mapGetters('test', ['dblCount'])  // 辅助函数
 
  

9.slot

作用: 父子组件之间的通信,父给子传 html 和 css

插槽有三种

普通插槽、具名插槽、作用域插槽

父组件--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

子组件---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

10.Pubsub

  1. 安装

    npm i pubsub-js

  2. 接收数据,接收数据的组件,绑定事件(订阅消息),留下回调,接收参数

    Pubsub.subscribe('changeMessage', this.changeMessage)

  3. 传递出局,传递数据的组件,触发事件(发布消息),传递参数

    Pubsub.publish('changeMessage')

这里和总线唯一的区别在接收数据的函数中,参数一是消息类型

父组件------------------------------------------------------------------------------------------------------------------------------------------------------------------------

子组件1------------------------------------------------------------------------------------------------------------------------------------------------------------------------

子组件2------------------------------------------------------------------------------------------------------------------------------------------------------------------------

你可能感兴趣的:(vue2,组件通信,vue)