Vue2, vue3 components pass value, reference type, how to deal with object array

insert image description here

Vue2, vue3 components pass value, reference type, how to deal with object array

Excerpt

All props form a single downward binding between their parent and child props: updates to the parent prop flow down to the child components, but not the other way around. This will prevent accidental changes from child components to parent...


The following component pass-by-value refers to 引用类型(array or object) pass-by-value.
The principles of vue2 and vue3 are the same, if you have any questions, please leave a message.

Prepare: One-way data flow

All props form a relationship between their parent and child props 单向下行绑定: updates to parent props flow down to child components, but not the other way around. This prevents accidental changes to the parent component's state from child components, which can make your app's data flow difficult to understand.

In addition, every time the parent component changes, all props in the child component will be refreshed with the latest values. This means you should not change props inside a child component. If you do this, Vue will issue a warning in the browser's console.

  • This prop is used to pass an initial value; the child component then expects to use it as a local prop data. Define a local data property and use this prop as its initial value
props: ['initialCounter'], 
data: function () {
    
     
	return {
    
     
		counter: this.initialCounter 
	} 
}
  • This prop is passed in as a raw value and needs to be converted. Use the value of this prop to define a计算属性
props: ['size'], 
computed: {
    
     
	normalizedSize: function () {
    
    
		return this.size.trim().toLowerCase() 
	} 
}

Note that objects and arrays are passed in by reference in JavaScript, so for an array or object type prop, in 子组件中改变变更这个对象或数组本身将会影响到父组件的状态.

question

prop transfers application type data (objects, arrays), and changes in subcomponents will directly change the parent component

Parent component App.vue

<template>
  <div id="app">
    <child :initialValue="valueEmit">
    </child>
  </div>  
</template>  
<script>
import childEmit from './components/child.vue'
export default {
    
    
data () {
    
    
    return {
    
    
      valueEmit: {
    
    cat: 2}
    }
  },
  components: {
    
    
    child
  }
}        
</script>        

Child component components/child.vue

<template>
  <div class="child-container">
    <p> 
      <label>child:</label>
      <input type="text" v-model="value.cat" />
    </p>
  </div>
</template>
<script>
export default {
    
    
  name: 'child',
  props: {
    
    
    initialValue: Object
  },
  data () {
    
    
    return {
    
    
      value: this.initialValue
    }
  }
}
</script>

Question 2

To change the child component without affecting the parent component, you can make a deep copy of the reference type data, but the parent component data change will not trigger the child component to respond. Modify the child component
, child component components/child.vue

export default {
    
    
  name: 'child',
  props: {
    
    
    initialValue: Object
  },
  data () {
    
    
    return {
    
    
      valueEmit: JSON.parse(JSON.stringify(this.initialValue))
    }
  }
}

Summarize

In our development process, we generally encounter the following three situations:

  1. 纯展示Use parent component properties directly without side effects!
<template>
<div>
    {
    
    {
    
    parentObj.value}}
  </div>
</template>
<script>
export default {
    
    
    name: 'child',
    props: {
    
    
      parentObj: Object
    }
  }
</script>
  1. 只子组件内部修改, the parent component will not modify (that is, the parent component only initializes) the new data declared in the child component data, and the reference can be cut off by Object.assign()or JSON.parse(JSON.stringify()).
<template>
<div>
    <input type="text" v-model="childObj.value">
  </div>
</template>
<script>
export default {
    
    
    name: 'child',
    props: {
    
    
      parentObj: Object
    },
    data () {
    
    
      return {
    
    
        childObj: Object.assign({
    
    }, this.parentObj)
      }
    }
  }
</script>
  1. 父子组件都会修改Processing by computed or watch
<template>
<div>
    <input type="text" v-model="childObj.value">
  </div>
</template>
<script>
export default {
    
    
    name: 'child',
    props: {
    
    
      parentObj: Object
    },
    computed: {
    
    
      childObj () {
    
    
        return Object.assign({
    
    }, this.parentObj)
      }
    }
  }
</script>
或者 watch 方式

export default {
    
    
  name: 'child',
  props: {
    
    
    parentObj: Object
  },
  data () {
    
    
    return {
    
    
      childObj: {
    
    }
    }
  },
  watch: {
    
    
    parentObj: {
    
    
      handler (val, oldVal) {
    
    
        if (val) {
    
    
          this.childObj = Object.assign({
    
    }, this.parentObj)
        }
      },
      deep: true,
      immediate: true
    }
  }
}
  1. About the difference between watch and computed: the correct way to use vue computed

Guess you like

Origin blog.csdn.net/zqd_java/article/details/129257044