Vue.$set failure pitfall discovery and solution

Vue.$set failure pitfall discovery and solution

I accidentally found that Vue.$set was invalid in the project

There is a requirement to add data filtering. The left side is the control selection, the middle is the condition, and the right side is the value.

Because different value option controls will be rendered depending on the control

    <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)
    }
  }
  //...
}

Code Snippet

Due to the uncertainty of the control ID, all data cannot be preset with a key in advance, so it is naturally impossible to respond. Therefore, this.$set is used in onValueChange to dynamically add data to achieve response.

Reproduction can find that the data in the value input box cannot respond in real time

I used $set but it didn't respond. After some investigation, I found that the value would not respond after switching the control. However, as long as I input something before switching and then switch, there would be no problem.

After another investigation, we found

<el-select v-model="data[props.prop]" @change="data[props.value] = ''">

The problem is solved after deleting the @change event

The problem occurs when data[props.value] = ''

So check the Vue source code

//vue/src/core/observer/index.js source code snippet/**
 * Set a property on an object. Adds the new property and
 * triggers change notification if the property doesn't
 * already exists.
 */
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
}

It can be found that before defineReactive, it is determined whether the key exists in the object. If it exists, it is skipped.

The pit is here. I have read the Vue.$set document many times and did not find that $set cannot add monitoring objects to existing keys.

Delete data[props.value] = '' and change it to onValueChange('') ​​to solve the problem perfectly

Summarize

Before Vue.$set, the key must not exist in the object, otherwise it will only update the value and will not add response monitoring for the key

The above is my personal experience. I hope it can give you a reference. I also hope that you will support 123WORDPRESS.COM.

You may also be interested in:
  • Case study of dynamic data binding of this.$set in Vue
  • Vue——Solving the error Computed property "****" was assigned to but it has no setter.
  • Use of setup in vue3.0 (two ways of use)
  • A brief discussion on the precautions for using resetFields() in Vue
  • Vue's vue.$set() method source code case detailed explanation

<<:  Four modes of Oracle opening and closing

>>:  Overview of the Differences between Linux TTY/PTS

Recommend

XHTML Basic 1.1, a mobile web markup language recommended by W3C

W3C recently released two standards, namely "...

Zookeeper unauthorized access test problem

Table of contents Preface Detect Zookeeper servic...

Why MySQL does not recommend using subqueries and joins

To do a paginated query: 1. For MySQL, it is not ...

Learn MySQL in a simple way

Preface The database has always been my weak poin...

A brief discussion on the lock range of MySQL next-key lock

Preface One day, I was suddenly asked about MySQL...

HTML uses marquee to achieve text scrolling left and right

Copy code The code is as follows: <BODY> //...

Ubuntu 20.04 firewall settings simple tutorial (novice)

Preface In today's increasingly convenient In...

Tips for implementing multiple borders in CSS

1. Multiple borders[1] Background: box-shadow, ou...

Detailed explanation of the abbreviation of state in react

Preface What is state We all say that React is a ...

Implementation code of front-end HTML skin changing function

50 lines of code to change 5 skin colors, includi...

Is it true that the simpler the web design style, the better?

Original address: http://www.webdesignfromscratch...

Detailed explanation of Linux commands and file search

1. Perform file name search which (search for ...