Vue主要原理最简实现与逻辑梳理
Vue的主要原理中主要用到了定义的这么几个函数Dep,Watcher,observer。
我们来使用这几个函数简单的实现一下vue构造函数数据绑定和相互依赖部分,梳理一下它们之间的关系。
省略了编译部分和proxy代理与其他的一些复杂逻辑。
Dep
Dep是依赖类,简要实现为
class Dep {
constructor () {
// 放当时属性的观察者
this.subs = []
}
}
// target 用来挂载当时的watcher观察者
Dep.target = null
observer
做属性劫持,并做点其他事情
function observer (vm, key, val) {
let dep = new Dep()
Object.defineProperty(vm, key, {
/**
* get主要做两个事情
* 1. 收集观察当前key的wathcer(即依赖当前key的操作)
* 2. 获取值
*/
get () {
// 这是作用1
if (Dep.target) {
dep.subs.push(Dep.target)
}
// 这是作用2
return val
},
/**
* set也是两个事情
* 1. 修改目标值
* 2. 执行依赖当前key的watcher
*/
set (newVal) {
// 这是作用1
val = newVal
// 这是作用2
for(cb of dep.subs) {
cb.call(vm)
}
}
})
}
Watcher
Watcher是观察者类,用来创建依赖某属性的操作(如指令,渲染,计算属性等)
class Watcher {
/**
* vm: 实例
* cb: 依赖某属性的操作函数
*/
constructor (vm, cb) {
// 把当前的操作挂载到Dep上
Dep.target = cb
/**
* 执行操作,两个作用
* 1. 进行操作的初始化
* 2. 触发属性的get方法,使当前cb被收集
*/
cb.call(vm)
Dep.target = null
}
}
demo
那么我们就使用上面定义好的函数写个例子
```<div>
<p class="text"></p>
<div>
```
let vm = new Vue({
// 假设有data
data: {msg: 1},
// 有某个v-text操作,我们抽象为vText函数,依赖属性msg(代表所有依赖其他属性的操作)
renderFun: {
vText () {
document.querySelector('.text').innerText = this.msg
}
}
})
// 修改vue实例的值,观察变化
vm.msg = 333
那么我们也写一个vue的简易构造函数
class Vue {
constructor (options) {
let data = options.data
let renderFun = options.renderFun
// initData
Object.keys(data).forEach(key => {
observer(this, key, data[key])
})
// 模拟计算属性,watcher,指令等依赖属性的操作
Object.keys(renderFun).forEach(key => {
new Watcher(this, renderFun[key])
})
}
}
执行过程
完整的代码可以看demo部分的两个链接
- 创建vue实例,执行
new Vue() 对data进行初始化,对
data中属性进行属性劫持- 劫持过程中,在闭包内创建对当前属性的依赖队列(dep.subs)和值(val)。
get进行观察者watcher的收集和值得获取;set进行值的更新和依赖队列中watcher的执行
- 劫持过程中,在闭包内创建对当前属性的依赖队列(dep.subs)和值(val)。
- 对编译过程中如
computed\watcher或模板编译过程中的指令函数进行初始化,我们以renderFun代替 - 针对
renderFun中的每个功能函数进行new Watcher()工作 以
vText为例子,在new Wathcer()过程中- 将
vText挂载到全局通用的Dep.target上 - 执行
vText,其中有读vm.msg的操作,则触发msg属性的get,进入Dep.target判断,将Dep.target即vText收集进msg的subs依赖队列中,此时vText执行完毕,页面innetText被修改 - 将
Dep.target置空
- 将
执行
vm.msg = 333,则触发msg的setset先修改msg的值- 再执行
msg依赖队列中的所有watcher的函数,即vText,页面的innerText被同步更新
总结
总之几者的关系就是在observer的get中将对当前属性的watcher收集进dep,在observer的set中执行收集到的watcher。
而vue的真正的执行过程绝不是上面写的这么简单,比如watcher的执行就绝不是简单的遍历执行,而且还对observer进行了很大程度的简化。我们还省略了诸如_proxy、defineReactive等出现频率较高的函数。写这样一个最简实现主要是为了梳理一下主干,降低阅读源码的难度。
??????????????????????????????????
原文地址:https://segmentfault.com/a/1190000014195710
Vue主要原理最简实现与逻辑梳理的更多相关文章
- Vue源码中compiler部分逻辑梳理(内有彩蛋)
目录 一. 简述 二. 编译流程 三. 彩蛋环节 示例代码托管在:http://www.github.com/dashnowords/blogs 博客园地址:<大史住在大前端>原创博文目录 ...
- 【转】Vue.js 2.0 快速上手精华梳理
Vue.js 2.0 快速上手精华梳理 Sandy 发掘代码技巧:公众号:daimajiqiao 自从Vue2.0发布后,Vue就成了前端领域的热门话题,github也突破了三万的star,那么对于新 ...
- (实现)vue.js最简实现
Vue.winward.js vue.js最简实现(the most simple vue.js) 让所有人都看得懂Vue原理 建议看完Vue.winward.js后,结合mpvue源码解读单页应用路 ...
- PPT技术干货1(下)——数据图表分析、逻辑梳理、高效办公
数据分析 让数据指导决策,帮你获得业绩增长 数据展示是PPT必备的基础技能, 有些人是简单粗暴的将数据直接堆在页面上: 这样的汇报缺乏重点,不具有针对性. 图表该如何设计呢? 1.数据可视化,内容交互 ...
- Vue2源码分析-逻辑梳理
很久之前就看完vue1,但是太懒就一直没写博客,这次打算抽下懒筋先把自己看过了记录下来,否则等全部看完,估计又没下文了 看源码总需要抱着一个目的,否则就很难坚持下去,我并没做过vue的项目,我几乎很少 ...
- Vue源码翻译之渲染逻辑链
本篇文章主要要记录说明的是,Vue在Vdom的创建上的相关细节.这也是描绘了Vue在界面的创建上的一个逻辑顺序,同时我也非常拜服作者编码的逻辑性,当然或许这么庞大复杂的编码不是一次性铸就的,我想应该也 ...
- DRF 商城项目 - 购物( 购物车, 订单, 支付 )逻辑梳理
购物车 购物车模型 购物车中的数据不应该重复. 即对相同商品的增加应该是对购买数量的处理而不是增加一条记录 因此对此进行联合唯一索引, 但是也因此存在一些问题 class ShoppingCart(m ...
- DRF 商城项目 - 用户( 登录, 注册,登出,个人中心 ) 逻辑梳理
用户登录 自定义用户登录字段处理 用户的登录时通过 手机号也可以进行登录 需要重写登录验证逻辑 from django.contrib.auth.backends import ModelBacken ...
- 『TensorFlow』分布式训练_其一_逻辑梳理
1,PS-worker架构 将模型维护和训练计算解耦合,将模型训练分为两个作业(job): 模型相关作业,模型参数存储.分发.汇总.更新,有由PS执行 训练相关作业,包含推理计算.梯度计算(正向/反向 ...
随机推荐
- HDOJ 2196 Computer 树的直径
由树的直径定义可得,树上随意一点到树的直径上的两个端点之中的一个的距离是最长的... 三遍BFS求树的直径并预处理距离....... Computer Time Limit: 1000/1000 MS ...
- 持续集成(CI)工具------Hudson/Jenkins(Continuous Integration)安装与配置具体解释
本文同意转载.但请标明出处:http://blog.csdn.net/wanghantong/article/40985653/, 版权全部 文章概述: 一. 描写叙述了持续集成工具Hudson的安装 ...
- C/C++大小端模式与位域
一.大端小端: 1.大端:指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中 例如:0x12345678 在内存中的存储为 : 0x0000 0x0001 0x0002 0x00 ...
- bzoj4950: [Wf2017]Mission Improbable
跟着靖靖做题%%%%% 这题一看就觉得和之前的某场模拟赛的一道题很像,找假如某行某列的最大值一样的就可以只堆一个,跑匈牙利就行 一开始以为箱子不能移动-_-! 然后有个坑,大家都知道当这个位置有箱子就 ...
- DCloud-MUI:代码块
ylbtech-DCloud-MUI:代码块 1.返回顶部 1. 怎么用? html 此底色代表最小触发字符 此底色代表非必要完整触发字符 *需HBuilder7.1+,或者下载m ...
- iOS获取相册/相机图片-------自定义获取图片小控件
一.功能简介 1.封装了一个按钮,点击按钮,会提示从何处获取图片:如果设备支持相机,可以从相机获取,同时还可以从手机相册获取图片. 2.选择图片后,有一个block回调,根据需求,将获得的图片拿来使用 ...
- [Apple开发者帐户帮助]四、管理密钥(1)创建私钥以访问服务
私钥允许您访问和验证与某些应用服务(如APN,MusicKit和DeviceCheck)的通信.您将在对该服务的请求中使用JSON Web令牌(JWT)中的私钥. 所需角色:帐户持有人或管理员. 在“ ...
- python 5:str(某一变量)(将其他数字解释为字符串)
age = messege = "Your's age is " + str(age) #将其他数字更改为字符串 print(messege) 运行结果应该是: Your's ag ...
- .net core 下Web API 技术栈
API文档工具:swagger https://www.cnblogs.com/suxinlcq/p/6757556.html https://www.cnblogs.com/danvic712/p/ ...
- CSS样式优先级和权重问题(部分)
内联样式: <div style="font-size: 12px;">姓名</div> 外部样式: <link rel="styleshe ...