• 【干货】Vue2.x 组件通信方式详解,这篇讲全了


    前言

    vue是数据驱动视图更新的框架, 我们平时开发,都会把页面不同模块拆分成一个一个vue组件, 所以对于vue来说组件间的数据通信非常重要,那么组件之间如何进行数据通信的呢?

    首先我们需要知道在vue中组件之间存在什么样的关系, 才更容易理解他们的通信方式。

    一般我们分为如下关系:

    父子组件之间通信
    非父子组件之间通信(兄弟组件、隔代关系组件、跨层级组件等)

    vue如何进行组件间的通信

    Vue2.x 组件通信共有12种

    1. props
    2. $emit / v-on
    3. .sync
    4. v-model
    5. ref
    6. $children / $parent
    7. $attrs / $listeners
    8. provide / inject
    9. EventBus
    10. Vuex
    11. $root
    12. slot
    13. 路由传参
    14. observable

    父子组件通信可以用:

    • props
    • $emit / v-on
    • $attrs / $listeners
    • ref
    • .sync
    • v-model
    • $children / $parent

    兄弟组件通信可以用:

    • EventBus
    • Vuex
    • $parent

    跨层级组件通信可以用:

    • provide/inject
    • EventBus
    • Vuex
    • $attrs / $listeners
    • $root

    Vue2.x 组件通信使用写法

    下面把每一种组件通信方式的写法一一列出

    1. props

    父组件向子组件传送数据,这应该是最常用的方式了

    子组件接收到数据之后,不能直接修改父组件的数据。会报错,所以当父组件重新渲染时,数据会被覆盖。如果子组件内要修改的话推荐使用 computed

    格式:

    // 数组:不建议使用
    props:[]
    
    // 对象
    props:{
     inpVal:{
      type:Number, //传入值限定类型
      // type 值可为String,Number,Boolean,Array,Object,Date,Function,Symbol
      // type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认
      required: true, //是否必传
      default:200,  //默认值,对象或数组默认值必须从一个工厂函数获取如 default:()=>[]
      validator:(value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
     }
    }
    

    事例:

    // Parent.vue 传送
    
    
    // Child.vue 接收
    export default {
      // 写法一 用数组接收
      props:['msg'],
      // 写法二 用对象接收,可以限定接收的数据类型、设置默认值、验证等
      props:{
          msg:{
              type:String,
              default:'这是默认数据'
          }
      },
      mounted(){
          console.log(this.msg)
      },
    }
    

    注意:

    prop 只可以从上一级组件传递到下一级组件(父子组件),即所谓的单向数据流。而且 prop 只读,不可被修改,所有修改都会失效并警告。

    • 第一,不应该在一个子组件内部改变 prop,这样会破坏单向的数据绑定,导致数据流难以理解。如果有这样的需要,可以通过 data 属性接收或使用 computed 属性进行转换。
    • 第二,如果 props 传递的是引用类型(对象或者数组),在子组件中改变这个对象或数组,父组件的状态会也会做相应的更新,利用这一点就能够实现父子组件数据的“双向绑定”,虽然这样实现能够节省代码,但会牺牲数据流向的简洁性,令人难以理解,最好不要这样去做。
    • 想要实现父子组件的数据“双向绑定”,可以使用 v-model 或 .sync。

    props与$emit

    2. $emit / v-on

    子传父的方法,子组件通过派发事件的方式给父组件数据,或者触发父组件更新等操作

    // Child.vue 派发
    export default {
      data(){
          return { msg: "这是发给父组件的信息" }
      },
      methods: {
          handleClick(){
              this.$emit("sendMsg",this.msg)
          }
      },
    }
    // Parent.vue 响应
    
    
    export default {
        methods:{
            getChildMsg(msg){
                console.log(msg) // 这是父组件接收到的消息
            }
        }
    }
    

    3. v-model

    和 .sync 类似,可以实现将父组件传给子组件的数据为双向绑定,子组件通过 $emit 修改父组件的数据

    // Parent.vue
    
    <script>
    export default {
        data(){
            return {
                value:1
            }
        }
    }
    
    // Child.vue