在做项目的过程中,经常遇到父子组件通信的问题,现在对3种通信方式总结一下:

一、prop向下传递,emit向上传递

初始版本

父组件通过prop将数据传递给子组件,子组件通过emit事件将子组件数据传递给父组件

//父组件
<template>
    <div>
        <child :value='value' @getChildData='getChildData'></child>
         来自子组件的数据:<span>{{value}}</span>
    <div/>
</template>
<script>
data() {
      return {
        value: '父组件的数据'
      }
    },
methods:{
    getChildData(v){
        this.value = v
    }
}
</script>
//子组件child
<template>
    <input v-model='childValue' @input='childInputChange'></input>
</template>
<script>
props:{
    value:{
        type:String,//在props接受父组件传递数据
        default:''
    }
},
data(){
    return {
        childValue:this.value
    }
},
watch:{
    value(){
        this.childValue = this.value //监听父组件的数据,同步更新子组件数据
    }
   },
methods:{
    childInputChange(){
        this.$emit('getChildData',this.childValue) // 通过emit触发getChildData,将子组件数据传递给父组件
    }
</script>

二、v2.2.0+ 新增 v-model 通过v-model属性实现

//父组件
<template>
    <div>
        <child v-model='value'></child>
        // 等价于 默认给子组件传递参数value,子组件更新函数名update:value
        <child :value='value' @update:value='val=>{ value = val }'></child>
        // 在子组件中可以通过model配置
        //接受数据的名字fatherValue和触发事件的方法childValueChange 
        <child :fatherValue='value' @childValueChange = "val=>{ value = val }"></child>
         父子组件同步的数据:<span>{{value}}</span>
    <div/>
</template>
<script>
data() {
      return {
        value: '父组件的数据'
      }
    }
</script>
​
//子组件child
<template>
    <input type="text" v-model="childValue" @input="childInputChange"/>
</template>

<script>
    export default {
        name: "child",
        model: {  // 定义model
            prop: 'fatherValue',  // 父组件v-model绑定的值传递给props中的fatherValue
            event: 'childValueChange'  
            // 通过emit触发childValueChange将内部值传递给父组件v-model绑定的值
        },
        props: {
            fatherValue: String    // 接受父组件传递的值
        },
        data(){
            return {
                childValue: this.fatherValue// 关联值
            }
        },
        methods: {
            childInputChange(){ 
                // 通过$emit触发childValueChange(model内定义)事件,将内部值传递给给父组件
                this.$emit('childValueChange', this.childValue)
            }
        }
    }
</script>

​

vue3允许写多个v-model,vue2不允许写多个v-model 

//父组件
<template>
    <div>
        <child v-model:value1='dValue1' v-model:value2='dValue2'></child>
        // 等价于 默认给子组件传递两个值value1、value2
        // 子组件更新函数update:value1将接受到的参数赋值给dValue1
        // 子组件更新函数update:value2将接受到的参数赋值给dValue2
        <child :value1='dValue1' @update:value1='val=>{ dValue1= val }'
               :value1='dValue2' @update:value1='val=>{ dValue2= val }'
        ></child>
    <div/>
</template>
<script>
data() {
      return {
        dValue1: '父组件的数据1',
        dValue2: '父组件的数据2' 
      }
    }
</script>

三、sync修饰符(v2.3.0+ 新增)

// 父组件
<template>
    <div>
        我是父子组件之间同步的数据{{data}}
        <child :data.sync='data'></child>
    </div>
</template>
<script>
    data(){
      return {
        data:'我是来自父组件的数据'
      }
    }
</script>
//子组件
<template>
  <div>
    <input type="text" v-model="childData" @input="childDataChange">
  </div>
</template>

<script>
    props:{
      data:{
        default:'',
        type:String
      }
    },
    data(){
      return {
        childData:this.data //关联父组件的值
      }
    },
    watch:{
      data(){
        this.childData = this.data
      }
    },
    methods:{
      childDataChange(v){
        this.$emit('update:data',v) // 触发update:data将子组件值传递给父组件
      }
    }
</script>

vue3取消了.sync这种语法,使用v-model:title 语法代替

// 父组件
<template>
    <div>
        我是父子组件之间同步的数据{{data}}
// 父组件传递给子组件title属性(默认使用value)
// 通过update:title(默认使用update:value) 方法将子组件传递的值赋值给data
        <child v-model:title = data></child>
    </div>
</template>
<script>
    data(){
      return {
        data:'我是来自父组件的数据'
      }
    }
</script>
//子组件
<template>
  <div>
    <button @input="childDataChange">{{title}}</button>
  </div>
</template>

<script>
    props:{
      title:{
        default:'',
        type:String
      }
    },
    methods:{
      childDataChange(v){
        this.$emit('update:title',v) // 触发update:data将子组件值传递给父组件
      }
    }
</script>
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐