最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • vue自定义组件实现 v-model双向绑定数据

    正文概述 掘金(用户5950684015079)   2021-05-28   222

    项目中会遇到自定义公共组件供项目调用,正常情况可以使用 props定义参数接收父组件传的参数,然后通过子组件的$emits()方法回传数据给父组件。 类似如下: 父组件

    <common-checkbox :checked="goodsSelected" class="left" :height="'16px'" :width="'16px'"  @checkChange="checkChange"></common-checkbox>
    
    
         /**
         * 接收子组件回传进行处理
         */
        checkChange(value) {
          this.goodsSelected=value//子组件数据赋值给父组件
        }
    

    子组件

        /**
         * 切换选中回传
         */
        toggleCheck(value) {
          this.$emit('changeCheck', value)//回传方法,把子组件变化后的数据回传给父组件处理
        }
    

    但是这种写法需要调用公共组件的页面额外写处理的方法,而且显得太low,我们可不可以像是框架自带的公共组件一样去声明直接v-model双向绑定呢?接下来提供项目中实际遇到这种情况的处理方法 第一种方式: 正常情况下当你在父组件里给子组件绑定 v-model属性时,子组件中会默认的将 v-model绑定的数据,付给子组件 名为 value的props属性,value依然需要提前在子组件props中声明,否则接收不到。 当 value修改后,并不会立即双向回传给父组件。如果想回传实现同步更新父组件的v-model需要如下操作

     this.$emit('input', value) 
    

    当未声明双向绑定回传的事件时,默认通过input事件回传,为什么说 “当未声明双向绑定回传的事件”,这个便是第二种方式,下面会讲到。 简单来说,第一种方式的实现,首先是v-model绑定父组件数据 ,然后子组件value 的props属性自动接收,最后当数据更改后调用this.$emit('input', value) 回传父组件,这样父组件不需要额外实现子组件的回传就可以实现双向绑定 第二种方式: 前面提到 “当未声明双向绑定回传的事件” 默认使用 input回传,既然这样说了那就存在,如果我不用input呢?这就需要了解vue的一个特殊的属性:model, 这个属性可以用来声明 子组件用哪个字段去接收双向绑定的数据,以及用哪个方法回调更新父组件v-model的数据,写法如下:

    export default {
      name: 'CommonCkeckBox',
      model: {
        prop: 'checked',
        event: 'changeCheck'
      },
        props: {
        checked: {
          type: Boolean,
          default: false,
        }, // 选中状态
      }
      }
    

    这种写法就意味着,父组件 双向绑定的数据会绑定到子组件名为checked的props属性,并且,当子组件调用this.$emit('changeCheck', value)时,会同步的更新父组件的数据,实现双向绑定。 接下来附一段自定义checkbox的代码以作参考:

    <template>
    <div class="check-box-container"  @click="toggleCheck()" :style="{width:width,height:height}">
            <div class="checkbox-icon">
                  <!-- 三种状态 选中  未选  禁用 -->
                  <img alt :src="`${$cdnImageUrl}/cart/icon-selected.png`" :width="width" :height="height" key="select" v-if="checked&&!disabled"/>
                  <img alt :src="`${$cdnImageUrl}/cart/icon-unselected.png`" :width="width" :height="height" key="unselected" v-if="!checked&&!disabled" />
                  <img alt :src="`${$cdnImageUrl}/cart/icon-unselected.png`" :width="width" :height="height" class="disabled" key="unselected"  v-if="disabled"/>
                </div>
            <slot></slot>
    </div>
    </template>
    <script>
    /**
     * 全局统一弹窗
     */
    export default {
      name: 'CommonCkeckBox',
      model: {
        prop: 'checked',
        event: 'changeCheck'
      },
      props: {
        checked: {
          type: Boolean,
          default: false,
        }, // 选中状态
        disabled: {
          type: Boolean,
          default: false,
        }, // 是否禁用
        width: {
          type: String,
          default: '16px',
        }, // 按钮默认宽度
        height: {
          type: String,
          default: '16px',
        }, // 按钮默认高度
      },
      created() {
      },
      data() {
        return {
        }
      },
      methods: {
        /**
         * 切换选中回传
         */
        toggleCheck() {
          this.$emit('changeCheck', !this.checked)
          this.$emit('toggleCheck')
        }
      },
      watch: {
        checked: {
          handler(newValue, oldValue) {
          // 开放状态变更事件
            this.$emit('onChange')
          },
          deep: true
        }
      },
    }
    </script>
    <style lang="scss"  scoped>
    .check-box-container{
        display: inline-block;
        .checkbox-icon{
            img{
              transform: translateZ(0);
              will-change: auto;
            }
            .disabled{
              background-color:#f5f5f5;
              border-radius: 50%;
            }
        }
    }
    </style>
    

    父组件:

          <common-checkbox v-model="item.goodsSelected" class="left" :width="'16px'"  :height="'16px'"></common-checkbox>
    

    具体用哪种方式根据项目场景选择,若第一种不满足需求,可以尝试第二中实现。


    起源地 » vue自定义组件实现 v-model双向绑定数据

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元