步步追问?如何以面试的角度打开v-model/双向数据绑定?

思路分析:

  1. 给出双绑定义
  2. v-model本质
  3. 双绑带来的好处
  4. 补充v-model可用在自定义事件(引导面试官提问)

回答范例:

  1. 双向数据绑定就是绑定一个响应式数据到视图,数据的变化能自动反映在视图中,同时用户的输入也能自动更新数据。

  2. v-model其实是一种语法糖 (就是一种简写方式,最终会被转换成原始写法)。

    表单元素上使用,编译器会根据不同的表单元素使用不同的属性并抛出不同的事件:

  • 对于texttextarea元素使用value属性和input事件

  • 对于checkboxradio元素使用checked属性和change事件

  • 对于select元素使用value属性和change事件

    另外还可以结合.lazy,.number,.trimv-model的行为做进一步限定。

  1. 总的来说,使用v-model能减少大量繁琐的事件处理代码,提高开发效率。

  2. 另外,v-model也可以用于自定义组件中。(等面试官问)


自定义组件的v-model

vue2和vue3在自定义组件使用v-model原理都是父子组件间通讯 ,只不过代码书写不一样。

vue2自定义组件的v-model

在vue2中,父组件使用v-model向子组件传递响应式数据,子组件需要在props配置项中接收,同时需要在相应的元素监听触发事件,像inputclick等事件,通过触发$emit将值回传给父组件。

追问:自定义组件使用v-model如果想改变属性名和事件名怎么做?

我们知道默认的属性名是value,事件名是input。可通过配置项modelprop可命名属性,event可命名事件。

追问:v-model和传统的使用 props和$emit有什么区别?

v-model更加简洁,使得双向绑定代码更加清晰和易读,具体表现在对父组件的代码书写上有所简化,父组件在使用子组件时只需要v-model=""就能传递响应式数据,不用提前定义一个事件处理函数来等待子组件通过emit修改数据传回到父组件,大致简化了以下代码:

js 复制代码
<Son :name="obj.name" @mychange="fn"></Son>

let fn=(name)=>{
    obj.name=name;
}
追问:v-model和.sync修饰符有什么区别?

相同点:都是语法糖,都是实现父子组件间通讯。

区别:

  • 代码书写不同,v-model="num" |||| :num.sync="num"
  • v-model只能绑定父组件的一个响应数据,.sync可绑定多个数据。
    <son :a.sync="num1" :b.sync="num2"></son>

我觉得由于vue2的v-model.sync在自定义组件上的使用有点重叠,vue3就对此进行了一定的优化。

vue3自定义组件的v-model

在vue3中,父组件依旧使用v-model向子组件传递响应式数据,子组件需要接收父组件的props:modelValue以及方法update:modelValue,然后通过computed计算属性的gettersetter来实现读取和修改父组件的值,在setter中,子组件使用update:modelValue这个emit来修改父组件的值。

追问:vue2和vue3的v-model在自定义组件使用有什么区别?
  • vue2可通过model配置项来命名属性和事件,vue3删除了model选项,固定使用modelValue为父组件的props,使用update:modelValue这个emit来修改父组件的值。
  • vue2的v-model只能绑定父组件的一个响应数据,vue3可通过v-model:属性1="" v-model:属性2=""绑定多个响应数据传给子组件。
追问:有没有听说过defineModel ?

在Vue3.4版本后,出现了defineModel这个新的api,简化了自定义子组件实现双向绑定大部分操作,可直接通过defineModel读取和修改父组件的值,我的理解就是相当于做了封装,在底层帮我们实现了definePropsdefineEmits

js 复制代码
//子组件中
// 声明 "modelValue" prop,由父组件通过 v-model 使用
const model = defineModel()
// 在被修改时,触发 "update:modelValue" 事件
model.value = "hello"

附录代码

由于本文是面试题,在懂代码的基础上,主要进行文字讲述。

以下是vue2和vue3关于自定义组件使用v-model的代码,可进一步回顾:

vue2 父组件
js 复制代码
<template>
  <div>
   <myInput v-model="message"></myInput>
    <p>{{message}}</p>
  </div>
</template>

<script>
import myInput from './components/demo'
export default {
  data () {
    return {
      message:''
    };
  },
  components: {myInput},
  methods: {}
}
</script>
子组件
js 复制代码
<template>
  <div>
    <input
      type="text"
      :value="parentData"
      @input="updateVal($event.target.value)"
    />
  </div>
</template>
​
<script>
export default {
  data() {
    return {};
  },
  model: {
    //父组件传过来的响应式值,可随便命名,但必须和props一致
    prop: "parentData",
    // 随便命名事件,对应下面$emit即可
    event: "changeXXX",
  },
  props: {
    parentData: {
      type: String,
      default: "tom",
    },
  },
  methods: {
    updateVal(val) {
      this.$emit("changeXXX", val);
    },
  },
};
</script>
vue3 父组件
js 复制代码
<childComponent v-model="msg" /> 
子组件
js 复制代码
<template>
  <input type="text" v-model="newValue" />
</template>
​
<script setup>
import { computed } from "vue";
//接收父组件的props:modelValue
const props = defineProps({
  modelValue: {
    type: String,
    default: "",
  },
});
//接收父组件的方法:update:modelValue
const emit = defineEmits(["update:modelValue"]);
//通过computed计算属性的getter和seter来实现读取和修改父组件的值    
let newValue = computed({
  get: () => {
    return props.modelValue;
  },
  set: (value) => {
    emit("update:modelValue", value);
  },
});
</script>

参考文章

vue2和vue3的v-model详解

写在最后

努力准备面试题中,希望整理的信息对您有所帮助,喜欢的话请帮忙点赞。

如有错误还请批评指教,谢谢!

相关推荐
Devil枫4 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
GIS程序媛—椰子5 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
毕业设计制作和分享6 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
程序媛小果6 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot
从兄7 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
凉辰8 小时前
设计模式 策略模式 场景Vue (技术提升)
vue.js·设计模式·策略模式
薛一半9 小时前
PC端查看历史消息,鼠标向上滚动加载数据时页面停留在上次查看的位置
前端·javascript·vue.js
MarcoPage9 小时前
第十九课 Vue组件中的方法
前端·javascript·vue.js
工业互联网专业10 小时前
Python毕业设计选题:基于Hadoop的租房数据分析系统的设计与实现
vue.js·hadoop·python·flask·毕业设计·源码·课程设计
你好龙卷风!!!10 小时前
vue3 怎么判断数据列是否包某一列名
前端·javascript·vue.js