vue2 Vue3 v-model 原理

简介: 这个子组件只是实现一个简单计数器的功能,然后我向上分发的事件名称是update:value。但是vue2如果使用v-model会自动的把这个事件名称给改成input。

面试题:请阐述一下 v-model 的原理


v-model即可以作用于表单元素,又可作用于自定义组件,无论是哪一种情况(vue2, vue3),它都是一个语法糖,最终会生成一个属性和一个事件。


202a30be7b93083c2de49473f0db0e0f.png

9abe821ac842afbabcd2542f6f823567.png


当其作用于表单元素时,vue会根据作用的表单元素类型而生成合适的属性和事件。例如:


  • text 和 textarea 元素使用 value property 和 input 事件;
  • checkbox 和 radio 使用 checked property 和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。


用于自定义组件


vue2


v-model也可作用于自定义组件,当其作用于自定义组件时,默认情况下,它会生成一个value属性和input事件。


子组件 HelloWorld


这个子组件只是实现一个简单计数器的功能,然后我向上分发的事件名称是update:value。但是vue2如果使用v-model会自动的把这个事件名称给改成input。


<template>
  <div class="hello">
    <button @click="change(value - 1)">-</button>
    <span>{{value}}</span>
    <button @click="change(value + 1)">+</button>
  </div>
</template>
<script>
export default {
  name: "HelloWorld",
  props: {
    value: Number,
  },
  methods: {
    change(val) {
      this.$emit("update:value", val);
    },
  },
};
</script>
复制代码


APP 来使用


<HelloWorld :value="inputVal" @update:value="inputVal = $event" />
等效于
<HelloWorld v-model="inputVal" />
复制代码


结果:


e26ba0ee5bcf4a0abe8cf25397133597.gif


分析虚拟dom结果


vue2的虚拟dom查看方式是 在mounted中使用this._vnode来进行查看,然后查看componentOptions来查看组件传递的属性。


4bb84a396519dda4ef525bbc9032c450.png

ab0841e0acbf27d6bcfe5aad4d72674f.png


开发者可以通过组件的model配置来改变生成的属性和事件 修改子组件 HelloWorld


<template>
  <div class="hello">
    <button @click="change(number - 1)">-</button>
    <span>{{ number }}</span>
    <button @click="change(number + 1)">+</button>
  </div>
</template>
<script>
export default {
  name: "HelloWorld",
  props: {
    number: Number,
  },
  model: {
    prop: "number", // 默认为 value
    event: "change", // 默认为 input
  },
  methods: {
    change(val) {
      this.$emit("change", val);
    },
  },
};
</script>
复制代码


父组件修改


<HelloWorld v-model="inputVal" />
<!-- 等效于 -->
<HelloWorld :number="inputVal" @change="data=$event" />
复制代码


效果


6a0ffbcc3e5071d0d007ea2f4eea2e9e.png


vue3


v-model也可作用于自定义组件,当其作用于自定义组件时,默认情况下,它会生成一个modelValue属性和onUpdate:modelValue事件。


子组件 Comp


<script setup>
import { ref, } from 'vue'
 const props =  defineProps({
    modelValue: Number
  })
 const emits = defineEmits(['update:modelValue']);
  const change = (val) => {
    emits('update:modelValue', val)
  }
</script>
<template>                             
  <button @click="change(props.modelValue -  1)">
    -
  </button>
  <span>{{props.modelValue}}</span>
  <button @click="change(props.modelValue +  1)">
    +
  </button>
</template>
复制代码


父组件App


<script setup>
import { ref, getCurrentInstance } from 'vue'
 import Comp from './Comp.vue'
const msg = ref(123);
 const internalInstance = getCurrentInstance();
  console.log(internalInstance)
</script>
<template>                             
  <Comp v-model="msg"></Comp>
  等效于
  <Comp :modelValue="msg" @update:modelValue="msg = $event"></Comp>
</template>
复制代码


结果


aaf725e03b5442d890143f3eb8a68992.gif


虚拟dom分析


vue3 的查看虚拟dom的使用方式,是使用``getCurrentInstance`来查看, 里面的children中的props中来查看属性传递


173bf53b8d6b5df3112d6f532c79f892.png


区别


vue2和vue3都又v-model,原理都是生成一个属性和一个事件,但是也存在些区别。


.sync修饰符


vue3中的.sync修饰符是去掉了的,他的功能可以由v-model的参数替代


例如:


<!-- vue2 -->
<Comp :title="inputVal" @update:title="inputVal = $event" />
<!-- 简写为 -->
<Comp :title.sync="inputVal" />
<!-- vue3 -->
<Comp :title="inputVal" @update:title="inputVal = $event" />
<!-- 简写为 -->
<Comp v-model:title="inputVal" />
复制代码


多个v-model


在vue3中允许你写多个v-model,这也是强烈的说明了,v-model就是一个语法糖,只是帮你减少了代码量,仅此而已。vue2不能写多个v-model


<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />
<!-- 是以下的简写: -->
<ChildComponent
  :title="pageTitle"
  @update:title="pageTitle = $event"
  :content="pageContent"
  @update:content="pageContent = $event"
/>
复制代码


##v-model 修饰符


vue2.x是自带的修饰符,但是在3.x的版本中,可以自定义修饰符哦 .在3.x中的修饰符会在当作属性传递给子组件,并且在属性中生成一个modelModifiers的属性。存在这个修饰符就会有对应的修饰符,并且是true,如果没有传递,那就是undefined。


修改Comp子组件


<script setup>
import { ref, } from 'vue'
 const props =  defineProps({
    modelValue: Number,
    modelModifiers: { 
      default: () => ({})
    }
  })
 const emits = defineEmits(['update:modelValue']);
  const change = (val) => {
    // 如果存在修饰符range2,那就多加1,减法就没有效果
    if(props.modelModifiers.range2){
      val ++;
    }
    emits('update:modelValue', val)
  }
</script>
<template>                             
  <button @click="change(props.modelValue -  1)">
    -
  </button>
  <span>{{props.modelValue}}</span>
  <button @click="change(props.modelValue +  1)">
    +
  </button>
</template>
复制代码


父组件使用


<Comp v-model.range2="msg"></Comp>
复制代码


效果


c2e22a985836465191168e58a280e83d.gif


vue3测试代码地址: vue2测试代码地址,由于忘记登录,被删除了


相关文章
|
2天前
|
JavaScript
Vue3搜索框(InputSearch)
这篇文章介绍了如何在Vue 3中创建一个具有搜索、清除、加载状态等多功能的搜索框组件(InputSearch),并提供了组件的配置选项、事件处理和使用示例。
Vue3搜索框(InputSearch)
|
2天前
|
JavaScript API 容器
Vue3加载条(LoadingBar)
这是一个基于 Vue 的加载条组件,提供了丰富的自定义选项和方法。通过简单的 API,可以控制加载条的开始、结束及错误状态。支持设置容器类名、样式、颜色等属性,并可通过 `start`、`finish` 和 `error` 方法来触发不同状态。
Vue3加载条(LoadingBar)
|
2天前
|
JavaScript
Vue3滚动条(Scrollbar)
这是一个基于 Vue 的自定义滚动条组件 Scrollbar.vue,提供了丰富的配置选项和方法。通过参数如 `contentClass`、`size` 和 `trigger` 等,可以灵活控制滚动条的样式和行为。
Vue3滚动条(Scrollbar)
|
2天前
|
JavaScript
Vue3分段控制器(Segmented)
这是一个基于 Vue 的分段控制器组件 `Segmented`,支持多种选项和自定义渲染。通过 `v-model` 绑定当前选中值,并提供 `block`、`disabled` 和 `size` 等属性来调整样式。
Vue3分段控制器(Segmented)
|
2天前
|
JavaScript
Vue3渐变文字(GradientText)
该文档介绍了一个基于 Vue 的渐变文字组件 `GradientText`,允许用户通过配置参数实现不同样式和尺寸的文字渐变效果。支持自定义起始和结束颜色、渐变角度及多种预设类型(如 `primary`、`info` 等)。
Vue3渐变文字(GradientText)
|
2天前
|
JavaScript
Vue3抽屉(Drawer)
这是一个基于Vue的抽屉组件(Drawer),提供了丰富的自定义选项,如宽度、高度、标题、关闭按钮等,并支持顶部、右侧、底部和左侧四种方向。
Vue3抽屉(Drawer)
|
2天前
|
JavaScript
Vue3骨架屏(Skeleton)
该文章介绍了一个名为Skeleton的Vue组件,用于创建加载时的占位符界面,包含多种可配置项如按钮、输入框、图像等,并支持动画效果。
Vue3骨架屏(Skeleton)
|
2天前
|
JavaScript API 容器
Vue3气泡卡片(Popover)
这是一个基于Vue的气泡卡片组件(Popover)介绍,提供了在线预览链接及详细API参数说明,包括maxWidth、title、content等,并支持自定义样式。
Vue3气泡卡片(Popover)
|
2天前
|
JavaScript API 数据安全/隐私保护
Vue3水印(Watermark)
这是一个基于Vue.js的水印组件库,提供了丰富的自定义选项,包括水印的布局、旋转角度、间距等。组件支持文字和图片水印,并可通过API调整样式和位置。
Vue3水印(Watermark)
|
2天前
|
JavaScript API 开发者
关于维护vue3的响应式的那些事:unref、toRef、toRefs、toRaw、toValue
总结:Vue 3的Composition API提供的这些工具,大大增强了我们对响应式状态的操作能力,让状态管理变得更为灵活和高效。`unref`、`toRef`、`toRefs` 以及 `toRaw` 各有其用途和应用场景,灵活应用这些工具,将有助于开发出更为强大和响应式的Vue应用。在开发过程中,正确区分和使用这些API,能够有效提高开发效率以及应用的性能。
6 0