Home  >  Article  >  Web Front-end  >  Let’s talk about how to implement two-way binding in Vue without using v-model?

Let’s talk about how to implement two-way binding in Vue without using v-model?

青灯夜游
青灯夜游forward
2022-01-29 09:00:303308browse

What if two-way binding is not implemented through v-model in Vue? The following article will introduce to you how to achieve two-way binding without using v-model. I hope it will be helpful to you!

Let’s talk about how to implement two-way binding in Vue without using v-model?

#How to achieve two-way binding without using v-model?

Some people say that you have the nerve to ask such a novice question?

Don’t tell me, when I first learned vue, I was tortured to death by these problems. I bit the bullet and wrote according to the official website document demo. After I became able to use it, I also wrote a lot of v-model in daily development. After I made up my mind to study the related bugs carefully, I found that there are still many ways to do it. Let me explain in detail. [Related recommendations: vue.js video tutorial]

Let’s look at the answer first:

<template>
  <div class="test-v-model">
    <p>使用v-model</p>
    <input v-model="msg" placeholder="edit me" />
    <p>{{ msg }}</p>

    <p>不使用v-model</p>
    <input :value="msg1" @input="handleInput" placeholder="edit me" />
    <p>{{ msg1 }}</p>
  </div>
</template>

<script>
export default {
  name: &#39;test-v-model&#39;,
  data() {
    return {
      msg: &#39;&#39;,
      msg1: &#39;&#39;
    }
  },
  methods: {
    handleInput(e) {
      this.msg1 = e.target.value
    }
  }
}
</script>

Do not use v- model, you need to bind the value through the value attribute and change the binding value through the input event to achieve two-way binding.

In other words, v-model is just a shorthand form

In fact, the essence of v-model is syntactic sugar. It is responsible for monitoring user input events to update data. , and perform some special processing on some extreme scenes. -- Official documentation

v-model internally uses different properties for different input elements and throws different events:

  • text and textarea elements Use value property and input events;
  • checkbox and radio use checked property and change events;
  • The
  • select field will have value as prop and change as event.

Knowledge extension related to this question

  • Two-way binding
  • One-way data binding
  • vue component One-way data flow for interaction between

#Q: What is two-way binding?

#Two-way binding means that when the data changes, the view is updated synchronously. When the view changes, the data will also be updated.

Q: What is one-way data binding?

One-way data binding means when the data changes , the view is updated synchronously, and when the view changes, the data will not be updated.

In vue, two-way binding is achieved through the instruction v-model, and one-way data binding is achieved through v-bind

After reading the following code and the gif demonstration of this code running, you will be able to understand their differences.

<template>
  <div>
    <p>双向绑定</p>
    <input v-model="msg" placeholder="edit me" />
    <p>{{ msg }}</p>

    <p>单向数据绑定</p>
    <input v-bind:value="msg1" placeholder="edit me" />
    <p>{{ msg1 }}</p>
  </div>
</template>

<script>
export default {
  name: &#39;test-v-model&#39;,
  data() {
    return {
      msg: &#39;&#39;,
      msg1: &#39;&#39;
    }
  }
}
</script>

Let’s talk about how to implement two-way binding in Vue without using v-model?

As can be seen from the gif diagram, using v-model, when the data changes, the view is updated synchronously. When the view changes, the data will also be updated. This is Two-way binding.

Using v-bind, when the data changes, the view is updated synchronously. When the view changes, the data will not be updated. This is one-way data binding.

Q: What is vue one-way data flow?

A child component cannot change the prop attribute passed to it by the parent component. The recommended approach is for it to throw an event and notify the parent component to change the bound value on its own.
To sum up, data goes down and events go up.

The vue document puts forward the concept of one-way data flow when introducing Prop. Click here to view the vue document's description of one-way data flow.

All props form a One-way downward binding between their parent and child props: The update of the parent prop will flow downward to the child component, but in reverse Coming here is not possible. This will prevent the child component from accidentally changing the state of the parent component, making the data flow of your application difficult to understand.

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

Let’s look at the following example:

The subcomponent directly performs two-way binding on the prop value. What will happen?

Parent component code:

<template>
  <child-component :value="fatherValue" />
</template>

<script>
import ChildComponent from &#39;./child.vue&#39;

export default {
  name: &#39;father-component&#39;,
  components: {
    ChildComponent
  },
  data() {
    return {
      fatherValue: &#39;&#39;
    }
  }
}
</script>

Child component code:

<template>
  <div class="child-component">
    <input v-model="value" placeholder="edit me" />
    <p>{{ value }}</p>
  </div>
</template>

<script>
export default {
  name: &#39;child-component&#39;,
  props: {
    value: {
      type: String,
      default: &#39;&#39;
    }
  }
}
</script>

Let’s talk about how to implement two-way binding in Vue without using v-model?

Let’s talk about how to implement two-way binding in Vue without using v-model?

Let’s talk about how to implement two-way binding in Vue without using v-model?

可以看到,childComponent中的 prop 值可以实现双向绑定,但是 FatherComponent 中的 data 值并未发生改变,而且控制台抛出了警告:

[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"

翻译一下:避免直接改变 prop 值,因为每当父组件重新渲染时,该值将被覆盖。相反,使用基于 prop 值的 data 或 computed。

很显然,直接改变子组件的 prop 值的这种行为被 vue 禁止了。

如何操作传入子组件的 prop 值

但是很多时候,我们确实要操作传入子组件的 prop 值,该怎么办呢?

正如上面的警告所说,有两种办法:

  • 这个 prop 用来传递一个初始值,定义一个本地的 data property 并将这个 prop 用作其初始值
props: {
  initialCounter: {
    type: Number,
    default: 0
  },
},
data() {
  return {
    counter: this.initialCounter
  }
}
  • 这个 prop 以一种原始的值传入且需要进行转换,用这个 prop 的值来定义一个计算属性
props: {
  size: {
    type: String,
    default: &#39;&#39;
  }
},
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

这样不管怎么操作数据都是操作的子组件数据了,不会影响到父组件数据。

所以,我们想用 prop 传入的数据实现双向绑定,可以这么写:

父组件代码不变

子组件里用 innerValue 来接收传入的 value :

<template>
  <div class="child-component">
    <input v-model="innerValue" placeholder="edit me" />
    <p>{{ innerValue }}</p>
  </div>
</template>

<script>
export default {
  name: &#39;child-component&#39;,
  props: {
    value: {
      type: String,
      default: &#39;&#39;
    }
  },
  data() {
    return {
      innerValue: this.value
    }
  }
}
</script>

这里要注意一个问题

在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。

还是上面的例子,我们将传入的值改为对象:

父组件代码:

<template>
  <child-component :obj="fatherObj" />
</template>

<script>
import ChildComponent from &#39;./child.vue&#39;

export default {
  name: &#39;father-component&#39;,
  components: {
    ChildComponent
  },
  data() {
    return {
      fatherObj: {
        name: &#39;lin&#39;
      }
    }
  }
}
</script>

子组件代码:

<template>
  <div class="child-component">
    <input v-model="innerObj.name" placeholder="edit me" />
    <p>{{ innerObj.name }}</p>
  </div>
</template>

<script>
export default {
  name: &#39;child-component&#39;,
  props: {
    obj: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      innerObj: this.obj
    }
  }
}
</script>

Let’s talk about how to implement two-way binding in Vue without using v-model?

Let’s talk about how to implement two-way binding in Vue without using v-model?

这里的 this.obj 是引用类型,赋值给了 innerObj,所以 innerObj 实际上还是指向了父组件的数据,对 innerObj.name 的修改依然会影响到父组件

所以,处理这种引用类型数据的时候,需要深拷贝一下

import { clone } from &#39;xe-utils&#39;
export default {
  name: &#39;child-component&#39;,
  props: {
    obj: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      innerObj: clone(this.obj, true)
    }
  }
}

Let’s talk about how to implement two-way binding in Vue without using v-model?

如上图所示,这样子组件和父组件之间的数据就不会互相影响了。

总结

至此,终于把双向绑定和单向数据流讲清楚了,真的没想到,平时开发时都懂的概念,想讲清楚居然花了这么多篇幅,确实不容易,不过,这也是对自己的一种锻炼吧。

问:v-model是双向绑定吗?

是,但只是语法糖

问:v-model是单向数据流吗?

是,数据向下,事件向上

本题还有一些其他问法,比如:

  • vue 的双向绑定和单向数据流有什么区别?
  • 为什么说 vue 的双向绑定和单向数据流不冲突?

看完本篇文章,相信不管怎么问,你都能对这两个概念理解透彻了。

更多编程相关知识,请访问:编程入门!!

The above is the detailed content of Let’s talk about how to implement two-way binding in Vue without using v-model?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.cn. If there is any infringement, please contact admin@php.cn delete