总结-vue组件双向传值改变的方式

601 阅读1分钟

注:四种方式效果并无差异,仅写法不同
简单需求:

  • 当B组件下拉框改变的时候,将内容设置给A组件input
  • 同时,当A组件的值改变的时候,组件B的值也改变

方式一

通过props+$emit传递
组件index.vue

// index.vue
<template>
 A:
 <inner :query="query" @queryChange="value = $event"/>
 <el-divider></el-divider>
 B:
 <el-select v-model="value" placeholder="请选择" @change="handleChange">
   <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item"></el-option>
 </el-select>
</template>

<script>
 data () {
    return {
        query: ''
    }
 },
 methods: {
   handleChange (val) {
    // 当下拉框改变的时候,将值赋值给query
    this.query = val.label
   }
 }
</script>

组件inner.vue

// inner.vue
<template>
  <div>
    <el-input v-model="inputText"></el-input>
  </div>
</template>

<script>
  props: {
    query: {
     type: String,
     default: ''
    }      
  },
  data () {
    return {
     inputText: ''
    }
  },
 
  watch: {
    query (v) {
     // 监听query发生改变了之后,将值传递给inputText
     this.inputText = v
    },
    inputText (v) {
    // 监听inputText发生改变之后,通过$emit传递出去
    this.$emit('queryChange', v)
    }
  }
</script>

方式二

通过.sync修饰符+update方式

 // 只需要将query传递给inner组件的时候
 <inner :query.sync="value.label"/>
 // inner组件在input的值改变之后
  watch: {
    inputText (v) {
      this.$emit('update:query', v)
    }
  }

方式三

通过v-model写法替代双向传递

// index.vue
<inner v-model="value.label" />
// inner.vue
<el-input :value="value" @input="handleInput"></el-input>
props: {
 value: {
   type: String,
   default: null
  }
 },
 methods: {
  handleInput (v) {
   this.$emit('input', v)
  }
 }

方式四

通过refs调用inner组件的方法改变inner组件里面的值

// index.vue
 A:
   <inner ref="inner" @inputChange="value.label = $event" />
   <el-divider></el-divider>
 B:
   <el-select v-model="value" placeholder="请选择" @change="handleChange">
    <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item"></el-option>
   </el-select>
 <script>
    methods: {
     handleChange (item) {
      this.query = item.label
      this.$refs['inner'].setQuery(item.label)
     }
    }
 </script>
// inner.vue
<template>
  <el-input v-model="inputText"></el-input>
</template>
watch: {
    inputText (v) {
      this.$emit('inputChange', v)
    }
  },