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 相关文章推荐
js/jquery解析json和数组格式的方法详解
Jan 09 Javascript
ECMAScript6的新特性箭头函数(Arrow Function)详细介绍
Jun 07 Javascript
Javascript判断文件是否存在(客户端/服务器端)
Sep 16 Javascript
做web开发 先学JavaScript
Dec 12 Javascript
javascript实现节点(div)名称编辑
Dec 17 Javascript
JSON字符串转JSON对象
Jul 31 Javascript
玩转NODE.JS(四)-搭建简单的聊天室的代码
Nov 11 Javascript
JQuery实现table中tr上移下移的示例(超简单)
Jan 08 jQuery
微信小程序搭建自己的Https服务器
May 02 Javascript
js定义类的方法示例【ES5与ES6】
Jul 30 Javascript
vue设置动态请求地址的例子
Nov 01 Javascript
Vue SPA 初次进入加载动画实现代码
Nov 14 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
PHP5 面向对象程序设计
2008/02/13 PHP
ThinkPHP与PHPExcel冲突解决方法
2011/08/08 PHP
CodeIgniter读写分离实现方法详解
2016/01/20 PHP
基于thinkPHP实现的微信自定义分享功能示例
2016/09/23 PHP
基于php(Thinkphp)+jquery 实现ajax多选反选不选删除数据功能
2017/02/24 PHP
php session的应用详细介绍
2017/03/22 PHP
浅谈thinkphp5 instance 的简单实现
2017/07/30 PHP
PHP PDOStatement::getColumnMeta讲解
2019/02/01 PHP
JavaScript页面刷新与弹出窗口问题的解决方法
2010/03/02 Javascript
基于jquery的button默认enter事件(回车事件)。
2011/05/18 Javascript
jQuery遍历Table应用示例
2014/04/09 Javascript
JavaScript中的数学运算介绍
2014/12/29 Javascript
DOM基础教程之使用DOM设置文本框
2015/01/20 Javascript
JavaScript Split()方法
2015/12/18 Javascript
微信小程序中做用户登录与登录态维护的实现详解
2017/05/17 Javascript
教你如何将 Sublime 3 打造成 Python/Django IDE开发利器
2014/07/04 Python
Python读大数据txt
2016/03/28 Python
Python Web框架Tornado运行和部署
2020/10/19 Python
python实现黑客字幕雨效果
2018/06/21 Python
Python3非对称加密算法RSA实例详解
2018/12/06 Python
使用k8s部署Django项目的方法步骤
2019/01/14 Python
windows10下安装TensorFlow Object Detection API的步骤
2019/06/13 Python
OpenCV3.0+Python3.6实现特定颜色的物体追踪
2019/07/23 Python
FFrpc python客户端lib使用解析
2019/08/24 Python
python3 动态模块导入与全局变量使用实例
2019/12/22 Python
HTML5本地存储之Database Storage应用介绍
2013/01/06 HTML / CSS
总经理秘书岗位职责
2014/03/17 职场文书
建筑管理专业求职信
2014/07/28 职场文书
调研座谈会发言材料
2014/08/23 职场文书
幼儿园法制宣传日活动总结
2014/11/01 职场文书
2015年度培训工作总结范文
2015/04/02 职场文书
2015年终个人政治思想工作总结
2015/11/24 职场文书
拥有这5个特征人,“命”都不会太差
2019/08/16 职场文书
go结构体嵌套的切片数组操作
2021/04/28 Golang
【海涛七七解说】DCG第二周:DK VS 天禄
2022/04/01 DOTA
JS前端可扩展的低代码UI框架Sunmao使用详解
2022/07/23 Javascript