The difference between vue2 and vue3 component v-model

foreword

One-way data flow, the data passed from the parent component to the child component, the child component can only display and cannot be modified, if it needs to be modified, the emit event is required to let the parent component modify it
insert image description here
Sometimes, some components do not trigger events through input. That is to say, value and input events can be applied in most cases, but there are cases where value has other meanings, or cannot be triggered by input. At this time, we cannot use v-model for abbreviation.
For example, for a selection box, the bound value is checked instead of value, and the receiving event is not input but change.
In order to solve this problem, You Yuxi introduced it in Vue2.2, model组件选项that is to say, you can specify the value and attribute of v-model binding through model.

vue2 component v-model.

1. Two-way binding of a single value (input) in vue2

<ChildComponent v-model = "title />
// 实际上是下面这种的简写
<ChildComponent :value = "title"  @input = "title = $event" />

insert image description here
Subassembly:

<template>
  <input type="text" :value="value" @input = "inputChange">
</template>

<script>
export default {
    
    
  name: "CustomInput",
  props: ['value'],
  methods: {
    
    
    inputChange(e) {
    
    
      this.$emit('input', e.target.value)
    }
  }
}
</script>

parent component:

<template>
  <div class="test">
    <span>自定义组件:</span>
    <CustomInput v-model="age"/> 
    // 等价
    // <CustomInput :value="age" @input="changeAge"/>
    {
    
    {
    
    age}}
  </div>
</template>

<script>
import CustomInput from "./CustomInput";

export default {
    
    
  name: "Test",
  components: {
    
    
    CustomInput,
  },
  data() {
    
    
    return {
    
    
      age: 20,
    }
  },
  methods: {
    
    
    changeAge(value) {
    
    
      this.age = Number(value);
    }
  }
}
</script>

In vue2, v-model is equivalent to passing the binding value with value, and using the @input event to receive the parameters passed by the subcomponent through $emit.

2. Two-way binding of a single value in vue2 (non-input setting model option)

insert image description here
insert image description here

Through the above code, we can see that by setting the model option, we can directly use the specified attributes and events without having to use value and input, which can be used in addition.

3. Two-way binding of multiple values ​​in vue2

But it is cumbersome to write in this way, and v-model can only bind one value. In this case, my component package can only change one value, which seems to be incompatible with development.

So, looking at the vue2 documentation
insert image description here
.syncand v-modelsimilar, it is shorthand for passing values ​​and receiving events. In this way, we don't need to write the model. Just tell me which value to update.

Pay attention to
insert image description here
child components:
insert image description here
parent components:
insert image description here
so, to bind multiple values, we can pass an obj down, use v-bind.sync='obj'

Look at another example:
child components:

<template>
  <div>
    <input :value="value" @input = "inputChange">
    <input :value="name" @input = "inputNameChange">
  </div>
</template>

<script>
export default {
    
    
  name: "CustomInput",
  props: ['value', 'name'],
  methods: {
    
    
    inputChange(e) {
    
    
      this.$emit('input', e.target.value)
    },
    inputNameChange(e) {
    
    
      this.$emit('update:name', e.target.value);
    }
  }
}
</script>

parent component:

<template>
  <div class="test">
    <span>自定义组件:</span>
    <CustomInput v-model="age" :name.sync="name"/> 
    // 此处v-model相当于:value="age" @input="age=$event"
  </div>
</template>

<script>
import CustomInput from "./CustomInput";

export default {
    
    
  name: "Test",
  components: {
    
    
    CustomInput,
  },
  data() {
    
    
    return {
    
    
      name: 'yn',
      age: 20,
    }
  },
  methods: {
    
    
    // changeAge(value) {
    
    
    //   this.age = Number(value);
    // }
  }
}
</script>

Is it a little confused to learn B, and it is .sync and update:title, and vue3 has deleted .sync. Let’s take a look at vue3, it’s easier to use

vue3 component v-model

From the above, we know that since the main reason for v-model in vue2.x is that the value and input events may have other uses, then can we directly use other attributes and methods without defining them through the model.
This function is implemented in vue3, v-model is no longer bound to value, but modelValue, and the receiving method is no longer input, but update:modelValue. The method of use is as follows:

1. Two-way binding of a single value in vue3

Usage of v-model on native elements:

<input v-model="searchText" />

In fact, it is equivalent to the following paragraph:

<input :value="searchText" @input="searchText = $event.target.value"/>

And when used on a component, v-model will be expanded into the following form:

<CustomInput
  :modelValue="searchText"
  @update:modelValue="newValue => searchText = newValue"
/>

The writing method in the subcomponent is:

export default defineComponent({
    
    
    name:"CustomInput",
    props:{
    
    
        modelValue:String,   // v-model绑定的属性值
    },
    setup(props, {
     
     emit}) {
    
    
        const updateValue = (e: KeyboardEvent) => {
    
    
          emit("update:modelValue",targetValue);   // 传递的方法
        }
    }
}

That is to say, in vue3, the value is changed to modelValue, and the input method is changed to update:modelValue

Let's look at another example
subcomponent:

<template>
  <div class='CustomInput'>
    <input :value="modelValue" @input = "inputChange">
  </div>
</template>

<script>
export default {
    
    
  name: 'CustomInput',
  props: {
    
    
    modelValue: String,
  },
  setup(props, {
     
     emit}) {
    
    
    function inputChange(e) {
    
    
      emit('update:modelValue', e.target.value)
    };
    return {
    
    
      inputChange,
    }
  }
};
</script>

parent component:

<template>
  <div class='test'>
  <CustomInput v-model="name"/>
    {
    
    {
    
    name}}
  </div>
</template>

<script>
import CustomInput from './CustomInput';
import {
    
     defineComponent, ref} from 'vue';

export default defineComponent({
    
    
  name: 'test',
  components: {
    
    
    CustomInput
  },
  setup() {
    
    
    const name = ref('zm');
    return {
    
    
      name
    }
  }
});
</script>

2. Two-way binding of multiple values ​​in vue3

Example 1:

<UserName
  v-model:first-name="first"
  v-model:last-name="last"
/>
<script setup>
defineProps({
    
    
  firstName: String,
  lastName: String
})

defineEmits(['update:firstName', 'update:lastName'])
</script>

<template>
  <input
    type="text"
    :value="firstName"
    @input="$emit('update:firstName', $event.target.value)"
  />
  <input
    type="text"
    :value="lastName"
    @input="$emit('update:lastName', $event.target.value)"
  />
</template>

Example 2:
Parent component:

<template>
  <div class='test'>
  <CustomInput v-model:name="name" v-model:age="age"/>
    {
    
    {
    
    name}} {
    
    {
    
    age}}
  </div>
</template>

<script>
import CustomInput from './CustomInput';
import {
    
     defineComponent, ref} from 'vue';

export default defineComponent({
    
    
  name: 'test',
  components: {
    
    
    CustomInput
  },
  setup() {
    
    
    const name = ref('zm');
    const age = ref(20);
    return {
    
    
      name,
      age
    }
  }
});

Subassembly:

<template>
  <div class='CustomInput'>
    <input :value="age" @input = "inputChange">
    <input :value="name" @input = "inputNameChange">
  </div>
</template>

<script>
export default {
    
    
  name: 'CustomInput',
  props: {
    
    
    name: String,
    age: Number,
  },
  setup(props, {
     
     emit}) {
    
    
    function inputChange(e) {
    
    
      emit('update:age', e.target.value)
    };
    function inputNameChange(e) {
    
    
      emit('update:name', e.target.value);
    }
    return {
    
    
      inputChange,
      inputNameChange,
    }
  }
};
</script>

3. v-model parameter

By default, v-model uses modelValue as the prop on the component, and uses update:modelValue as the corresponding event. We can change these names by specifying a parameter to v-model:

<MyComponent v-model:title="bookTitle" />

Then in the subcomponent, you can use title instead of modelValue

<!-- MyComponent.vue -->
<script setup>
defineProps(['title'])
defineEmits(['update:title'])
</script>

<template>
  <input
    type="text"
    :value="title"
    @input="$emit('update:title', $event.target.value)"
  />
</template>

That is, our final usage method is:

<ChildComponent v-model:title="title"  />
// 或者
<ChildComponent :title="title" @update:title = "title = $event" />

Look at another example
parent component:

<template>
  <div id="app">
    <h1>Vue3中v-model的变化</h1>
    <input type="text" v-model="name"/>
    <p>{
    
    {
    
     name }}</p>
    <!-- Vue2的写法 -->
    <!-- v-model实际上就是:value和@input的语法糖 -->
    <!-- 双向绑定多个属性的时候可以使用.sync关键字 -->
    <CustomInput v-model="age" :name.sync="name"/>
    <!-- Vue3的写法 -->
    <CustomInput v-model:age="age" v-model:name="name"/>
  </div>
</template>

<script>
import CustomInput from "../components/CustomInput.vue";
export default {
    
    
  name: "App",
  components: {
    
    
  	CustomInput
  },
	data() {
    
    
    return {
    
    
    	name: "你好",
      age: 20,
    }
  },
}
</script>

Subassembly:

<template>
  <div class="custom-input">
    <h1>自定义的input</h1>
    <!-- Vue2的写法 -->
    <input type="text" :value="value" @input="onInput" />
    <input type="text" :value="name" @input="onNameInput" />
    <!-- Vue3的写法 -->
    <input type="text" :value="age" @input="onInput" />
    <input type="text" :value="name" @input="onNameInput" />
  </div>
</template>

<script>
import CustomInput from "../components/CustomInput.vue";
export default {
    
    
  // Vue2的写法
  props: ["value", "name"],
  // Vue3的写法,直接接收绑定的参数
  props: ["age", "name"],
  // Vue3双向绑定单个属性时,可以使用modelValue来接收参数并更新,对应的触发事件为update:modelValue
  props: ["modelValue"],
  methods: {
    
    
  	onInput(e) {
    
    
      // Vue2的写法
      // 触发的事件只能是input
      // e.target.value是字符串需要转换成数字
    	this.$emit("input", parseInt(e.target.value));
      // Vue3的写法
      this.$emit("update:age", e.target.value);
    },
    onNameInput(e) {
    
    
      // 只能用update
    	this.$emit("update:name", e.target.value);
    },
  },
}
</script>

Well, so far, we have introduced the use and problems of v-model in vue2, and the new usage syntax of v-model in vue3. Hurry up to experience the use of vue3.

Guess you like

Origin blog.csdn.net/weixin_44582045/article/details/131254965