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 $nextTick实现原理深入详解

    vue $nextTick实现原理深入详解

    这篇文章主要介绍了vue $nextTick实现原理深入详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • 浅谈Vuejs Prop基本用法

    浅谈Vuejs Prop基本用法

    本篇文章主要介绍了Vuejs Prop基本用法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • 使用Vue实现移动端左滑删除效果附源码

    使用Vue实现移动端左滑删除效果附源码

    这篇文章主要介绍了使用Vue实现移动端左滑删除效果,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-05-05
  • vue3+ts 兄弟组件之间传值的实现

    vue3+ts 兄弟组件之间传值的实现

    Vue3是一款流行的前端框架,它支持多种传值方式,包括兄弟组件之间的传值,本文主要介绍了vue3+ts 兄弟组件之间传值的实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • 如何理解Vue简单状态管理之store模式

    如何理解Vue简单状态管理之store模式

    状态管理也就是数据状态管理,vue应用程序的各组件之间经常需要进行通信,除了v-on、EventBus等通信方式外,可以采用数据共享的方式进行通信。这种简单的数据共享模式就是store模式。
    2021-05-05
  • vue usePop弹窗控制器的实现

    vue usePop弹窗控制器的实现

    本文主要介绍了vue usePop弹窗控制器的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • 使用vue-cli初始化项目时运行‘npm run dev’报错及解决

    使用vue-cli初始化项目时运行‘npm run dev’报错及解决

    这篇文章主要介绍了使用vue-cli初始化项目时运行‘npm run dev’报错及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • Vue实现固定底部组件的示例

    Vue实现固定底部组件的示例

    本文主要介绍了Vue实现固定底部组件的示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • 详解如何提高 webpack 构建 Vue 项目的速度

    详解如何提高 webpack 构建 Vue 项目的速度

    这篇文章主要介绍了详解如何提高 webpack 构建 Vue 项目的速度,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • vue配置文件自动生成路由和菜单实例代码

    vue配置文件自动生成路由和菜单实例代码

    因为不同的用户有不同的权限,能访问的页面是不一样的,所以我们在写后台管理系统时就会遇过这样的需求:根据后台数据动态添加路由和菜单,这篇文章主要给大家介绍了关于vue配置文件自动生成路由和菜单的相关资料,需要的朋友可以参考下
    2021-08-08

最新评论