zoukankan      html  css  js  c++  java
  • 给定制的vuejs组件添加v-model双向绑定支持

    用过vuejs的前端工程师,对于v-model一定印象深刻。它向类似textarea,input等原生html原生添加双向数据绑定的能力非常方便。但是对于你的定制vue组件并不是能够直接应用v-model的,我们需要做一些额外的工作,但是这个额外工作是非常简单的。

    为了理解如何给你的组件提供v-momeiydel支持,你应该深入地了解v-model本身底层是如何工作地。v-model初看起来就像是一个魔术,但是真的没有那么神秘。

    v-model="syncedProp"

    等价于以下代码

    :value="syncedProp" @input="syncedProp=$arguments[0] 或者
    :value="syncedProp" @input="syncedProp=$event.target.value

    理解了以上地两点,那么如果需要支持v-model,你自己的组件需要做的就是:

    1. 接收一个:value的property

    2. 当用户变更value值的时候发送一个@input事件

    基础实现:

    我们假设我们有一个date picker的组件,该组件接收year,month的value:{month:1,year:2019},我们希望该组件有两个输入Inputs,一个用于month,一个用于year,并且通过v-model来更新绑定的对象.这里是实现的例子代码:

    <template>
      <div class="date-picker">
        Month: <input type="number" ref="monthPicker" :value="value.month" @input="updateDate()"/>
        Year: <input type="number" ref="yearPicker" :value="value.year" @input="updateDate()"/>
      </div>
    </template>
    
    <script>
    export default {
      props: ['value'],
    
      methods: {
        updateDate() {
          this.$emit('input', {
            month: +this.$refs.monthPicker.value,
            year: +this.$refs.yearPicker.value
          })
        }
      }
    };
    </script>

    有了以上的实现代码后,我们就可以像下面的代码来使用它:

    <template>
      <div class="wrapper">
        <date-picker v-model="date"></date-picker>
        <p>
          Month: {{date.month}}
          Year: {{date.year}}
        </p>
      </div>
    </template>
    
    <script>
    import DatePicker from './DatePicker.vue';
    
    export default {
      components: {
        DatePicker
      },
    
      data() {
        return {
          date: {
            month: 1,
            year: 2017
          }
        }
      }
    })
    </script>

    总结以上范例代码,我们可以看到就做了两件事:

    1. 接受一个value这个prop,并通过该value prop传入的值在本组件中使用

    2. 当需要通知外部数据已经变化需要更新外部的绑定数据时,只需要emit一个input事件即可!

    高级一点的例子

    在上面基础版本基础上,我们把事情搞得稍微复杂一点,比如,我们传入的日期格式不是object形式,而时字符串形式mm/yyyy的格式,这时需要使用的化,必须要做进一步处理,同样地,当用户主动修改了数据修正外部地数据时,也需要再组合成一个字符串emit出去!

    <template>
      <div class="date-picker">
        Month: <input type="number" ref="monthPicker" :value="splitDate.month" @input="updateDate()"/>
        Year: <input type="number" ref="yearPicker" :value="splitDate.year" @input="updateDate()"/>
      </div>
    </template>
    
    <script>
    export default {
      props: ['value'],
    
      computed: {
        splitDate() {
          const splitValueString = this.value.split('/');
    
           return {
            month: splitValueString[0],
            year: splitValueString[1]
          }
        }
      },
    
      methods: {
        updateDate() {
          const monthValue = this.$refs.monthPicker.value;
          const yearValue = this.$refs.yearPicker.value;
          this.$emit('input', `${monthValue}/${yearValue}`);
        }
      }
    };
    </script>

    定制v-model所使用的prop和event

    如上面所说,v-model匹配的就是value属性以及input的事件上报,但是我们也可以修改这个默认的行为。

    其办法就是通过在我们的定制组件中,声明一个model对象,该model对象包含两个字段,一个prop,一个event分别用于对应的value和input事件

    比如下面的组件代码:

    export default {
      prop: ['cprop'],
      model: {
          prop: 'cprop',
          event: 'cevent'
      }
      methods: {
          handleInput (value) {
              this.$emit('cevent', value)
          }
      }
    }

    如果我们在html中像下面来使用:

    <basic-input v-model="email" />
    <!-- 等价于以下代码 -->
    <basic-input :cprop="email" @cevent="e => email = e.target.value" />
  • 相关阅读:
    maven junit.framework不存在问题解决
    maven项目在打war包时出现非法字符: 'ufeff' 解决方案
    如何隐藏tomcat命令窗口
    小程序如何生成开发版的带参二维码
    小程序码生成随记
    生活中的一些笔记
    存储过程
    项目出现 The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path 解决方法
    maven环境配置详解,及maven项目的搭建及maven项目聚合
    sqldeveloper和plsqldebeloper
  • 原文地址:https://www.cnblogs.com/kidsitcn/p/11585528.html
Copyright © 2011-2022 走看看