Vue数据代理的实现流程逐步讲解

 更新时间:2023年01月06日 16:03:06   作者:BraveWangDev  
通过一个对象代理对另一个对象中的属性的操作(读/写),就是数据代理。要搞懂Vue数据代理这个概念,那我们就要从Object.defineProperty()入手,Object.defineProperty()是Vue中比较底层的一个方法,在数据劫持,数据代理以及计算属性等地方都或多或少的用到了本函数

一,前言

上篇,主要介绍了 Vue 数据初始化流程中,数组类型的数据劫持是如何实现的,核心思路如下:

出于对性能的考虑,Vue 没有对数组采用 Object.defineProperty 进行递归劫持,而是对能够导致原数组变化的 7 个方法进行了拦截和重写,实现了对数组的数据劫持

至此,已经完成了对响应式数据(对象和数组)的劫持(深层劫持)操作

本篇,继续介绍 Vue 数据初始化流程中, Vue 实例上数据代理的实现

二,数据代理的实现

1,Vue 是如何操作数据的

在 Vue 中,是可以在外部直接通过 vm 实例进行数据访问和操作:

let vm = new Vue({
  el: '#app',
  data() {
    return { message: 'Hello Vue', obj: { key: "val" }, arr:[1,2,3]}
  }
});
console.log(vm.message)
console.log(vm.arr.push(4))

抛出问题:vm.message 等价于 $options.data.message,是如何实现的?

2,当前是如何操作数据的

当前代码,外部的 vm 实例只能拿到 vm. o p t i o n s ,拿到 d a t a 需要 v m . options,拿到 data 需要 vm. options,拿到data需要vm.options.data

// src/state.js#initData
function initData(vm) {
    let data = vm.$options.data;
    data = isFunction(data) ? data.call(vm) : data;
    observe(data);
    data.message
    data.arr.push(4); 
}

要想实现 vm.message 和 $options.data.message 等效

相当于将 vm 实例操作代理到 $options.data 上,即实现数据代理

3,数据代理的思路

为了让外部的 vm 实例能够拿到观测后的 data,将处理后的 data 直接挂载到 vm 上

// src/state.js#initData
function initData(vm) {
    let data = vm.$options.data;
    data = vm._data = isFunction(data) ? data.call(vm) : data;
    observe(data);
}

这样,vm 实例就能够在外部通过 vm._data.message 获取到 data.message

接下来,再做一次代理,将 vm 实例操作(vm.message),代理到 vm._data 上即可

4,数据代理的实现

通过 Object.defineProperty 对 _data 中的数据操作进行劫持

即:vm.message 在 vm 实例上取值时,将它代理到 vm._data 上取值

// src/state.js#initData
function initData(vm) {
    let data = vm.$options.data;
    data = vm._data = isFunction(data) ? data.call(vm) : data;
    observe(data);
    // 当 vm.message 在 vm 实例上取值时,将它代理到vm._data上去取
    for(let key in data){
        Proxy(vm, key, '_data')
    }
}
// src/state.js#Proxy
/**
 * 代理方法
 *  当取 vm.key 时,将它代理到 vm._data上去取
 * @param {*} vm        vm 实例
 * @param {*} key       属性名
 * @param {*} source    代理目标,这里是vm._data
 */
function Proxy(vm, key, source) {
    Object.defineProperty(vm, key, {
        get(){
            return vm[source][key]
        },
        set(newValue){
            vm[source][key] = newValue;
        }
    })
}

5,数据代理的测试

let vm = new Vue({
  el: '#app',
  data() {
    return { message: 'Hello Vue', obj: { key: "val" }, arr:[1,2,3]}
  }
});
console.log(vm)
console.log(vm.message)

观察打印结果:

获取 vm 实例时,会通过 get 方法将 _data 全部属性打印出来

当前 vm 实例上,包含 data 全部属性及对应的 get、set 方法

这样,就实现了数据代理:

当从 vm 实例取值时,就会被代理到 vm._data 取值

三,结尾

本篇主要介绍了 Vue 数据初始化流程中,Vue 实例上数据代理的实现,核心思路如下:

  • 将 data 暴露在 vm._data 实例属性上
  • 利用 Object.defineProperty 将 vm.xxx 操作代理到 vm._data 上

到此这篇关于Vue数据代理的实现流程逐步讲解的文章就介绍到这了,更多相关Vue数据代理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue组件上使用v-model之单选框

    Vue组件上使用v-model之单选框

    这篇文章主要介绍了Vue组件上使用v-model之单选框,代码分为子组件内容和父组件内容,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-10-10
  • vue项目根据不同环境进行设置打包命令的方法

    vue项目根据不同环境进行设置打包命令的方法

    这篇文章主要介绍了vue项目根据不同环境进行设置打包命令,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-11-11
  • Vue通过input筛选数据

    Vue通过input筛选数据

    这篇文章主要为大家详细介绍了Vue通过input筛选数据的相关代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • Vue3 中实现元素拖拽功能

    Vue3 中实现元素拖拽功能

    这篇文章主要介绍了在Vue3中实现飘逸的元素拖拽,在本次案例中需要认真思考对应的几个坐标和移动时坐标如何更新,事件的使用要成对出现,如何在这个拖拽的 Icon 上增加点击事件时还需要多做一些处理,需要的朋友可以参考下
    2023-07-07
  • 使用axios请求时,发送formData请求的示例

    使用axios请求时,发送formData请求的示例

    今天小编就为大家分享一篇使用axios请求时,发送formData请求的示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10
  • vue动态设置img的src路径实例

    vue动态设置img的src路径实例

    今天小编就为大家分享一篇vue动态设置img的src路径实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • 派发器抽离vue2单组件中的大量逻辑技巧

    派发器抽离vue2单组件中的大量逻辑技巧

    这篇文章主要为大家介绍了派发器抽离vue2单组件中的大量逻辑技巧,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • 详解Vue如何通过URL传递与获取参数

    详解Vue如何通过URL传递与获取参数

    Vue Router 路由实际上就是一种映射关系,例如,多个选项卡之间的切换就可以使用路由功能来实现,在实际的开发中,经常需要通过URL来传递参数,同时在 JavaScript 脚本中需要获取URL中的参数,下面将介绍 Vue 项目中,如何通过 URL 对参数进行传递与获取,需要的朋友可以参考下
    2024-09-09
  • vue的指令和插值问题汇总

    vue的指令和插值问题汇总

    Vue 是一套用于构建用户界面的渐进式框架,Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合,这篇文章主要介绍了vue的指令和插值总结,需要的朋友可以参考下
    2022-10-10
  • vue中前端如何实现pdf预览功能(含vue-pdf插件用法)

    vue中前端如何实现pdf预览功能(含vue-pdf插件用法)

    这篇文章主要给大家介绍了vue中前端如何实现pdf预览功能的相关资料,文中包含vue-pdf插件用法,在前端开发中,很多时候我们需要进行pdf文件的预览操作,需要的朋友可以参考下
    2023-07-07

最新评论