上图,无图无真相


花了400大洋买了frontedmasters的一个月的会员,就是为了看男神的这份vue教程,没有中文字幕,痛苦地坚持啃完了,建议有钱并且英语好的人直接买会员去官网看视频,尤大神人长得帅,业务水平高,英语还超苏,对不起,忍不住犯了会儿花痴,如果没钱英语又渣的人只能看我的总结了,看我的文章的好处就是不用花钱,不用被英语折磨,坏处就是本人的文字水平和业务水平真的有限,不会一步步引导式地分析原理和代码的实现,只能贴代码和尽我所能来解释了,能理解多少就看大家的水平了,这算不算无良商家,不包售后啊,哈哈。

这个系列文章将从下面几个方面来介绍vue

reactivity(响应式)
plugin(插件)
render(渲染函数)
routing(路由)
state-management(状态管理)
international(多语言支持)
1 reactivity

相信了解过vue的同学都知道,vue是MVVM框架,最大的特点就是双向数据绑定,数据Model修改了之后视图View会自动更新, view也可以通过v-model的将ViewModel的变化同步到Model里面

这篇文章要探讨的问题:vue是如何监控数据的变化从而自动更新视图,也就是vue响应式是如何实现的,我们一步步来看。

1.1. getter and setter

考虑下面这段代码,一个简单的代数计算关系,b依赖a, b是a的10倍

 var a= 10;var b = a*10;a = 20//b = ? 如何监听b的变化
复制代码

请认真思考一下再往下看:当每次改变a的值的时候,如何监听a的变化并且更新b,保证他们的数学关系b是a的10倍?

给大家留了10行空白,不知道大家有没有认真思考上面的问题?

不卖关子了,直接用两个数值,我们目前无法监控,可以换种思路,直接监控一个数值变量行不通,我们可以监控一个对象属性的变化,在属性改变的时候收集它的依赖,就可以触发依赖的更新

js有一个方法Object.defineProperty可以劫持属性的读取器getter和setter, 来看个例子

 let obj = {a:10};observer(obj, 'a');obj.a = 20;let b = obj.a;obj.a = 30;// 实现一个函数,可以监控到对象属性的变化function observer(obj, key) {Object.defineProperty(obj, key, {configurable: true, // 可以被deleteenumerable: true, // for in迭代set(val) {console.log(`对象的属性${key}被赋值了${val}`);},get() {console.log(`对象的属性${key}被读取了`);}});}//对象的属性a被赋值了20//对象的属性a被读取了//对象的属性a被赋值了30
复制代码

从上面的例子可以看出, 我们只要用 Object.defineProperty重写对象的属性读写器getter和setter就可以监听到对象属性的变化,上面的代码只可以监控一个属性的变化,对于对象的所有属性,需要遍历转换,改造一下observer方法(这里只考虑一层对象,深层次的需要递归遍历,数组的监控也需要另写方法,有兴趣的去看vue的源码)

 function observer(obj) {Object.keys(obj).forEach(key => {let internalValue = obj[key]Object.defineProperty(obj, key, {get() {console.log(`getting key "${key}": ${internalValue}`)return internalValue},set(newVal) {console.log(`setting key "${key}" to: ${internalValue}`)internalValue = newVal}})})}
复制代码

现在我们已经可以监听到一个对象所有属性的变化了,最开始提出的问题已经解决了一半了,接下来要解决的问题是当属性变化的时候,如何收集它的依赖,触发依赖的更新呢?也就是我们这篇文章的主题,如何实现一个简易的响应式系统。

思路就是:在读取属性的时候收集依赖,在改变属性值的时候触发依赖的更新

实现一个observer,劫持对象属性的getter和setter
实现一个全局的订阅器Dep,可以追加订阅者,和通知依赖更新
在读取属性的时候追加当前依赖到Dep中,在设置属性的时候循环触发依赖的更新
按照这个思路,实习一个简易的响应式系统。

 // 全局的依赖收集器Depwindow.Dep = class Dep {constructor() {this.subscribers = new Set(); // 保证依赖不重复添加}// 追加订阅者depend() {if(activeUpdate) { // activeUpdate注册为订阅者this.subscribers.add(activeUpdate)}}// 运行所有的订阅者更新方法notify() {this.subscribers.forEach(sub => {sub();})}}let activeUpdate// js单线程语言,任一时刻只能有一个函数执行,也就是任一时刻,只可能有一个依赖在更新 //用一个全局变量activeUpdate来标志,这里有点不好理解,大家多想想就会明白autorun的巧妙之处了// autorun接受一个更新函数function autorun(update) {function wrapperUpdate() {activeUpdate = wrapperUpdateupdate() // wrapperUpdate, 闭包activeUpdate = null;}wrapperUpdate();}function observer(obj) {Object.keys(obj).forEach(key => {var dep = new Dep(); // 为每个key创建订阅器Deplet internalValue = obj[key]Object.defineProperty(obj, key, {get() {// console.log(`getting key "${key}": ${internalValue}`)// 将当前正在运行的更新函数追加进订阅者列表if(activeUpdate) { dep.depend() //收集依赖}return internalValue},set(newVal) {//console.log(`setting key "${key}" to: ${internalValue}`)// 加个if判断,数据发生变化再触发更新if(internalValue !== newVal) {internalValue = newValdep.notify() // 触发依赖的更新}}})})}let state = {count:0}observer(state);autorun(() => {console.log('state.count发生变化了', state.count)})state.count = state.count + 5;// state.count发生变化了 0// state.count发生变化了 5
复制代码

这篇文章先更到这里,后续内容有时间继续更新,虽然更新时间不定,但是计划月底更新完,希望喜欢的小伙伴多多关注和支持,谢谢。

最后

分享移动开发与微信小程序开发该做哪些!其中有哪些关键的技术点!需要下图学习教程的欢迎加入web前端交流群:854591759获取!
点击链接加入群聊【web前端交流群】:

和尤雨溪一起进阶vue相关推荐

  1. 尤雨溪回应:Vue与TypeScript为什么相性特别差?

    近日,有开发者在知乎上提出了一个问题:"TypeScript 不适合在 vue 业务开发中使用吗?",Vue的作者尤雨溪针对这一问题发表了自己的看法,也解释了Vue 3.0选用Ty ...

  2. 尤雨溪亲自回应Vue.js涉及国家安全漏洞问题

    最近,有两幅关于 Vue 安全问题的截图在业界广为传播,截图内容表明目前有多家公司统计软件开发过程中使用 Vue.js 和 SonarQube 的情况,疑似有黑客利用 Vue.js 和 SonarQu ...

  3. 请停止搬运部署,尤雨溪官申Vue 3官方文档地址

    北京时间9月22日,Vue 框架创始人尤雨溪通过个人微博申明 Vue 3以及 Vited 的官方中文文档地址,它们分别是 v3.cn.vuejs.org,Vite 的官方中文文档地址是 cn.vite ...

  4. 专访Vue作者尤雨溪:Vue CLI 3.0重构的原因

    1.为什么要对 Vue CLI 进行大规模修改? 尤雨溪认为旧版本的 Vue CLI 本质上只是从 GitHub 拉取模版,这种拉模版的方式有几个问题: (1) 在单个模版里面同时支持太多选项会导致模 ...

  5. 专访尤雨溪:先别管4.0了,Vue CLI重构了解一下

    \ 上个月,Vue CLI 3.0 正式发布,为很多开发者带来期待已久的新特性,尤雨溪也说 Vue CLI 3.0 经历了重构,旨在尽可能减少现代前端工具在配置上的烦恼,并尽可能在工具链中加入最佳实践 ...

  6. Vue 2.0的建议学习顺序(尤雨溪)

    起步 扎实的 JavaScript / HTML / CSS 基本功.这是前置条件. 通读官方教程 (guide) 的基础篇.不要用任何构建工具,就只用最简单的script,把教程里的例子模仿一遍,理 ...

  7. Vue 涉及国家安全漏洞?尤雨溪亲自回应!

    点击上方"Java精选",选择"设为星标" 别问别人为什么,多问自己凭什么! 下方有惊喜,留言必回,有问必答! 每一天进步一点点,是成功的开始... 两张来源不 ...

  8. Vue 新 ref 语法糖提案引热议 尤雨溪回复

    近日,Vue 发明人尤雨溪在 Vue RFCs 下提交了一份新的 Ref 语法糖提案,该提案一经发布便引来了不少争议. 提案内容 这份提案就是在单文件组织(SFC)中引入一个新的script 标签写法 ...

  9. 新手入门指导:Vue 2.0 的建议学习顺序——尤雨溪

    起步 1. 扎实的 JavaScript / HTML / CSS 基本功.这是前置条件. 2. 通读官方教程 (guide) 的基础篇.不要用任何构建工具,就只用最简单的 <script> ...

最新文章

  1. js动态变量名_scss引入其他scss变量,并通过js动态修改scss变量
  2. 统一客服消息返回错误:{errcode:43004,errmsg:require subscribe hint: [9Vv08633952]}
  3. [jquery]if条件句
  4. 阿里云安装mysql5.6_yum安装mysql 5.6-阿里云开发者社区
  5. python中paste函数的作用_PIL使用小结(crop和paste函数)
  6. centos6.3 nginx php,CentOS 6.3下nginx、php-fpm、drupal快速部署
  7. spark DAGScheduler、TaskSchedule、Executor执行task源码分析
  8. SpringBoot2 Spring Cloud Config Server和Config Client分布式配置中心使用教程
  9. 基于Django+链家+Bootstrap真实数据的房源推荐/可视化系统
  10. 浙江省高校教师职称计算机考试成绩查询系统,浙江省高校招生考试信息管理系统...
  11. win10清理_win10不再需要杀毒软件,同时建议不要安装垃圾清理类软件
  12. java实现日历打印
  13. 祁连山:西部生态安全的守护者
  14. CSS学习30:多媒体标签(视频音频)
  15. stata学习笔记|异方差问题
  16. 二进制(一):由来及简介
  17. 总结-互联网校招面试锦囊
  18. AJAX都有哪些优点和缺点
  19. 十五天学会Autodesk Inventor,看完这一系列就够了(十一),放样和螺旋扫掠(绘弹簧)
  20. 图形性能测试软件,跨平台图形性能基准测试软件3DMark Wild Life发布

热门文章

  1. 基于JAVA的疫情防控核酸检查管理系统【数据库设计、源码、开题报告】
  2. JAVA基础语法——面向对象思想
  3. 8、Opencv实现文档扫描
  4. 作为一个程序员,读不懂Spring就像读不懂对象的心?
  5. SEO运营思路分享:如何通过4步快速引爆你的网站排名!
  6. 计算机一级系统压缩密码,教你如何设置密码保护Win10系统压缩文件夹?
  7. 生产制造业网络运维监控方案
  8. 地平线发布AI on Horizon战略,边缘AI芯片开放赋能智能驾驶...
  9. 新年寄望:从小做起,活在当下
  10. 在事件循环中使用暂停器