Vue之Watcher源码解析(2)


Posted in Javascript onJuly 19, 2017

接着上节Vue Watcher源码的话,继续探讨,目前是这么个过程:

Vue之Watcher源码解析(2)

函数大概是这里:

// line-3846
  Vue.prototype._render = function() {

    // 获取参数

    try {
      // 死在这儿
      vnode = render.call(vm._renderProxy, vm.$createElement);
    } catch (e) {
      // 报render错误
    }
    // return empty vnode in case the render function errored out
    if (!(vnode instanceof VNode)) {
      // 返回空节点
    }
    // set parent
    vnode.parent = _parentVnode;
    return vnode
  };

然后,在上个月,我卡死在了render.call这个函数上面,因为所有vue实例被设置了proxy代理,所以会跳转到各种奇怪的检测函数中。

过了一个月,我依然看不懂,一点都不想讲,所以先跳过,直接看后面!

这里假设vnode已经返回了,来看看是个啥:

Vue之Watcher源码解析(2)

Vue之Watcher源码解析(2)

这是一个虚拟节点,由之前字符串化后的DOM树生成,主要包含子节点、上下文、属性、文本、标签名、类型等属性,这些可以直接从键名判断。

得到vnode后,由于这里是根节点,所以不存在_parentVnode,直接返回。

然后到了mountComponent函数:

// line-2374
  function mountComponent(vm, el, hydrating) {
    vm.$el = el;
    // error
    callHook(vm, 'beforeMount');

    var updateComponent;
    /* istanbul ignore if */
    if ("development" !== 'production' && config.performance && mark) {
      updateComponent = function() {
        // 开发者模式下的处理方式
      };
    } else {
      // 重新进入这里
      updateComponent = function() {
        vm._update(vm._render(), hydrating);
      };
    }

    vm._watcher = new Watcher(vm, updateComponent, noop);
    hydrating = false;

    // manually mounted instance, call mounted on self
    // mounted is called for render-created child components in its inserted hook
    if (vm.$vnode == null) {
      vm._isMounted = true;
      callHook(vm, 'mounted');
    }
    return vm
  }

这样,就带着返回的vode进入了_update函数,开始正式渲染页面。

函数如下:

// line-2374
  Vue.prototype._update = function(vnode, hydrating) {
    var vm = this;
    if (vm._isMounted) {
      callHook(vm, 'beforeUpdate');
    }
    // 保存原属性
    var prevEl = vm.$el;
    var prevVnode = vm._vnode;
    var prevActiveInstance = activeInstance;
    activeInstance = vm;
    vm._vnode = vnode;
    // patch
    if (!prevVnode) {
      // 初始化渲染
      vm.$el = vm.__patch__(
        vm.$el, vnode, hydrating, false /* removeOnly */ ,
        vm.$options._parentElm,
        vm.$options._refElm
      );
    } else {
      // 更新
      vm.$el = vm.__patch__(prevVnode, vnode);
    }
    activeInstance = prevActiveInstance;
    // update __vue__ reference
    if (prevEl) {
      prevEl.__vue__ = null;
    }
    if (vm.$el) {
      vm.$el.__vue__ = vm;
    }
    // if parent is an HOC, update its $el as well
    // HOC => High Order Component => 高阶组件
    if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
      vm.$parent.$el = vm.$el;
    }
    // updated hook is called by the scheduler to ensure that children are
    // updated in a parent's updated hook.
  };

由于是初次渲染,所以会进入第一个条件分支,并调用__patch__函数,传入原生DOM节点、虚拟DOM、false三个参数。

__patch__在加载框架时候已经注入了,见代码:

// line-7526
  // install platform patch function
  Vue$3.prototype.__patch__ = inBrowser ? patch : noop;

  // line-6968
  var patch = createPatchFunction({
    nodeOps: nodeOps,
    modules: modules
  });

这里,nodeOps为封装的DOM操作操作方法,modules为属性、指令等相关方法。

这个createPatchFunction函数的构造相当于一个模块,里面包含大量的方法,但是最后不是返回一个对象包含内部方法的引用,而是返回一个函数,形式大概如下:

// line-4762
  function createPatchFunction() {
    // fn1...
    // fn2...
    return function patch() {
      // 调用内部方法fn1,fn2...
    }
  }

方法比较多,下次再讲,边跑流程边看。

Vue之Watcher源码解析(2)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
动感效果的TAB选项卡jquery 插件
Jul 09 Javascript
JavaScript中奇葩的假值示例应用
Mar 11 Javascript
JavaScript常用验证函数实例汇总
Nov 25 Javascript
node.js中的fs.readlink方法使用说明
Dec 17 Javascript
创建自己的jquery表格插件
Nov 25 Javascript
jQuery+formdata实现上传进度特效遇到的问题
Feb 24 Javascript
第三篇Bootstrap网格基础
Jun 21 Javascript
浅谈javascript中的Function和Arguments
Aug 30 Javascript
原生JS实现图片轮播切换效果
Dec 15 Javascript
让bootstrap的carousel支持滑动滚屏的实现代码
Nov 27 Javascript
基于Vue实现拖拽功能
Jul 29 Javascript
JS如何在不同平台实现多语言方式
Jul 16 Javascript
Angular.js项目中使用gulp实现自动化构建以及压缩打包详解
Jul 19 #Javascript
JS+canvas实现的五子棋游戏【人机大战版】
Jul 19 #Javascript
Vue学习笔记进阶篇之vue-router安装及使用方法
Jul 19 #Javascript
Vue学习笔记进阶篇之单元素过度
Jul 19 #Javascript
jQuery实现可编辑表格并生成json结果(实例代码)
Jul 19 #jQuery
jQuery实现导航栏头部菜单项点击后变换颜色的方法
Jul 19 #jQuery
利用require.js与angular搭建spa应用的方法实例
Jul 19 #Javascript
You might like
php文件扩展名判断及获取文件扩展名的N种方法
2015/09/12 PHP
详解php比较操作符的安全问题
2015/12/03 PHP
PHP长连接实现与使用方法详解
2018/02/11 PHP
javascript的函数
2007/01/31 Javascript
prototype Element学习笔记(篇二)
2008/10/26 Javascript
jquery解析xml字符串示例分享
2014/03/25 Javascript
js锁屏解屏通过对$.ajax进行封装实现
2014/07/31 Javascript
JavaScript函数定义的常见注意事项小结
2014/09/16 Javascript
jquery删除指定子元素代码实例
2015/01/13 Javascript
详解原生JavaScript实现jQuery中AJAX处理的方法
2016/05/10 Javascript
jQuery.ajax 跨域请求webapi设置headers的解决方案
2016/08/08 Javascript
jQuery多级联动下拉插件chained用法示例
2016/08/20 Javascript
javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】
2016/12/15 Javascript
bootstrap table实例详解
2017/01/06 Javascript
angular.fromJson与toJson方法用法示例
2017/05/17 Javascript
vue axios 给生产环境和发布环境配置不同的接口地址(推荐)
2018/05/08 Javascript
webpack4实现不同的导出类型
2019/04/09 Javascript
jquery-ui 进度条功能示例【测试可用】
2019/07/25 jQuery
如何使用50行javaScript代码实现简单版的call,apply,bind
2019/08/14 Javascript
解决LayUI数据表格复选框不居中显示的问题
2019/09/25 Javascript
Python中方法链的使用方法
2016/02/23 Python
对pandas写入读取h5文件的方法详解
2018/12/28 Python
python3+selenium自动化测试框架详解
2019/03/17 Python
Python实现Word表格转成Excel表格的示例代码
2020/04/16 Python
Python pip使用超时问题解决方案
2020/08/03 Python
基于Python-Pycharm实现的猴子摘桃小游戏(源代码)
2021/02/20 Python
Jowissa官方网站:瑞士制造的手表,优雅简约的设计
2020/07/29 全球购物
OSPF有什么优点?为什么OSPF比RIP收敛快?
2013/02/13 面试题
自荐信格式技巧有哪些呢
2013/11/19 职场文书
毕业自我评价
2014/02/05 职场文书
团委书记的竞聘演讲稿
2014/04/24 职场文书
预备党员公开承诺书
2014/05/28 职场文书
应届生自荐信
2014/06/30 职场文书
高中校园广播稿3篇
2014/09/29 职场文书
php双向队列实例讲解
2021/11/17 PHP
Windows Server 2012 R2 磁盘分区教程
2022/04/29 Servers