踏入前端,步入玄学

 17年底至18年初附带做了vue的一些框架搭建,中途断断续续用了部分vue,时隔几个月后的工作又拾起vue,对于一些原理性的知识淡忘了,正值这段时间使用中遇到了一些坑,又拨了部分代码出来温习温习。

正式进入大前端,新同事称谓的玄学...

读在最前面:

  1、本文根据问题,讲述大致 Vue虚拟Dom Diff 思路、数据响应式机制相关,源码版本 Vue.js v2.5.17-beta.0

       2、知识点:vue virtual dom diff、 observe 、 watch、render ,各知识点暂不深入剖析

  3、阅读本文,读者应了解Vue有一定的前端基础,知道一些名词概念如:render、vnode、virtual dom

  4、本文先引出问题及原理,然后单用2个实现给出详情解析

  4、v-if案例解析(element-ui  form-item表单无法验证问题剖析 )(问1)

  5、watch案例解析(element-ui el-select 无法选中问题剖析)(问2)

直接甩疑问案例,Fire!

问1:当v-if为true时,会重新渲染相关dom节点吗?

问题来源(element-ui  form-item表单无法验证问题剖析)

<child v-if="true"><child>

答:会!(什么??? 难道v-if 为true不应该一直坚强到最后吗,是什么让她如此虚弱)

涉及 知识点 vue virtual dom diff

问题原理:

前言:vue2 引入了虚拟dom,即如果使用.vue的模板方式书写,会首先编译为render函数,生成vnode,每次数据变更后,会在nexttick中进行新老vnode对比进行patch操作

1、对比前后 vnode对象相同颜色的节点进行同层级对比 ,如下图

2、我们挑选黄色节点说明:0、1、2标识节点序号 , 头、尾 分别代表节点的头部和节点的尾部

对比序号从0、0(分别对应老节点序号0,新节点序号0)开始 ,每一次循环对比一个节点数据(使用sameVNode方法判断,见下面代码示例,源码5858行),新老对比范围为 ,老(0-2)新(0-2)

(1)头头,即老0->新0 如果一致,则新老开始节点 序号 +1 同时,跳出循环 ,开始下一个循环对比 新老对比范围为 ,老(1-2)新(1-2)

(2)尾尾,即老2->新2 如果一致,则新老结束节点 序号 -1 同时,跳出循环 ,开始下一个循环对比 新老对比范围为 ,老(0-1)新(0-1)

(3)头尾,即老0->新2 如果一致,则老开始节点 序号 +1,新结束节点序号-1  同时,跳出循环 ,开始下一个循环对比 新老对比范围为 ,老(1-2)新(0-1)

(4)尾头,即老2->新0 如果一致,则老结束节点 序号 -1 ,新开始节点序号+1  同时,跳出循环 ,开始下一个循环对比 新老对比范围为 ,老(0-1)新(1-2)

(5)用新节点去未遍历过的的老节点中查找

(6)老节点全部遍历完或新节点全部遍历完,则退出大循环(对未遍历到的老节点执行删除操作,对未遍历到的新节点执行新增操作)

function sameVnode (a, b) {
return (
a.key === b.key && (
(
a.tag === b.tag &&
a.isComment === b.isComment &&
isDef(a.data) === isDef(b.data) &&
sameInputType(a, b)
) || (
isTrue(a.isAsyncPlaceholder) &&
a.asyncFactory === b.asyncFactory &&
isUndef(b.asyncFactory.error)
)
)
)
}  

大致如图:

问2:子组件中明明有watch value,为什么this.$emit('input', 888);没有触发watch回调,反而在父组件data数据变化后触发回调?

问题来源(element-ui el-select 无法选中问题剖析)

    <child v-model="b"></child> // b在父组件中没有初始化,即没有执行父组件的observe
var child = Vue.extend({
template: '<p>数据响应及render相关-案例说明</p>',
props: {
value: {
required: true
}
},
mounted() {
this.$emit('input', 888);
},
watch: {
value(val, oldVal) {
console.log(val, oldVal, 'child')
}
}
});

涉及 知识点 observe、render、watch

问题原理:

1、vue实例在生成时,会经历比较漫长的初始化过程如:初始化事件、渲染器、注入器、数据代理\劫持等等

2、v-model指令为被默认构造 :value="b" @input="b = xxx" (此处b为上面代码中v-model="b"),执行this.$emit('input', 888),会更新b的值

3、每次data数据变化的时候,会收集watcher进入一个队列,队列中收集了所有此时刻周期中有相关变化形成queueWatcher,在下一个时间周期中进行数据响应更新 flushSchedulerQueue,并执行render 、patch

4、在render中会进行新老vnode patch,在更新过程中会执行node的prepatch(源码5938行)操作,其中会执行updateChildComponent -> validateProp 从而更新了 value的值,从而进入了watch回调

大致如图:

    

by:海豚湾-丰

  

Vue 虚拟Dom 及 部分生命周期初探的更多相关文章

  1. vue虚拟DOM源码学习-vnode的挂载和更新流程

    代码如下: <div id="app"> {{someVar}} </div> <script type="text/javascript& ...

  2. Vue 实例详解与生命周期

    Vue 实例详解与生命周期 Vue 的实例是 Vue 框架的入口,其实也就是前端的 ViewModel,它包含了页面中的业务逻辑处理.数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进 ...

  3. Vue – 基础学习(1):对生命周期和钩子函的理解

    一.简介 先贴一下官网对生命周期/钩子函数的说明(先贴为敬):所有的生命周期钩子自动绑定 this 上下文到实例中,因此你可以访问数据,对属性和方法进行运算.这意味着你不能使用箭头函数来定义一个生命周 ...

  4. Es6语法+v-on参数相关+vue虚拟dom

    Es6的语法 Es5:if和for 都没有块级作用域,函数function有作用域. Es6:加入let使得if和for有作用域 .建议: 在Es6中优先使用const,只有需要改变某一个标识符的时候 ...

  5. 05-Vue入门系列之Vue实例详解与生命周期

    Vue的实例是Vue框架的入口,其实也就是前端的ViewModel,它包含了页面中的业务逻辑处理.数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进行对整个Vue实例生成.编译.挂着. ...

  6. Vue入门系列(五)Vue实例详解与生命周期

    Vue官网: https://cn.vuejs.org/v2/guide/forms.html#基础用法 [入门系列] (一)  http://www.cnblogs.com/gdsblog/p/78 ...

  7. Vue实例详解与生命周期

    http://www.jianshu.com/p/b5858f1e6e76 Vue的实例是Vue框架的入口,其实也就是前端的ViewModel,它包含了页面中的业务逻辑处理.数据模型等,当然它也有自己 ...

  8. vue的MVVM模式和生命周期总结(一)

    一.MVVM模式 MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel ...

  9. Vue学习系列(四)——理解生命周期和钩子

    前言 在上一篇中,我们对平时进行vue开发中遇到的常用指令进行归类说明讲解,大概已经学会了怎么去实现数据绑定,以及实现动态的实现数据展示功能,运用指令,可以更好更快的进行开发.而在这一篇中,我们将通过 ...

随机推荐

  1. 使用 TListView 控件(4)

    本例效果图: 代码文件: unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, ...

  2. Codeforces 494C - Helping People

    题意 有一个长度为 \(n\) 的数列 \(a\),有 \(m\) 个 操作,每个操作是给 \(a[l_i,r_i]\) 中的数都加一,一个操作有 \(p_i\) 的概率执行(否则不执行).一个性质是 ...

  3. 【设计模式】—— 创建者模式Builder

    前言:[模式总览]——————————by xingoo 模式意图 一个对象的创建十分复杂,为了区分构建过程和使用过程,因此分开.使用一个Director类进行对象的创建,Builder规定了这个创建 ...

  4. 【模板】Floyd

    int n; ][MAX_N + ]; void Floyd() { ; k <= n; ++k) { ; i <= n; ++i) { ; j <= n; ++j) { d[i][ ...

  5. javaee, javaweb和javase的区别以及各自的知识体系

    javaee, javaweb和javase的区别以及各自的知识体系 来源 https://blog.csdn.net/weixin_39297312/article/details/79454642 ...

  6. JS发送跨域Post请求出现两次请求的解决办法

    原文地址: http://www.cnblogs.com/JimmyBright/p/7681097.html 所有跨域的js在提交post请求的时候,如果服务端设置了可跨域访问 public sta ...

  7. BZOJ 2427 [HAOI2010]软件安装 | 这道树形背包裸题严谨地证明了我的菜

    传送门 BZOJ 2427 题解 Tarjan把环缩成点,然后跑树形背包即可. 我用的树形背包是DFS序上搞的那种. 要注意dp数组初始化成-INF! 要注意dp顺推的时候也不要忘记看数组是否越界! ...

  8. XStream--java对象与xml形式文件相互转换

    1.pom.xml中添加依赖 <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifa ...

  9. [机器学习]-SVD奇异值分解的基本原理和运用

    SVD奇异值分解: SVD是一种可靠的正交矩阵分解法.可以把A矩阵分解成U,∑,VT三个矩阵相乘的形式.(Svd(A)=[U*∑*VT],A不必是方阵,U,VT必定是正交阵,S是对角阵<以奇异值 ...

  10. Windows一个文件夹下面最多可以放多少文件

    一个文件夹下面最多可以放多少文件 这个问题其实我也不知道,不过我们可以来进行个测试,看看文件夹下面最多能放多少个文件. 那么怎么来测试这样一个问题呢,很显然我们一个个的去建立文件是不现实的,没那么多时 ...