通过v-model‘实现’组件双向数据绑定

原创
2019/05/12 18:03
阅读数 587
AI总结

单向数据流

  • 单向数据流是Vue组件一个非常明显的特征,不应该在子组件中直接修改props的值
  • 如果传递的prop仅仅用作展示,不涉及修改,则在模板中直接使用即可
  • 如果需要对prop的值进行转化然后展示,则应该使用computed计算属性
  • 如果prop的值用作初始化,应该定义一个子组件的data属性并将prop作为其初始值

组件之间的通信

  • 父子组件的关系可以总结为 prop 向下传递,事件event向上传递
  • 祖先组件和后代组件(跨多代)的数据传递,可以使用provideinject来实现
  • 跨组件或者兄弟组件之间的通信,可以通过eventBus或者vuex等方式来实现

封装的组件如何实现v-model的数据双绑的效果

以下两种通常是我们的实现方式, 看着就很麻烦

  1. 通过emit将事件派发到父组件,prop将数据传到子组件

    每个父组件都要实现changeValue方法来接收数据并更新数据

    // 子组件
    <template>
    <div>
    <van-button @click="add" type="default">加一</van-button>
    <div>
        {{countsVal}}
    </div>
    <van-button @click="reduce" type="default">减一</van-button>
    </div>
    </template>

    <script>
        export default {
            props: {
                value: Number
            },
			  model: {
			  prop: 'value',
			  event: 'input'
			},
            data () {
                return {
                // props的初始化比data的初始化要靠前
                countsVal: this.value
                }
            },
            methods: {
                add () {
                    this.countsVal++
                    this.$emit('add', this.countsVal)
                },
                reduce() {
                    this.countsVal--
                    this.$emit('reduce', this.countsVal)
                }
            }
        };
    </script>

    // 父组件
    <template>
        <div>
                <counter :value='value' @add='changeValue' @reduce='changeValue'/>
        </div>
    </template>

    <script>
        export default {
            data () {
                return {
                value: 10
                }
            },
            methods: {
                changeValue (data) {
                    this.value = data
                }
            }
        };
    </script>
  1. 将加减执行的回到函数通过父组件传到子组件中实现改变数据

    每个父组件都要实现addreduce两个方法

    // 子组件
    <template>
    <div>
    <van-button @click="add" type="default">加一</van-button>
    <div>
        {{countsVal}}
    </div>
    <van-button @click="reduce" type="default">减一</van-button>
    </div>
    </template>

    <script>
    export default {
        props: {
            value: Number,
            add: Function,
            reduce: Function
        }
    };
    </script>
    
    // 父组件
    <template>
    <div>
    <counter :value='value' :add='add' :reduce='reduce'/>
    </div>
    </template>

    <script>
        export default {
            data () {
                return {
                value: 10
                }
            },
            methods: {
                add (data) {
                    this.value++
                },
                reduce (data) {
                    this.value--
                }
            }
        };
    </script>

通过v-model语法糖实现,父子组价的数据双绑

Vue内置了v-model指令,v-model 是一个语法糖,可以拆解为 props: value 和 events: input。就是说组件只要提供一个名为 value 的 prop,以及名为 input 的自定义事件,满足这两个条件,使用者就能在自定义组件上使用 v-model,戳这里看model配置

// 子组件
  <template>
      <div>
          <van-button @click="changeVal(1)" type="default">加一</van-button>
          <div>
              {{countsVal}}
          </div>
          <van-button @click="changeVal(-1)" type="default">减一</van-button>
      </div>
  </template>

  <script>
  export default {
      props: {
          value: Number
      },
      data () {
          return {
          // props的初始化比data的初始化要靠前
          countsVal: this.value
          }
      },
      methods: {
          changeVal (data) {
          this.countsVal += parseInt(data)
          this.$emit('input', this.countsVal)
          }
      }
  }
  </script>
  // 父组件只需要通过v-model将数据传进去就好了
  <template>
      <div>
          <counter v-model='counts'/>
      </div>
  </template>

  <script>
      import counter from './base/counter'
      export default {
          components: {
              counter
          },
          data () {
              return {
              counts: 10
              }
          }
      }
  </script>
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
AI总结
返回顶部
顶部