【面试题】谈一下v-model的实现原理

唠嗑部分

首先来说一说双向数据绑定,即数据变视图变,视图变数据变,在react中要实现这种功能,就要写受控表单了,而在vue中有一个指令,十分方便

v-model指令,这个指令可以说十分强大了,可以实现双向数据绑定,先看一下简单用法

<div id="app">
  <input type="text" v-model="message">
  <p>您输入的内容是: {
   
   { message }}</p>
</div>
 
<script>
  var vm = new Vue({
    el: '#app',
    data: {
      message: ''
    }
  });
</script>

这样就能实现双向数据绑定了,那么你知道它是什么原理嘛?

言归正传

说到这个问题,就要分版本来说了,小白最近呢也是把vue3干完了,先说一下哈

在vue2.x当中是使用Object身上的一个方法实现的响应式,在vue3当中呢使用Proxy代理来实现响应式,下面我们具体分析一下

在vue2.x中呢,v-model指令是基于Object.defineProperty()方法转换成getter/setter,当数据发生变化时,setter函数会通知相关的视图进行更新,从而实现双向数据绑定。大家都知道,data函数返回的数据都是响应式的,这也是大前端框架的主要特点,那什么是响应式呢?

简单理解一下,当数据变了的时候,框架监测到,并且会帮我们更新页面

那根据上述理解,下面我们来写一段伪代码

let person = {
    
    
    name: '张三',
    age:20
}
let vm = {
    
    };
Object.defineProperty(vm, 'name', {
    
    
    set(value) {
    
    
        console.log(`有人新增或修改了vm身上的属性name,我要去更新页面了`)
        person.name = value
    },
    get(){
    
    
        return person.name
    }
})
Object.defineProperty(vm, 'age', {
    
    
    set(value) {
    
    
        console.log(`有人新增或修改了vm身上的属性age,我要去更新页面了`)
        person.age = value
    },
    get(){
    
    
        return person.age
    }
})

当vm的值变化时,会触发更新页面的逻辑,也就实现了响应式

那么这样会有什么问题,vue3为什么会优化掉呢?

1、首先这种方式每次只能监听一个对象的一个属性,那么对于复杂对象来说,底层就会使用循环处理,并且无法优化

2、这种方式不能够监听到属性的新增、删除

3、如果是数组类型,通过下标修改数据,也不能够检测到

注意,在vue2中

1、对象添加属性,不能直接添加,而是要通过this.$set(要操作的对象,添加的属性,值),或者Vue,set(要操作的对象,添加的属性,值),页面才能检测到,更新页面

2、对象删除属性,不能直接delete xxx.xx,而是要通过this.$delete(要操作的对象,删除的属性)

在vue3当中,响应式设计采用了proxy代理来实现,我们来看一段伪代码

let person = {
    
    
    name: '张三',
    age:20
}

const p = new Proxy(person, {
    
    
    set(target, prop, value) {
    
    
        console.log(`有人新增或修改了p身上的属性${
      
      prop},我要去更新页面了`)
        Reflect.set(target, prop, value)
    },
    get(target, prop) {
    
    
        console.log(`有人读取了p身上的属性${
      
      prop}`)
        return Reflect.get(target, prop)
    },
    deleteProperty(target, prop) {
    
    
        console.log(`有人删除了p身上的属性${
      
      prop},我要去更新页面了`)
        return Reflect.deleteProperty(target, prop)
    }
})

proxy方式可以一次性监视对象的所有属性,也能监听到属性的删除,对于数组类型下标修改也能检测到,解决了2.x留下的问题。

结语

1、使用Proxy实现的数据响应式系统更为灵活和高效,它可以代理整个对象

2、Object.defineProperty()方法只能代理单个对象属性,要通过循环或递归才能监听整个对象。

3、Vue2.x响应式原理是基于Object.defineProperty()实现的。

4、Vue3响应式原理是基于Proxy代理+Reflect实现的。

5、制作不易,一键三连再走吧,您的支持永远是我最大的动力!

猜你喜欢

转载自blog.csdn.net/admin_2022/article/details/130485222