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 面向对象编程基础 多态
Aug 21 Javascript
js实现连个数字相加而不是拼接的方法
Feb 23 Javascript
jQuery拖动div、移动div、弹出层实现原理及示例
Apr 08 Javascript
JavaScript动态创建link标签到head里的方法
Dec 22 Javascript
基于canvas的二维码邀请函生成插件
Feb 14 Javascript
JavaScript实现瀑布流图片效果
Jun 30 Javascript
React根据宽度自适应高度的示例代码
Oct 11 Javascript
vue-cli2.x项目优化之引入本地静态库文件的方法
Jun 19 Javascript
JS获取并处理php数组的方法实例分析
Sep 04 Javascript
详解微信小程序开发用户授权登陆
Apr 24 Javascript
Postman动态获取返回值过程详解
Jun 30 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 强制下载文件实现代码
2013/10/28 PHP
PHP中in_array函数使用的问题与解决办法
2016/09/11 PHP
PHP7实现和CryptoJS的AES加密方式互通示例【AES-128-ECB加密】
2019/06/08 PHP
如何使用jQuery Draggable和Droppable实现拖拽功能
2013/07/05 Javascript
原生js事件的添加和删除的封装
2014/07/01 Javascript
jquery mobile页面跳转后样式丢失js失效的解决方法
2014/09/06 Javascript
JavaScript使用键盘输入控制实现数字验证功能
2016/08/19 Javascript
妙用Bootstrap的 popover插件实现校验表单提示功能
2016/08/29 Javascript
关于List.ToArray()方法的效率测试
2016/09/30 Javascript
getElementById().innerHTML与getElementById().value的区别
2016/10/27 Javascript
JavaScript、C# URL编码、解码总结
2017/01/21 Javascript
详解vue的数据binding绑定原理
2017/04/12 Javascript
原生JS实现Ajax跨域请求flask响应内容
2017/10/24 Javascript
vue路由嵌套的SPA实现步骤
2017/11/06 Javascript
JavaScript中的相等操作符使用详解
2019/12/21 Javascript
vue组件系列之TagsInput详解
2020/05/14 Javascript
Python实现的监测服务器硬盘使用率脚本分享
2014/11/07 Python
使用rst2pdf实现将sphinx生成PDF
2016/06/07 Python
详解Python进程间通信之命名管道
2017/08/28 Python
python实现年会抽奖程序
2019/01/22 Python
对python_discover方法遍历所有执行的用例详解
2019/02/13 Python
python 环境搭建 及python-3.4.4的下载和安装过程
2019/07/20 Python
深入了解Python 变量作用域
2020/07/24 Python
python 实现压缩和解压缩的示例
2020/09/22 Python
Antonioli美国在线商店:时尚前卫奢华
2019/07/29 全球购物
汇智创新科技发展有限公司
2015/12/06 面试题
20年同学聚会感言
2014/02/03 职场文书
横幅标语大全
2014/06/17 职场文书
广告学专业求职信
2014/06/19 职场文书
工程技术负责人岗位职责
2015/04/13 职场文书
2015年党员个人工作总结
2015/05/13 职场文书
小学感恩主题班会
2015/08/12 职场文书
一文搞懂redux在react中的初步用法
2021/06/09 Javascript
Logback 使用TurboFilter实现日志级别等内容的动态修改操作
2021/08/30 Java/Android
十大冰系宝可梦排名,颜值最高的阿罗拉九尾,第三使用率第一
2022/03/18 日漫
PostgreSQL聚合函数介绍以及分组和排序
2022/04/12 PostgreSQL