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 处理URL实用技巧
Nov 23 Javascript
js中window.open()的所有参数详细解析
Jan 09 Javascript
Jquery组件easyUi实现手风琴(折叠面板)示例
Aug 23 Javascript
jQuery ajax 当async为false时解决同步操作失败的问题
Nov 18 Javascript
详解Python中logging日志模块在多进程环境下的使用
Dec 26 Javascript
Bootstrap导航中表单简单实现代码
Mar 06 Javascript
Vue.js 2.0 移动端拍照压缩图片上传预览功能
Mar 06 Javascript
在Vue项目中取消ESLint代码检测的步骤讲解
Jan 27 Javascript
利用原生JS实现data方法示例代码
May 28 Javascript
JS去除字符串最后的逗号实例分析【四种方法】
Jun 20 Javascript
JS数组属性去重并校验重复数据
Jan 10 Javascript
Vue 使用typescript如何优雅的调用swagger API
Sep 01 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 可阅读随机字符串代码
2010/05/26 PHP
php 字符串中的\n换行符无效、不能换行的解决方法
2014/04/02 PHP
将PHP程序中返回的JSON格式数据用gzip压缩输出的方法
2016/03/03 PHP
PHP7 foreach() 函数修改
2021/03/09 PHP
js调试工具console.log()方法查看js代码的执行情况
2014/08/08 Javascript
jquery中$each()方法的使用指南
2015/04/30 Javascript
jQuery与js实现颜色渐变的方法
2016/12/30 Javascript
web打印小结
2017/01/11 Javascript
Bootstrap 实现表格样式、表单布局的实例代码
2018/12/09 Javascript
小程序实现横向滑动日历效果
2019/10/21 Javascript
JavaScript前端开发时数值运算的小技巧
2020/07/28 Javascript
python控制台英汉汉英电子词典
2020/04/23 Python
Python正则捕获操作示例
2017/08/19 Python
python批量修改文件编码格式的方法
2018/05/31 Python
Django实战之用户认证(用户登录与注销)
2018/07/16 Python
python:接口间数据传递与调用方法
2018/12/17 Python
Python Pandas分组聚合的实现方法
2019/07/02 Python
matlab 计算灰度图像的一阶矩,二阶矩,三阶矩实例
2020/04/22 Python
Python 中Operator模块的使用
2021/01/30 Python
Pyecharts 中Geo函数常用参数的用法说明
2021/02/01 Python
大学生的网络创业计划书
2013/12/26 职场文书
婚礼主持词
2014/03/13 职场文书
个人合作协议书范本
2014/04/18 职场文书
开学典礼演讲稿
2014/05/23 职场文书
奥运会口号
2014/06/13 职场文书
垃圾分类的活动方案
2014/08/15 职场文书
群众路线教育实践活动学习笔记
2014/11/05 职场文书
公司门卫岗位职责
2015/04/13 职场文书
2015教师年度思想工作总结
2015/04/30 职场文书
信访维稳承诺书
2015/05/04 职场文书
民事撤诉申请书范本
2015/05/18 职场文书
军事理论课感想
2015/08/11 职场文书
python 调用js的四种方式
2021/04/11 Python
iPhone13将有八大升级
2021/04/15 数码科技
JavaScript实现简单图片切换
2021/04/29 Javascript
公历12个月名称的由来
2022/04/12 杂记