Vue2源码分析-day1

初始化数据

vue中最核心的我们都知道那就是响应式数据,数据的变化视图自动更新。那么我们来new一个我们自己的vue

index.html文件下加入如下代码,这也是vue最常见的基本结构。data已经有了下面我们来获取data的数据

 <script src="./vue.js"></script><script>const vm=new MVue({data(){return{name:"zhangsan",age:"16"}}})</script>

首先我们在src/main.js文件下加入如下代码

// 创建MVue构造函数
function MVue(options) {      // options就是我们接受到用户的选项,选项式api}// 将构造函数导出
export default MVue

为了更能的扩展功能和方便维护,我们需要一个专门做初始化的方法。所以我们在src下创建init.js文件加入如下代码

export function init(MVue){// 给MVue原型对象上挂载_init()方法MVue.prototype._init = function(options){}
}

main.js文件下如果这个方法,并且调用

import { init } from "./init"// 创建MVue构造函数
function MVue(options) {      // options就是我们接受到用户的选项,选项式api// 当vue被new的时候调用_init()方法this._init(options)
}init(MVue)// 将构造函数导出
export default MVue

下面我们就可以写我们的初始化方法了,init.js文件下加入如下代码。可能你会好奇这个init_state()方法是那里的。由于用户选项有很多比如data,watch,computed…所以我们最好创建一个文件统一管理。在src文件下创建state.js文件

import { init_state } from "./state"export function init(MVue){// 给MVue原型对象上挂载_init()方法MVue.prototype._init = function(options){// 在用户选项挂载到实例上const vm=thisvm.$options=options// 初始化状态init_state(vm)}
}

state.js文件下加入如下代码

export function init_state(vm){// 获取实例上挂载的选项const opts=vm.$options;// 选项上如果存在data初始化dataif(opts.data){init_data(vm);}
}
function init_data(vm){let data=vm.$options.data;// 判断data是对象还是函数并且重新赋值data=typeof data==='function'?data.call(vm):data;console.log(data);
}

到这里,输入打包命令打开index.html如果在游览器下看到如下图所示,我们就成功获取到了data里面的数据

pnpm run build

在这里插入图片描述


实现对象的响应式原理

下面我们首先来实现只有一层对象的数据劫持。state.js文件下加入如下代码

import { observe } from "./observe/index";export function init_state(vm){// 获取实例上挂载的选项const opts=vm.$options;// 选项上如果存在data初始化dataif(opts.data){init_data(vm);}
}
function init_data(vm){let data=vm.$options.data;// 判断data是对象还是函数并且重新赋值data=typeof data==='function'?data.call(vm):data;// 将data劫持重新定义dataobserve(data)
}

src文件下创建observe/index.js文件并且加入如下代码

class Observer {constructor(data) {/* 这里注意,Object.defineProperty只能劫持已经存在的属性,新增或删除的无法劫持这也是为什么vue2中新增了,$set和$delete方法这类方法的原因*/this.walk(data)}walk(data) {// 循环对象keys依次劫持,重新定义属性Object.keys(data).forEach(key => {define_reactive(data, key, data[key])})// 这里重新定义data后我们打印看下data是否都加入了get和set方法console.log(data);}}// 这里会存在一个闭包,get和set方法存放了函数外部的变量value
export function define_reactive(data, key, value) {Object.defineProperty(data, key, {get() {return value},set(newValue){if(value!=newValue){value=newValue}}})
}export function observe(data) {// 对对象劫持if (typeof data !== 'object' || data === null) {return;}// 如果一个对象被劫持过就不需要再次劫持,我们可以通过一个观察类判断是否被劫持过return new Observer(data)
}

如果你的游览器打印了如下图所示,那么恭喜你只有一层对象的data你重新定义完成了

在这里插入图片描述
说起data,vue2中一直有个属性_data属性。这上面挂载了我们所有在data中定义的属性。下面我们来实现它

state.js文件下修改如下代码。没错就是这么简单要加入vm._data=data这行代码就完成了。由于这是引用值。所有对data的修改也会影响到_data

function init_data(vm){let data=vm.$options.data;// 判断data是对象还是函数并且重新赋值data=typeof data==='function'?data.call(vm):data;// 实例上挂载_datavm._data=data// 将data劫持重新定义dataobserve(data)
}

下面我们在index.html下打印vm看看是否有我们的_data属性

在这里插入图片描述

到这里,其实我们的_data属性并不完美,你通过vm获取属性的时候发现每次都要加上_data,
vm._data.name。但是vue2中并不是这样的而是直接vm.name就可以获取并且修改。下面我们来解决这个问题

state.js文件下加入如下代码。我们将将vm._data代理给vm就可以解决这个问题

function proxy(vm,source,key){Object.defineProperty(vm,key,{get(){return vm[source][key]},set(newValue){if(vm[source][key]!=newValue){vm[source][key]=newValue;}}})
}function init_data(vm){let data=vm.$options.data;// 判断data是对象还是函数并且重新赋值data=typeof data==='function'?data.call(vm):data;// 实例上挂载_datavm._data=data// 将data劫持重新定义dataobserve(data)// 将vm._data代理给vmfor(let key in data){proxy(vm,'_data',key)}
}

下面我们在看我们的vm实例会发现多了name和age属性。并且可以通过vm访问到和修改

在这里插入图片描述
到这里不知你们还记得我们最早说过的,这只是一个只有一层对象的数据劫持。如果多层就代理不到了
我们修改index.html代码如下

       const vm=new MVue({data(){return{name:"zhangsan",age:"16",address:{city:"地球村    "}}}})console.log(vm);

在游览器上。我们会看到address并且没有get和set方法。下面我们来解决这个问题

在这里插入图片描述

observe/index.js文件下修改如下代码

// 这里会存在一个闭包,get和set方法存放了函数外部的变量value
export function define_reactive(data, key, value) {observe(value)		// 递归调用我们的observe方法Object.defineProperty(data, key, {get() {return value},set(newValue){if(value!=newValue){value=newValue}}})
}

再次看我们的address就会发现get和set方法已经出现了。这说明我们的多级对象代理已经完成了

在这里插入图片描述

用户可能会存在这样的赋值,现在我们是没办法办法代理到的

const vm = new MVue({data() {return {name: "zhangsan",age: "16",}}
})
vm.address = {city: "地球村"
}

所以我们在observe/index.js文件下define_reactive方法中的set修改如下。如果直接通过vm赋值对象,给这些属性同样代理

set(newValue){if(value!=newValue){observe(newValue)value=newValue}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IMV7.0

一、背景 经历了多个版本&#xff0c;基础内容在前面&#xff0c;可以使用之前的基础环境&#xff1a; v1&#xff1a; https://blog.csdn.net/wtt234/article/details/132139454 v2&#xff1a; https://blog.csdn.net/wtt234/article/details/132144907 v3&#xff1a; https…

centos7 部署Tomcat和jpress应用

目录 一、静态、动态、伪静态 二、Web 1.0 和 Web 2.0 三、centos7 部署Tomcat 3.1 安装、配置jdk 3.2 安装 Tomcat 3.3 配置服务启动脚本 3.3.1 创建用户和组 3.3.2 创建tomcat.conf文件 3.3.3 创建服务脚本(tomcat.service) 3.3.4 重新加载守护进程并且测试 四、部…

试图将更改推送到 GitHub,但是远程仓库已经包含了您本地没有的工作(可能是其他人提交的修改)

这通常是由于其他人或其他仓库推送到了相同的分支上&#xff0c;导致您的本地仓库和远程仓库之间存在冲突。 错误信息&#xff1a; To github.com:8upersaiyan/CKmuduo.git ! [rejected] main -> main (fetch first) error: failed to push some refs to github.com:8upers…

【干货】商城系统的重要功能特性介绍

电子商务的快速发展&#xff0c;商城系统成为了企业开展线上销售的重要工具。一款功能强大、用户友好的商城系统能够有效提升企业的销售业绩&#xff0c;提供良好的购物体验。下面就商城系统的重要功能特性作一些简单介绍&#xff0c;帮助企业选择合适的系统&#xff0c;打造成…

etcd

文章目录 etcd单机安装设置键值对watch操作读取键过往版本的值压缩修订版本lease租约&#xff08;过期机制&#xff09;授予租约撤销租约keepAlive续约获取租约信息 事务基于etcd实现分布式锁原生实现官方 concurrency 包实现 服务注册与发现Go 操作 Etcd 参考 etcd etcd 是一…

Java课题笔记~ Spring事务的程序举例环境搭建

举例&#xff1a;购买商品 trans_sale 项目 本例要实现购买商品&#xff0c;模拟用户下订单&#xff0c;向订单表添加销售记录&#xff0c;从商品表减少库存。 实现步骤&#xff1a; Step0&#xff1a;创建数据库表 创建两个数据库表 sale , goods sale 销售表&#xff1a;…

访问器模式(C++)

定义 表示一个作用于某对象结构中的各元素的操作。使得可以在不改变(稳定)各元素的类的前提下定义(扩展)作用于这些元素的新操作(变化)。 应用场景 在软件构建过程中&#xff0c;由于需求的改变&#xff0c;某些类层次结构中常常需要增加新的行为(方法)&#xff0c;如果直接…

途乐证券:沪指强势拉升涨0.63%,券商等板块走强,传媒板块活跃

31日早盘&#xff0c;两市股指全线走高&#xff0c;沪指一度涨超1%收复3300点&#xff0c;上证50指数盘中涨逾2%&#xff1b;随后涨幅有所收窄&#xff1b;两市成交额显着放大&#xff0c;北向资金净买入超90亿元。 到午间收盘&#xff0c;沪指涨0.63%报3296.58点&#xff0c;深…

SQL分类及通用语法数据类型(超详细版)

一、SQL分类 SQL是结构化查询语言&#xff08;Structured Query Language&#xff09;的缩写。它是一种用于管理和操作关系型数据库系统的标准化语言。SQL分类如下&#xff1a; DDL: 数据定义语言&#xff0c;用来定义数据库对象&#xff08;数据库、表、字段&#xff09;DML:…

信息安全:认证技术原理与应用.

信息安全&#xff1a;认证技术原理与应用. 认证机制是网络安全的基础性保护措施&#xff0c;是实施访问控制的前提&#xff0c;认证是一个实体向另外一个实体证明其所声称的身份的过程。在认证过程中&#xff0c;需要被证实的实体是声称者&#xff0c;负责检查确认声称者的实体…

如何使用Word转PDF转换器在线工具?在线Word转PDF使用方法

Word转PDF转换器在线&#xff0c;是一种方便快捷的工具&#xff0c;可帮助您在不需要下载任何软件的情况下完成此任务。无论您是需要在工作中共享文档&#xff0c;还是将文件以PDF格式保存以确保格式不变&#xff0c;都可以依靠这款在线工具轻松完成转换。那么如何使用Word转PD…

QGIS二次开发三:显示Shapefile

Shapefile 为 OGR 所支持的最重要的数据格式之一&#xff0c;自然可以被 QGIS 加载。那么该如何显示Shapefile呢&#xff1f; 一、先上代码 #include <qgsapplication.h> #include <qgsproviderregistry.h> #include <qgsmapcanvas.h> #include <qgsvec…

【Spring】Bean的作用域和生命周期

目录 一、引入案例来探讨Bean的作用域 二、Bean的作用域 2.1、Bean的6种作用域 2.2、设置Bean的作用域 三、Spring的执行流程 四、Bean的声明周期 1、生命周期演示 一、引入案例来探讨Bean的作用域 首先我们创建一个User类&#xff0c;定义一个用户信息&#xff0c;在定义…

fabric.js里toDataURL后,画布内容展示不全?

复现场景&#xff1a; 用fabric生成画布后&#xff0c;转成图片&#xff0c;然后直接在浏览器里打开&#xff0c;画布展示内容缺失 画布原图&#xff1a; toDataURL后链接在浏览器打开&#xff1a; 原因解析&#xff1a; base64链接太长&#xff0c;输入浏览器链接被截断&…

尚品汇总结九:RabbitMQ在项目的应用(面试专用)

项目中的问题 1.搜索与商品服务的问题 商品服务修改了 商品的上架状态,商品就可以被搜索到.采用消息通知,商品服务修改完商品上架状态,发送消息 给 搜索服务,搜索服务消费消息,进行商品数据ES保存.下架也是一样. 2.订单服务取消订单问题 延迟队里 保存订单之后 开始计时,…

参考RabbitMQ实现一个消息队列

文章目录 前言小小消息管家1.项目介绍2. 需求分析2.1 API2.2 消息应答2.3 网络通信协议设计 3. 开发环境4. 项目结构介绍4.1 配置信息 5. 项目演示 前言 消息队列的本质就是阻塞队列&#xff0c;它的最大用途就是用来实现生产者消费者模型&#xff0c;从而实现解耦合以及削峰填…

如何将视频转成gif图?视频怎么转gif高清图片?

在看电视或是短视频的时候&#xff0c;总能发现一些有趣的片段&#xff0c;当想把这些视频转gif图片发送给朋友的时候该怎么处理呢&#xff1f;其实可以试试专业的视频转gif工具&#xff0c;本文介绍一个视频在线转gif的方法&#xff0c;一起来了解一下吧。 打开首页&#xff…

重发布选路问题

一、思路 &#xff1b; 1.增加不优选路开销解决选路不佳问题 2.用增加开销的方式使R1 不将ASBR传的R7传给另一台ASBR解决R1、R2、R3、R4pingR7环回环路 二、操作 ------IP地址配置如图 1.解决环路 [r2] ip ip-prefix a permit 7.7.7.0 24 [r2]route-policy huawei per…

c++ boost circular_buffer

boost库中的 circular_buffer顾名思义是一个循环缓冲器&#xff0c;其 capcity是固定的当容量满了以后&#xff0c;插入一个元素时&#xff0c;会在容器的开头或结尾处删除一个元素。 circular_buffer为了效率考虑&#xff0c;使用了连续内存块保存元素 使用固定内存&#x…

The Sandbox 与 D.OASIS 联手打造 D.OASIS 城市

我们非常高兴地宣布与 D.OASIS 建立合作伙伴关系&#xff0c;共同打造无与伦比的娱乐体验&#xff1a;The Sandbox 中的 D.OASIS 城市&#xff01; 作为合作的一部分&#xff0c;The Sandbox 和D.OASIS将共同打造 D.OASIS 城市&#xff0c;一座充满无限可能的大都市&#xff0…