【手写 Vue2.x 源码】第六篇 - 数据代理的实现

news2025/1/17 15:18:46

一,前言

上篇,主要介绍了 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)

image.png

观察打印结果:

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

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

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

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


三,结尾

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

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

下一篇,调试数据劫持和代理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/144909.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NOSQL数据库习题

NOSQL数据库习题第一章第二章第三章第四章第五章NoSQL数据库上机测试第一章 1.写出DB、RDB、DBMS、TRDB、NoSQL、NewSQL、NDFS的中文名称。 答:DB:数据库 RDB:关系型数据库 DBMS:数据库管理系统 TRDB:传统关系型数据…

解决Shotgrid登陆不上, 上传出错,窗口卡住不动等问题

在使用Shotgrid时,是否遇到这种问题: accounts.autodesk.com出错 auth.autodesk.com出错 再或者这样出错: Shotgrid登陆出错 再再这样关闭Load…时这样出错, 窗口半天都关闭不了: 分析: 1 出现这种错…

(一分钟)激光SLAM扫描匹配 文献阅读

本博客介绍了激光SLAM扫描匹配的相关问题。编辑切换为居中添加图片注释,不超过 140 字(可选)扫描匹配也是数据关联类的问题,是SLAM里面的重要构成部分。编辑切换为居中添加图片注释,不超过 140 字(可选&…

PyTorch实例2——文本情绪分类器

实例主要用于熟悉相关模型,并且练习创建一个模型的步骤:数据收集、数据预处理、构建模型、训练模型、测试模型、观察模型表现、保存模型传送门:蓝桥云课实验 目录1. 实验环境2. 实验目的3. 相关原理4. 实验步骤4.1 数据收集从在线商城抓取评论…

OpenHarmony 标准系统HDF框架之I2C驱动开发

OpenHarmony 标准系统HDF框架之I2C驱动开发主要内容I2C 基础知识## I2C 基础知识 —— 概念和特性I2C 基础知识 —— 协议、四种信号组合I2C 调试手段## I2C 调试手段 —— 硬件I2C 调试手段 —— 软件HDF 框架下的 I2C 设备驱动## HDF 框架下的 I2C 设备驱动 —— 案例描述HDF…

Shell 传递参数

我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……实例以下实例我们向脚本传递三个参数&#xff…

ArcGIS Pro脚本工具(15)——按字段属性值分类导图

之前做了配合地图系列批量导图的脚本工具 ArcGIS Pro脚本工具(9)——配合地图系列批量导图_学学GIS的博客-CSDN博客_arcgispro批量导出地图pngPro的地图系列是批量制图的利器,但是有个不便的地方,就是设置完成地图系列后&#xf…

机器学习实战教程(13篇)

机器学习实战教程(13篇)这些网址非常适合想学习机器学习,却苦于没有项目(尤其缺少数据)的人。无意中看到,给自己做一个记录。机器学习实战教程(一):K-近邻算法(史诗级干货长文&#…

2022年度外设产品行业增长分析:鼠标、键盘同比增长27%

近年来,信息技术迅速发展,网民数量不断增长,深刻改变着社会的运作方式,对社会生产、商业运作模式等方面产生重大影响。广泛的行业应用为网络设备品牌商、制造商带来了差异化的细分市场,各类互联网设备接入数量也快速增…

混合空间增强

混合图像增强是一种图像处理技术,用于在不损失图像细节的情况下增强图像的对比度和亮度。它通常通过将图像拆分成多个通道,然后对每个通道进行独立处理来实现。 综合利用平滑滤波,锐化滤波,灰度拉伸等技术对图像进行处理&#xff…

【Linux】sudo给某条指令提权

sudo1.为什么要有sudo2.使用sudo提权的前提2. 在root下添加普通用户到信任列表3.验证4.总结1.为什么要有sudo 首先我们要知道,普通用户是受Linux的权限约束的。就比如普通用户对自己的家目录有完全管理的权限,但是不能随意查看其他人的家目录&#xff0c…

1.机器学习中的关键组件

1.机器学习中的关键组件 无论什么类型的机器学习问题,都会遇到这些组件: 可以用来学习的_数据_(data);如何转换数据的_模型_(model);一个_目标函数_(objective function…

JavaScript 输出

文章目录JavaScript 输出JavaScript 显示数据使用 window.alert()操作 HTML 元素在本教程中写到 HTML 文档写到控制台您知道吗?JavaScript 输出 JavaScript 没有任何打印或者输出的函数。 JavaScript 显示数据 JavaScript 可以通过不同的方式来输出数据: 使用 wi…

TiDB 6.5 LTS 发版

在 2023 伊始,我们很高兴向大家宣布,TiDB 6.5 LTS 版本已经发布了。这是 TiDB V6 的第二个长期支持版(上一个是 TiDB 6.1),除了携带了诸多备受期待的新特性,同时也将得到 TiDB 开发社区的长期维护&#xff…

设计模式(一):DDD领域驱动设计

DDD重架构,轻业务! – 从单体架构开始快速验证DDD设计模式 贫血模型充血模型防腐层 DDD四层架构规范DDD单体架构和微服务架构隔离 本地单体SPI 插拔式扩展业务模式Nacos 插拔式扩展业务模式 ---- 服务名作为服务service code DDD清晰架构 – 构建领域仓库…

加解密与HTTPS(5)

您好,我是湘王,这是我的CSDN博客,欢迎您来,欢迎您再来~咱们大学读完之后有毕业证书,并且这个证书可以在学信网查询。专业上有注会、CCIE、律师证等,可以在国家职业认证机构或委托机构的网站上查…

【UCIe】UCIe DLP/DLLP 介绍

🔥点击查看精选 UCIe 系列文章🔥 🔥点击进入【芯片设计验证】社区,查看更多精彩内容🔥 📢 声明: 🥭 作者主页:【MangoPapa的CSDN主页】。⚠️ 本文首发于CSDN&#xff0…

DNS协议——域名解析

DNS协议 DNS协议是一个应用层协议,作用是域名解析   使用DNS协议的原因,就是因为哪怕是点分十进制,对于我们都不太友好,因此使用域名来代替IP地址,比如www.baidu.com   最开始的时候,DNS系统只是一个普…

java基于ssm的个人博客系统个人博客网站个人博客项目源码

简介 Java ssm开发的个人博客系统,可以发布博客,照片,站长留言。 演示视频 https://www.bilibili.com/video/BV1sf4y1y7Ne/?share_sourcecopy_web&vd_sourceed0f04fbb713154db5cc611225d92156 技术 mysql,SSM,css,js,jq 功能 简单…

laravel5.5之laravel-admin的使用

目录 一、首先确保安装好了laravel,并且数据库连接设置正确 二、运行下面的命令来发布资源 三 、后台项目文件 四、静态文件 五、访问后台 六、参考文档 一、首先确保安装好了laravel,并且数据库连接设置正确 composer require encore/laravel-adm…