Problems and Solutions of vue Using v model Bidirectional Binding Parent child Component Values

  • 2021-11-01 01:50:19
  • OfStack

Directory scenario Try to solve Solve

Scene

In use today v-model I encountered a strange problem when carrying out bidirectional data binding of components. The web page itself runs normally, and a warning message appears in Browser 1.


[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "value"

This warning is raised by a custom component RxSelect


Vue.component("RxSelect", {
 model: {
 prop: "value",
 event: "change",
 },
 props: {
 value: [Number, String],
 map: Map,
 },
 template: `
  <select
   v-model="value"
   @change="$emit('change', value)"
  >
   <option
   v-for="[k,v] in map"
   :value="k"
   :key="k"
   >{{v}}</option>
  </select>
  `,
});

The code we use seems to be nothing wrong with the code?


<main id="app">
  The current selected gender is : {{map.get(sex)}}
 <div>
 <rx-select :map="map" v-model="sex" />
 </div>
</main>

JavaScript code


new Vue({
 el: "#app",
 data: {
 map: new Map().set(1, " Secrecy ").set(2, " Male ").set(3, " Female "),
 sex: "",
 },
});

After testing, the program itself runs normally, and the value transmission of father and son components is no problem. Bidirectional data binding does take effect, but the browser is 1 straight error.

Try to solve

We have found a way

Inside the component for variables that require bidirectional binding data Declare 1 variable innerValue And initialized to value In select Use on v-model Bind this variable innerValue Eavesdropping value In the parent component value Modify when changing innerValue Value of Eavesdropping innerValue Change, use when changing this.$emit('change', val) Tell the parent component that it needs to be updated value Value of

Vue.component("RxSelect", {
 model: {
 prop: "value",
 event: "change",
 },
 props: {
 value: [Number, String],
 map: Map,
 },
 data() {
 return {
  innerValue: this.value,
 };
 },
 watch: {
 value(val) {
  this.innerValue = val;
 },
 innerValue(val) {
  this.$emit("change", val);
 },
 },
 template: `
 <select v-model="innerValue">
 <option
  v-for="[k,v] in map"
  :value="k"
  :key="k"
 >{{v}}</option>
 </select>
 `,
});

Use code completely 1 sample, but component RxSelect There is a lot more code. . .

Solve

A more elegant way is to use computed Calculate properties and their get/set The degree of code increase is still acceptable


Vue.component("RxSelect", {
 model: {
 prop: "value",
 event: "change",
 },
 props: {
 value: [Number, String],
 map: Map,
 },
 computed: {
 innerValue: {
  get() {
  return this.value;
  },
  set(val) {
  this.$emit("change", val);
  },
 },
 },
 template: `
 <select v-model="innerValue">
 <option
  v-for="[k,v] in map"
  :value="k"
  :key="k"
 >{{v}}</option>
 </select>
 `,
});

The above is the vue use v-model bidirectional binding parent-child component value encountered problems and solutions in detail, more about vue use v-model bidirectional binding parent-child component value information please pay attention to other related articles on this site!


Related articles: