Problems and solutions encountered when using v-model to two-way bind the values ​​of parent-child components in Vue

Problems and solutions encountered when using v-model to two-way bind the values ​​of parent-child components in Vue

Scenario

Today, I encountered a strange problem when using v-model for two-way data binding of components. The webpage itself ran normally, but the browser kept showing warning messages.

[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 caused 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 are using seems to be fine?

<main id="app">
 The currently 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, "Confidential").set(2, "Male").set(3, "Female"),
 sex: "",
 },
});

After testing, the program itself runs normally, there is no problem with the value transfer between parent and child components, and the two-way data binding does take effect, but the browser keeps reporting an error.

Try to solve

We found a way

  1. For variables that require two-way binding, declare a variable innerValue in the component data and initialize it to value
  2. Use v-model on select to bind this variable innerValue
  3. Monitor changes in value and modify the value of innerValue when value changes in the parent component
  4. Monitor changes in innerValue and use this.$emit('change', val) to tell the parent component that value needs to be updated when it changes.
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>
 `,
});

The usage code is exactly the same, but the code of the component RxSelect is much longer. . .

solve

A more elegant way is to use computed properties and their get/set , but the amount of code added is 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 details of the problems and solutions encountered when Vue uses v-model to two-way bind the values ​​of parent and child components. For more information about Vue using v-model to two-way bind the values ​​of parent and child components, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • Example code of vue custom component to implement v-model two-way binding data
  • The use of v-model in vue3 components and in-depth explanation
  • Detailed explanation of the difference between v-model directive and .sync modifier in Vue
  • A brief discussion on the principle of Vue's two-way event binding v-model
  • Vue uses v-model to encapsulate the entire process of el-pagination components
  • Basic implementation method of cross-component binding using v-model in Vue
  • Solution for Vue form input box not supporting focus and blur events
  • Detailed usage of Vue's form input component using custom events [Date component and currency component]
  • Example code for Vue form input binding
  • Vue form input formatting Chinese input method abnormality
  • Vue form input binding v-model

<<:  MySQL uses triggers to solve the row limit of the table in the database. Detailed explanation and examples

>>:  Detailed explanation of three ways to configure Nginx virtual hosts (based on ports)

Recommend

Realizing tree-shaped secondary tables based on angular

First look at the effect: Code: 1.html <div cl...

404 error occurs when accessing the homepage of tomcat started in Docker mode

Scenario: When starting tomcat in docker (version...

Steps to deploy hyper-V to achieve desktop virtualization (graphic tutorial)

The hardware requirements for deploying Hyper-V a...

I have sorted out some domestic design websites that I think are good.

<br />I have compiled some domestic design w...

Vue3 uses axios interceptor to print front-end logs

Table of contents 1. Introduction 2. Use axios in...

Summary of a CSS code that makes the entire site gray

In order to express the deep condolences of peopl...

A detailed introduction to Linux file permissions

The excellence of Linux lies in its multi-user, m...

Examples of using the Li tag in HTML

I hope to align the title on the left and the dat...

Nginx's practical method for solving cross-domain problems

Separate the front and back ends and use nginx to...

CSS3 overflow property explained

1. Overflow Overflow is overflow (container). Whe...

Steps to change mysql character set to UTF8 under Linux system

Table of contents 1. Check the MySQL status in th...

Brief analysis of MySQL union and union all

In the database, both UNION and UNION ALL keyword...

Analysis of pitfalls in rounding operation of ROUND function in MySQL

This article uses examples to illustrate the pitf...

Pure CSS drop-down menu

Achieve results Implementation Code html <div ...