以下内容来自公众号逆锋起笔,关注每日干货及时送达

作者:Rudy24

链接:https://juejin.cn/post/7040733315791323143

  • 面试官:看过 Vue 的源码没?

  • 候选者:看过。

  • 面试官:那你说下 Vue data 中随意更改一个属性,视图都会被更新吗?

  • 候选者:不会。

  • 面试官:why?

  • 候选者:如果该属性没有被用到 template 中,就没有必要去更新视图,频繁这样性能不好。

  • 面试官:那 Vue 中是如何去实现该方案的?

  • 候选者:在实例初始化过程中,利用Object.defineProperty对 data 中的属性进行数据监听,如果在 template 中被使用到的属性,就被 Dep 类收集起来,等到属性被更改时会调用notify更新视图。

  • 面试官:那你怎么知道那些属性是在 template 被用到的呢?

  • 候选者:WTF。。。这个倒不是很清楚,您能解释下吗?

  • 面试官:OK,那我就简单解释下:

先写个简单的 demo,其中 data 中有 4 个属性a,b,c,d,在模板中被利用到的属性只有a,b。看看是不是只有a,b才会调用Dep收集起来呢?

new Vue({el: '#app',data() {return {a: 1,b: 2,c: 3,d: 4,};},created() {console.log(this.b);this.b = 'aaa';},template: '<div>Hello World{{a}}{{b}}</div>',
});
复制代码
  1. 在Vueinstance/state.js里面,会利用proxy把每个属性都 代理一遍

const keys = Object.keys(data)const props = vm.$options.propsconst methods = vm.$options.methodslet i = keys.lengthwhile (i--) {const key = keys[i]if (props && hasOwn(props, key)) {process.env.NODE_ENV !== 'production' && warn(`The data property "${key}" is already declared as a prop. ` +`Use prop default value instead.`,vm)} else if (!isReserved(key)) {// 代理对象的属性proxy(vm, `_data`, key)}}// observe dataobserve(data, true /* asRootData */)
复制代码
  1. 利用defineReactive对data中的每个属性进行劫持

observe(data, true /* asRootData */);// observe
const keys = Object.keys(obj);
for (let i = 0; i < keys.length; i++) {defineReactive(obj, keys[i]);
}// defineReactive
Object.defineProperty(obj, key, {enumerable: true,configurable: true,get: function reactiveGetter() {const value = getter ? getter.call(obj) : val;// 重点在这里,后续如果在模板中使用到的属性,都会被执行reactiveGetter函数// 被Dep类 收集起来if (Dep.target) {console.log(`${key} 属性 被Dep类收集了`)dep.depend();if (childOb) {childOb.dep.depend();if (Array.isArray(value)) {dependArray(value);}}}return value;},set: function reactiveSetter(newVal) {const value = getter ? getter.call(obj) : val;/* eslint-disable no-self-compare */if (newVal === value || (newVal !== newVal && value !== value)) {return;}if (setter) {// 这里是处理computed set 函数setter.call(obj, newVal);} else {val = newVal;}childOb = !shallow && observe(newVal);// 如果我们在更改属性时,就会调用notify 异步更新视图dep.notify();},
});
复制代码
  1. 执行$mount进行视图挂载

if (vm.$options.el) {vm.$mount(vm.$options.el);
}
复制代码
  1. $mount 是调用 Vue 原型上的方法, 重点是最后一句 mount.call(this, el, hydrating)

Vue.prototype.$mount = function (el?: string | Element,hydrating?: boolean
): Component {el = el && query(el);const options = this.$options;// resolve template/el and convert to render function/*** 查看render 函数是否存在?如果不存在就解析template模板* Vue渲染页面时,有两个方式 1. template,2. render,最终所有的模板类的都需要使用render去渲染*/if (!options.render) {let template = options.template;if (template) {if (typeof template === 'string') {if (template.charAt(0) === '#') {template = idToTemplate(template);/* istanbul ignore if */if (process.env.NODE_ENV !== 'production' && !template) {warn(`Template element not found or is empty: ${options.template}`,this);}}} else if (template.nodeType) {template = template.innerHTML;} else {if (process.env.NODE_ENV !== 'production') {warn('invalid template option:' + template, this);}return this;}} else if (el) {// 如果模板不存在,就创建一个默认的html模板template = getOuterHTML(el);}}// 重写了Vue.prototype.$mount ,最终调用缓存的mount方法完成对$mount的挂载return mount.call(this, el, hydrating);
};
复制代码
  1. 这里mount调用了 mountComponent(this, el, hydrating) 方法,而 mountComponent是执行了 _render函数,最终_render是调用render 生成一个vnode

const { render, _parentVnode } = vm.$options;
vnode = render.call(vm._renderProxy, vm.$createElement);
复制代码

最后一张图可以看到是render函数在渲染我们demo里面的template模板,最终只有a, b两个属性才会被Dep类收集起来。微信搜索readdot,关注后回复视频教程获取23种精品资料

image.png

如果文中有错误的地方,麻烦各位指出,我会持续改进的。谢谢, 需要调试源码的,这里点击这里,按照 readme操作即可。

逆锋起笔专注于程序员圈子,你不但可以学习到javapython等主流技术干货,还可以第一时间获悉最新技术动态内测资格BAT大佬的经验精品视频教程副业赚钱经验,微信搜索readdot关注!

Vue3 相比于 Vue2 有哪些 “与众不同”?

Vue 开发最佳指南,你都需要学点啥?

记一次 Vue3.0 技术分享会

Vue 实战中的一些小魔法

一名 Vue 程序员总结的 React 基础

点一下,代码无 Bug

Vue data 中随意更改一个属性,视图都会被更新吗?相关推荐

  1. android addview指定位置,Android开发中,请问当在一个视图中addView另一个布局视图时为什么报错?...

    Android开发中,我在一个视图中addView另一个布局视图(该视图通过inflate加载获得,其中root为null即没有附加parent视图),为什么还是会报错误: The specified ...

  2. 有属性的自定义注解,如何获取到post请求中RequestBody中对象的一个属性值?

    1,写两个自定义注解,一个作用于方法的,一个作用于字段的 作用于方法的自定义注解代码: package com.youku.nintendo.annotation;import enums.Permi ...

  3. 微信小程序,直接给data中的对象添加属性

    data:{ testData:{} }, onLoad(){ const testData = this.data.testData;this.setData({['testData.li']:'1 ...

  4. 在SAP系统中,更改一个公司代码(Company Code)的会计科目表(Chart of Accounts)

    通常,我们在SAP系统中会通过复制一个已有的公司代码来创建一个新的公司代码.这种情况下,如果我们想改变"新创建出的company code"的会计科目表,应该如何做呢? 通常需要如 ...

  5. python中如何对一个属性或方法进行封装_python学习第20天

    一.面向对象oop - 封装 1.类中封装: 成员属性和成员方法 2.封装等级 公有:公有成员既能够在类外调用,也可以在类调用 私有:私有成员不能够在类外调用,可以在类内调用 (前面加上双下划线表示) ...

  6. vue data 中的 return 用法

    文章目录 一.vue 里面的data return 是什么? 二.如何使用 1.vue 双向绑定 v-model 2.带有 ":"的属性 比如:class.:id等等 3. 标签使 ...

  7. java properties $,如何引用java.util.Properties中的另一个属性?

    由于eproperties是有点不维护和commonsconfiguration依赖于日志logging(具有讽刺意味的是你不能用它来configuration日志logging)我使用这个代码片段, ...

  8. 遍历一个类中的每一个属性、方法、公共字段

    //获取对象类型     Type   t   =   obj.GetType();     //获取类的属性     PropertyInfo[]   propertys   =   t.GetPr ...

  9. vue监听对象某一个属性

    watch: {uploadObj: {//监听对象deep: true,handler: function(value) {if (!value.receiver && !value ...

最新文章

  1. XGBOOST带试验源码
  2. Ansible9:条件语句【转】
  3. sudo: /etc/sudoers is world writable 错误解决方案
  4. ChannelFactory创建和销毁昂贵
  5. jvm在windows和linux,理解JVM如何使用Windows和Linux上的本机内存
  6. leetcode 421. Maximum XOR of Two Numbers in an Array | 421. 数组中两个数的最大异或值(位运算,Trie前缀树)
  7. selenium java 断言_Java+Selenium+Testng自动化测试学习(三)— 断言
  8. python入门需要有什么基础?
  9. Windows server 2008 R2实现多用户远程连接
  10. SpringMVC入门笔记
  11. python数据类型—字符串
  12. php自己编译扩展,Linux编译PHP添加扩展库的方法
  13. 《PRML》学习笔记2.2——多项式分布和狄利克雷分布
  14. win10桌面背景为什么突然变黑了 win10桌面背景不显示解决方法
  15. 使用空驱动消除设备管理器里面的未知设备
  16. Messari:21年第二季度Web3及NFT报告
  17. Jmeter dubbo插件测试dubbo接口
  18. 20180402-A · US Tuition Costs · ggplot2, 折线图 · R 语言数据可视化 案例 源码
  19. 等边三角形的积木编程
  20. 【渝粤教育】电大中专新媒体营销实务 作业 题库

热门文章

  1. MATLAB的交互式界面 简易设计
  2. 如何用随机森林算法,在深海养肥一群鱼
  3. 激光雷达和毫米波雷达工作原理对比
  4. C++——素数(质数)专题训练
  5. 汇编实现文件内容的base64编码
  6. 当前对计算机专业人才的要求,关于计算机专业人才需求的分析
  7. python列表推导式去除m3u8中的广告视频地址下载视频
  8. 2019多校第三场 HDU6608 Fansblog(威尔逊定理,逆元,质数间隔)
  9. 北京大学肖臻老师《区块链技术与应用》ETH笔记 - 8.0 ETH挖矿难度的调整
  10. TIA博途V16专业版与博途V15.1专业版或其他版本能否安装在同一台PC中?