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 相关文章推荐
jQuery获取CSS样式中的颜色值的问题,不同浏览器格式不同的解决办法
May 13 Javascript
jQuery中校验时间格式的正则表达式小结
Sep 22 Javascript
JS 实现导航栏悬停效果(续2)
Sep 24 Javascript
ExtJS 刷新后如何默认选中刷新前最后一次选中的节点
Apr 03 Javascript
jQuery中delegate()方法用法实例
Jan 19 Javascript
深入学习JavaScript中的Rest参数和参数默认值
Jul 28 Javascript
Javascript实现图片加载从模糊到清晰显示的方法
Jun 21 Javascript
Angular简单验证功能示例
Dec 22 Javascript
mpvue中使用flyjs全局拦截的实现代码
Sep 13 Javascript
新年快乐! javascript实现超级炫酷的3D烟花特效
Jan 30 Javascript
vue中get请求如何传递数组参数的方法示例
Nov 08 Javascript
使用compose函数优化代码提高可读性及扩展性
Jun 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
在PWS上安装PHP4.0正式版
2006/10/09 PHP
PHP XML error parsing SOAP payload on line 1
2010/06/17 PHP
yii框架builder、update、delete使用方法
2014/04/30 PHP
js基于qrcode.js生成二维码的方法【附demo插件源码下载】
2016/12/28 PHP
PHP 二维关联数组根据其中一个字段排序(推荐)
2017/04/04 PHP
PHP新特性详解之命名空间、性状与生成器
2017/07/18 PHP
php curl简单采集图片生成base64编码(并附curl函数参数说明)
2019/02/15 PHP
jquery插件如何使用 jQuery操作Cookie插件使用介绍
2012/12/15 Javascript
javascript实现节点(div)名称编辑
2014/12/17 Javascript
jQuery构造函数init参数分析
2015/05/13 Javascript
快速学习jQuery插件 Cookie插件使用方法
2015/12/01 Javascript
全面解析jQuery $(document).ready()和JavaScript onload事件
2016/06/08 Javascript
js传值后台中文出现乱码的解决方法
2016/06/30 Javascript
JavaScript实现倒计时跳转页面功能【实用】
2016/12/13 Javascript
详解vue-Resource(与后端数据交互)
2017/01/16 Javascript
基于zepto.js实现手机相册功能
2017/07/11 Javascript
vee-validate vue 2.0自定义表单验证的实例
2018/08/28 Javascript
详解node字体压缩插件font-spider的用法
2018/09/28 Javascript
python使用threading获取线程函数返回值的实现方法
2017/11/15 Python
python装饰器-限制函数调用次数的方法(10s调用一次)
2018/04/21 Python
Python 读取图片文件为矩阵和保存矩阵为图片的方法
2018/04/27 Python
Python 确定多项式拟合/回归的阶数实例
2018/12/29 Python
wxPython实现绘图小例子
2019/11/19 Python
python ubplot使用方法解析
2020/01/10 Python
html5基础标签(html5视频标签 html5新标签用法)
2013/12/30 HTML / CSS
利用HTML5的新特点实现图片文件异步上传
2014/05/29 HTML / CSS
特步官方商城:Xtep
2017/03/21 全球购物
Trunki英国官网:儿童坐骑式行李箱
2017/05/30 全球购物
Marmot土拨鼠官网:美国专业户外运动品牌
2018/01/11 全球购物
西班牙在线宠物食品和配件商店:bitiba
2019/10/11 全球购物
学生安全教育材料
2014/02/14 职场文书
审计班子对照检查材料
2014/08/27 职场文书
办公室年度工作总结2015
2015/05/21 职场文书
领导视察通讯稿
2015/07/18 职场文书
导游词之江西赣州
2019/10/15 职场文书
如何解决php-fpm启动不了问题
2021/11/17 PHP