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类型转换方法及需要注意的问题小结(挺全面)
Nov 11 Javascript
RequireJS使用注意细节
May 15 Javascript
js 获取范围内的随机数实例代码
Aug 02 Javascript
jQuery动态增减行的实例代码解析(推荐)
Dec 05 Javascript
JavaScript的数据类型转换原则(干货)
Mar 15 Javascript
微信小程序自定义弹窗wcPop插件
Nov 19 Javascript
详解Vue源码之数据的代理访问
Dec 11 Javascript
js设置鼠标悬停改变背景色实现详解
Jun 26 Javascript
小程序如何自主实现拦截器的示例代码
Nov 04 Javascript
微信小程序点击滚动到指定位置的实现
May 22 Javascript
layui实现显示数据表格、搜索和修改功能示例
Jun 03 Javascript
微信小程序实现单个或多个倒计时功能
Nov 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
推荐几款用 Sublime Text 开发 Laravel 所用到的插件
2014/10/30 PHP
详解HTTP Cookie状态管理机制
2016/01/14 PHP
php的4种常用运行方式详解
2016/12/22 PHP
Laravel5.7框架安装与使用学习笔记图文详解
2019/04/02 PHP
PHP下载大文件失败并限制下载速度的实例代码
2019/05/10 PHP
jQuery动画出现连续触发、滞后反复执行的解决方法
2015/01/28 Javascript
深入理解JavaScript系列(50):Function模式(下篇)
2015/03/04 Javascript
jQuery 调用WebService 实例讲解
2016/06/28 Javascript
Vue 实用分页paging实例代码
2017/04/12 Javascript
BootStrap入门学习第一篇
2017/08/28 Javascript
vue实现多个元素或多个组件之间动画效果
2018/09/25 Javascript
微信小程序点击保存图片到本机功能
2019/12/13 Javascript
JavaScript 闭包的使用场景
2020/09/17 Javascript
nuxt 服务器渲染动态设置 title和seo关键字的操作
2020/11/05 Javascript
pygame学习笔记(3):运动速率、时间、事件、文字
2015/04/15 Python
Python中asyncore异步模块的用法及实现httpclient的实例
2016/06/28 Python
Python创建xml文件示例
2017/03/22 Python
Python实现嵌套列表及字典并按某一元素去重复功能示例
2017/11/30 Python
Django中cookie的基本使用方法示例
2018/02/03 Python
Python生成任意范围任意精度的随机数方法
2018/04/09 Python
Python3处理HTTP请求的实例
2018/05/10 Python
python把1变成01的步骤总结
2019/02/27 Python
Python使用Beautiful Soup爬取豆瓣音乐排行榜过程解析
2019/08/15 Python
解决pycharm debug时界面下方不出现step等按钮及变量值的问题
2020/06/09 Python
详解pyinstaller生成exe的闪退问题解决方案
2020/06/19 Python
美国专营婴幼儿用品的购物网站:buybuy BABY
2017/01/01 全球购物
伊芙丽官方旗舰店:中国淑女一线品牌
2017/12/01 全球购物
Glamest意大利:女性在线奢侈品零售店
2019/04/28 全球购物
《小蝌蚪找妈妈》教学反思
2014/02/21 职场文书
镇党政领导班子民主生活会思想汇报
2014/10/11 职场文书
2015年个人剖析材料范文
2014/12/29 职场文书
2015年小班保育员工作总结
2015/05/27 职场文书
2016年助残日旅游活动总结
2016/04/01 职场文书
python 自动化偷懒的四个实用操作
2021/04/11 Python
不要在HTML中滥用div
2021/05/08 HTML / CSS
CSS3中Animation实现简单的手指点击动画的示例
2021/07/15 HTML / CSS