Use and in depth explanation of v model in vue3 component

  • 2021-11-23 21:57:30
  • OfStack

Bidirectional binding data is used in the directory v-model input v-model in Component Other writing Summarize

Bi-directional binding data in v-model input

v-model in vue, we often use it to bind with the input value of input input box. The simple implementation principle should be known to all. Bind value value through v-bind and dynamically change the bound value value in combination with @ input input event to realize bidirectional binding. The following vue3 implementation code:


<template>
   <input type="text" :value="tryText" @input="handelInput">
   <h2>{{tryText}}</h2>
</template>

<script>
import { ref} from "vue"
    export default {
        setup(){
            let tryText = ref(" Default input value ")
            function handelInput(e) {
                tryText.value = e.target.value;//ref The defined data access and modification needs to be passed through .value
            }
            return{
                tryText,
                handelInput
            }
        }
    }
</script>

v-model is often used in ipnut. Now let's look at how v-model is used in components and what it does

v-model in Component

How to use v-model in the component? Let's simply implement it

Parent component


<template>
  <!--  Component binding  v-model -->
  <hy-input v-model="message"></hy-input>
  <h2>{{message}}</h2>
</template>

<script>
import {  ref } from '@vue/reactivity'
import HyInput from "../components/HyInput.vue"
export default {
  components: {HyInput },
    setup(){
        let message = ref(" Hey hey hey (*^ー^)(^ー^*) Use ")
        return{
            message,
        }
    }
}
</script>

Subcomponent


<template>
   <button @click="handelClick">O( STH _ STH )O Ha ha ~</button>
   <br>
</template>

<script>
    export default {
        props:{
            modelValue:String,
        },
        emits:['update:modelValue'],
        setup(props,context){
            function handelClick() {
                context.emit("update:modelValue","O( STH _ STH )O Ha ha ~")
            }
        
            return{
                handelClick,
            }
        }
    }
</script>

Seeing this, we may have some doubts. Why did we launch the event? Why is there a default props receive value? Don't worry, we can understand it by looking at the implementation principle

In this way, we can change the data of message in the parent component by clicking the button of the child component, which is the implementation of data bidirectional binding v-model in a simple component

Since it is a two-way binding, might as well boldly guess whether it is similar to the implementation principle in input? Let's look at how it works

Parent component


<template>
  <!--  Principle  -->
  <hy-input :modelValue="message" @update:modelValue="message = $event"></hy-input>
  <h2>{{message}}</h2>
</template>

<script>
import {  ref } from '@vue/reactivity'
import HyInput from "../components/HyInput.vue"
export default {
  components: {HyInput },
    setup(){
        let message = ref(" Hey hey hey (*^ー^)(^ー^*) Use ")
        return{
            message,
        }
    }
}
</script>

Subcomponents remain unchanged


<template>
   <button @click="handelClick">O( STH _ STH )O Ha ha ~</button>
   <br>
</template>

<script>
    export default {
        props:{
            modelValue:String,
        },
        emits:['update:modelValue'],
        setup(props,context){
            function handelClick() {
                context.emit("update:modelValue","O( STH _ STH )O Ha ha ~")
            }
        
            return{
                handelClick,
            }
        }
    }
</script>

From the results, we found that it can be realized

In this way, we can well understand the sending events and default receiving values in sub-components. The basic implementation principle is: the parent component sends values to the sub-components, and the sub-components receive them through props. However, when the data needs to be modified in the sub-components, we tell the parent component by sending an event, and then the parent component receives the transmitted values for modification. In fact, it is the communication between parent and child components, but vue helps us to do a simple encapsulation.

ps: The default v-model binding data needs to use modelValue to receive the transmitting event when reading the sub-component. The default name is update: modelValue. If you want to bind multiple values or use custom names, please see the following other writing methods

ps: You can't modify data by modifying props. First of all, this is a particularly bad development habit. Then we know that the features of props are only responsible for transferring data, and modifying props can't achieve the desired effect. We should notify the parent component to update the data, which is the best practice.

Other writing

If the input in our child component is bound bidirectionally to the parent component, how can it be implemented? And the need to pass multiple bidirectional bound data? What about custom names?
Parent component


<template>
  <!--  Component binding  v-model -->
  <hy-input v-model="message" v-model:text="inputText"></hy-input>
  <h2>{{message}}</h2>
  <h2>{{inputText}}</h2>
</template>

<script>
import {  ref } from '@vue/reactivity'
import HyInput from "../components/HyInput.vue"
export default {
  components: {HyInput },
    setup(){
        let message = ref(" Hey hey hey (*^ー^)(^ー^*) Use ")
        let inputText = ref(" Hee hee hee ")
  
        return{
            message,
            inputText
        }
    }
}
</script>

Subcomponent


<template>
   <button @click="handelClick">O( STH _ STH )O Ha ha ~</button>
   <br>
   <input type="text" v-model="customText">
   <br>
</template>

<script>
import {computed} from "vue"
    export default {
        props:{
            modelValue:String,
            text:String
        },
        emits:['update:modelValue',"update:text"],
        setup(props,context){
            function handelClick() {
                context.emit("update:modelValue","O( STH _ STH )O Ha ha ~")
            }
            let customText = computed({
                set(value){
                    context.emit("update:text",value)
                },
                get(){
                    return props.text
                }
            })

            return{
                handelClick,
                customText,
            }
        }
    }
</script>

Multiple binding values and renaming writing v-model: text= "inputText" Subcomponent props is directly text emission event name is update: text
Here, we can see that in order to realize the bidirectional binding of the parent component with the input box v-model in the child component, we need to use the calculation attribute computed to realize it. Maybe some students want to bind text in props directly. Or the above sentence, if only read can be bound, but when you modify it, you need to send an event to inform the parent component to update the data (you can't modify the value in props, you can only read it! ! ! ). Therefore, in the calculation attribute, we emit an event in set to update the parent component data, and when reading, we just read the value in props directly.

Summarize


Related articles: