Vue父子组件双向数据绑定

[本文出自天外归云的博客园]

简介

Vue版本:2.9.6

Element版本:2.4.8

问题描述:子组件对Element中el-select进行封装,父组件中把选中的值selected和所有选项options传给子组件,当子组件中选中的option发生改变时,通知父组件并更新父组件中的selected值

问题本质:在子组件中接收父组件中传递过来的值A,当值A在子组件中发生改变,通知父组件并在父组件中更新值A

代码

1. 父组件中引入并调用子组件,传给子组件fatherSelected和fatherOptions两个变量值,内容如下:

<template>
  <div>
    <SelectOption :selected.sync="fatherSelected"
                  :options="fatherOptions"></SelectOption>
  </div>
</template>

<script>
import { SelectOption } from '@/components/common'

export default {
  name: 'Father',
  data () {
    return {
      fatherOptions: [{'label': 'lab1', 'value': 'val1', 'id':'id1'}, {'label': 'lab2', 'value': 'val2', 'id':'id2'}],
      fatherSelected: ''
    }
  }
}
</script>

2. 路径'@/components/common'下创建一个index.js文件导出子组件,内容如下:

export { default as SelectOption } from './SelectOption'

3. 子组件,用props定义从父组件接收传参的变量selected和options,内容如下:

<template>
  <div class="selectOption">
    <el-select v-model="mySelected"
               filterable
               @change="changeSelected">
      <el-option v-for="option in options"
                 :key="option.id"
                 :label="option.label"
                 :value="option.value">
      </el-option>
    </el-select>
  </div>
</template>
<style>
.selectOption {
  margin-top: 30px;
}
</style>
<script>
export default {
  props: ['selected', 'options'],
  data: function () {
    return {
      mySelected: this.selected
    }
  },
  methods: {
    changeSelected: function () {
      this.$emit('update:selected', this.mySelected)
    }
  }
}
</script>

注意事项

1. 子组件中接收父组件的值selected后,一定要保存到子组件作用域中的一个变量mySelected中

2. 当mySelected的值发生改变,@change监听会触发函数changeSelected执行

3. 通过thie.$emit来通知父组件进行update入参selected的值,对应更新父组件中的fatherSelected变量值

4. 对于允许子组件通知并进行改变的值fatherSelected一定要加 ".sync" 处理

5. 特别需要注意的是,假如selected的值在父组件中是异步获取的,还需要在子组件中对父组件的传值props中的selected变量加上watch监听,以便针将父组件中的变量值变化同步到子组件中,把上面的script部分代码更新为下面这段:

<script>
export default {
  props: ['selected', 'options'],
  data: function () {
    return {
      mySelected: this.selected
    }
  },
  methods: {
    changeSelected: function () {
      this.$emit('update:selected', this.mySelected)
    }
  },
  watch: {
    selected: function () {
      this.mySelected = this.selected
    }
  }
}
</script>

这样一旦父组件中的值异步更新后,子组件监听到父组件传递的selected变量值发生变化时就会自动更新子组件中的mySelected变量值。注意!手动的改变option的值是触发子组件中的@change事件,而父组件中的传值异步更新并不会触发子组件的@change事件。所以总结如下:

1. @change触发的事件在是在子组件的变量值发生变化时更新给父组件中对应的变量值用的

2. 子组件中的watch变量值是在父组件props的变量值发生变化时更新给子组件用的

posted @ 2018-10-28 17:18  天外归云  阅读(753)  评论(0编辑  收藏  举报