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 相关文章推荐
JavaScript 垃圾回收机制分析
Oct 10 Javascript
Jquery仿IGoogle实现可拖动窗口示例代码
Aug 22 Javascript
浅谈javascript中this在事件中的应用
Feb 15 Javascript
Js与Jq获取浏览器和对象值的方法
Mar 18 Javascript
设计模式中的组合模式在JavaScript程序构建中的使用
May 18 Javascript
D3.js实现柱状图的方法详解
Sep 21 Javascript
微信小程序 开发工具快捷键整理
Oct 31 Javascript
动手写一个angular版本的Message组件的方法
Dec 16 Javascript
jQuery实现滚动到底部时自动加载更多的方法示例
Feb 18 jQuery
vue列表数据发生变化指令没有更新问题及解决方法
Jan 16 Javascript
Json实现传值到后台代码实例
Jun 30 Javascript
ES11新增的这9个新特性,你都掌握了吗
Oct 15 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
服务器端解压缩zip的脚本
2006/12/22 PHP
PHP 远程文件管理,可以给表格排序,遍历目录,时间排序
2009/08/07 PHP
php socket客户端及服务器端应用实例
2014/07/04 PHP
PHP清除缓存的几种方法总结
2017/09/12 PHP
jQuery对象[0]是什么含义?
2010/07/31 Javascript
JS弹出对话框返回值代码(asp.net后台)
2010/12/28 Javascript
js获取日期:昨天今天和明天、后天
2014/06/11 Javascript
基于jQuery+Cookie实现的防止刷新的在线考试倒计时
2015/06/19 Javascript
jquery datatable服务端分页
2016/08/31 Javascript
JavaScript制作颜色反转小游戏
2016/09/25 Javascript
关于RequireJS的简单介绍即使用方法
2016/10/20 Javascript
Ionic+AngularJS实现登录和注册带验证功能
2017/02/09 Javascript
nodejs搭建本地http服务器教程
2017/03/13 NodeJs
Vuex之理解Mutations的用法实例
2017/04/19 Javascript
详解Node.js 命令行程序开发教程
2017/06/07 Javascript
JavaScript设计模式之策略模式详解
2017/06/09 Javascript
vue如何通过id从列表页跳转到对应的详情页
2018/05/01 Javascript
微信小程序之多列表的显示和隐藏功能【附源码】
2018/08/06 Javascript
基于Vue 2.0 监听文本框内容变化及ref的使用说明介绍
2018/08/24 Javascript
JavaScript遍历数组和对象的元素简单操作示例
2019/07/09 Javascript
layui关闭层级、简单监听的实例
2019/09/06 Javascript
node.js通过url读取文件
2020/10/16 Javascript
Python的Flask开发框架简单上手笔记
2015/11/16 Python
Python利用ElementTree模块处理XML的方法详解
2017/08/31 Python
Windows 7下Python Web环境搭建图文教程
2018/03/20 Python
Python使用struct处理二进制(pack和unpack用法)
2020/11/12 Python
详解HTML5布局和HTML5标签
2020/10/26 HTML / CSS
英国的潮牌鞋履服饰商店:size?
2019/03/26 全球购物
英语专业学生个人求职信范文
2014/01/06 职场文书
敬老文明号事迹材料
2014/01/16 职场文书
车队司机个人自我鉴定
2014/04/17 职场文书
2015年销售工作总结范文
2015/03/30 职场文书
趣味运动会口号
2015/12/24 职场文书
敬业奉献模范事迹材料(2016精选版)
2016/02/26 职场文书
干货干货!2019最新优秀创业计划书
2019/03/21 职场文书
使用Djongo模块在Django中使用MongoDB数据库
2021/06/20 Python