当前位置:编程学习 > > 正文

vue设置属性没响应(Vue.$set 失效的坑 问题发现及解决方案)

时间:2021-10-13 00:51:50类别:编程学习

vue设置属性没响应

Vue.$set 失效的坑 问题发现及解决方案偶然在项目中发现Vue.$set失效

vue设置属性没响应(Vue.$set 失效的坑 问题发现及解决方案)

有这样一个需求 添加数据过滤用 左边是控件选择 中间是条件 右边是值

因为会根据控件不同渲染不同的值选项控件

  •     <el-form inline >
          <el-form-item style="margin-bottom: 20px;">
            <el-select v-model="data[props.prop]" @change="data[props.value] = ''">
              <el-option
                v-for="item in controls"
                :key="item.id"
                :value="item.id"
                :label="item.label">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item style="margin-bottom: 20px;">
            <el-select v-model="data[props.type]">
              <el-option
                v-for="item in condition"
                :key="item.code"
                :value="item.code"
                :label="item.name"
              ></el-option>
            </el-select>
          </el-form-item>
          <el-form-item style="margin-bottom: 20px;">
            <FormControl v-if="control" :control="control" :value="data[props.value]" @input="onValueChange" ></FormControl>
            <el-input v-else :value="data[props.value]" @input="onValueChange"></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="el-icon-plus" @click="add"></el-button>
          </el-form-item>
        </el-form>
    
  • {
      props:{
        props: {
          type: Object,
          default: () => ({
            prop: 'prop',
            value: 'value',
            type: 'type'
          })
        }
      },
      data(){
        return {
          data:{
            
          }
        }
      },
      methods:{
        onValueChange(val){
          this.$set(this.data, this.props.value, val)
        }
      }
      //...
    }
    
  • 代码片段

    由于控件ID的不确定性 所有 data并不能提前预设好key 自然无法响应 所以在onValueChange 使用了this.$set动态添加数据实现响应

    vue设置属性没响应(Vue.$set 失效的坑 问题发现及解决方案)

    复现可以发现 值输入框内的数据并不能实时响应

    明明用了$set却不能响应 一番排查后发现只要切换控件后 value值就不能响应 但是只要在切换前随便输入点啥 再切换就没问题

    又是一番排查后发现

  • <el-select v-model="data[props.prop]" @change="data[props.value] = ''">
    
  • 删除@change事件后故障解决

    问题出现在 data[props.value] = ''

    遂查看Vue源码

  • //vue/src/core/observer/index.js 源码片段 
     
    /**
     * Set a property on an object. Adds the new property and
     * triggers change notification if the property doesn't
     * already exist.
     */
    export function set (target: Array<any> | Object, key: any, val: any): any {
      if (process.env.NODE_ENV !== 'production' &&
        (isUndef(target) || isPrimitive(target))
      ) {
        warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`)
      }
      if (Array.isArray(target) && isValidArrayIndex(key)) {
        target.length = Math.max(target.length, key)
        target.splice(key, 1, val)
        return val
      }
      if (key in target && !(key in Object.prototype)) {
        target[key] = val
        return val
      }
      const ob = (target: any).__ob__
      if (target._isVue || (ob && ob.vmCount)) {
        process.env.NODE_ENV !== 'production' && warn(
          'Avoid adding reactive properties to a Vue instance or its root $data ' +
          'at runtime - declare it upfront in the data option.'
        )
        return val
      }
      if (!ob) {
        target[key] = val
        return val
      }
      defineReactive(ob.value, key, val)
      ob.dep.notify()
      return val
    }
    
  • 可以发现 在defineReactive之前 判断了key是否存在于对象之内 若存在就跳过了

    坑就在这 多次翻阅Vue.$set文档并未发现$set不能为已存在的key添加监测对象

    删除 data[props.value] = '' 改为 onValueChange('') 完美解决问题

    vue设置属性没响应(Vue.$set 失效的坑 问题发现及解决方案)

    总结

    Vue.$set之前一定要对象内key不存在 不然只会更新值 并不会为该Key添加响应监测

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持开心学习网。

    标签:
    上一篇下一篇

    猜您喜欢

    热门推荐