Customize v-Model bidirectional binding in Vue

⭐️ more front-end technology and knowledge, search subscription number JS bacteria subscription

The V-Model two-way binding is actually a way of issuing input events through the $emit method in the child component. The parent component listens for the value passed in the input event and stores it in the parent component data. The parent component then passes the value to the child component as a prop, binding the value property of the input to the child component.

Let’s go ahead and implement it:

Child components pass values

First, the child component needs an input tag, which is bound to an input event. $emit fires the parent component’s input event, passing the value to the parent

<input type="text" @input="$emit('input', $event.target.value)">
Copy the code

The parent component listens for an input event and then passes the value of the input input carried by the event into the data state

<my-comp @input="value = $event"></my-comp>
Copy the code
export default {
  // ...
  data () {
    return {
      value: 'initial value' // Maintain a value state}}}Copy the code

At this point, the child listens for an input event, and the user input string is retrieved by the parent and stored in the data state

The parent component passes values

The parent component then passes the value to the child component, which then binds the value to the value property of the input

<my-comp :value="value" @input="value = $event"></my-comp>
Copy the code

Added :value=”value” to pass value through prop

The value property of the input is bound to the child component

<input type="text" @input="$emit('input', $event.target.value)" :value="value">
Copy the code

Note that value needs to be set in props

export default {
  name: 'MyComp'.props: ['value']}Copy the code

At this point, the custom V-model processing is complete, look at the effect:

Other elements use v-models

Using the V-Model on input is simple, but consider that other elements don’t necessarily listen for input events but for change events, and don’t necessarily change the content of the element with the value attribute. For example, checkbox, we need to listen for the change event, as well as the Checked property.

So first implement manually:

<input type="checkbox" @change="$emit('change', $event.target.checked)" :checked="checked">
Copy the code

The child component first listens for the change event, and the $emit method fires the parent component’s change event, passing the checked property value to the parent. It also receives the checked value passed in by the parent component, which determines the checked attribute of the input element.

export default {
  name: 'MyComp'.props: ['checked']}Copy the code

Then you need to modify the parent component:

<my-comp @change="checked = $event"></my-comp>
Copy the code
export default {
    // ...
  data () {
    return {
      checked: false}}}Copy the code

The parent component listens for the change event and maintains the state checked in data, which defaults to false

Finally, look at the results:

Use the V-model instruction directly

Alternatively, the V-model directive can be used directly:

<my-comp v-model="checked"></my-comp>

But you need to modify the V-model directive in the component to specify prop and Event:

export default {
  name: 'MyComp'.props: ['checked'].model: {
    prop: 'checked'.event: 'change'}}Copy the code

Please pay attention to my subscription number, push technical articles about JS irregularly, only talk about technology not gossip 😊