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 相关文章推荐
srcElement表格样式
Sep 03 Javascript
清华大学出版的事半功倍系列 javascript全部源代码
May 04 Javascript
让table变成exls的示例代码
Mar 24 Javascript
javascript简单实现类似QQ头像弹出效果的方法
Aug 03 Javascript
使用jquery实现鼠标滑过弹出更多相关信息层附源码下载
Nov 23 Javascript
js实现延时加载Flash的方法
Nov 26 Javascript
jQuery mobile 移动web(4)
Dec 20 Javascript
node.js 核心http模块,起一个服务器,返回一个页面的实例
Sep 11 Javascript
微信小程序云开发如何实现数据库自动备份实现
Aug 16 Javascript
layui自定义验证,用ajax查询后台是否有重复数据,form.verify的例子
Sep 06 Javascript
JS数组降维的实现Array.prototype.concat.apply([], arr)
Apr 28 Javascript
vue实现几秒后跳转新页面代码
Sep 09 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
Docker搭建自己的PHP开发环境
2018/02/24 PHP
关于laravel 子查询 & join的使用
2019/10/16 PHP
前端开发部分总结[兼容性、DOM操作、跨域等](持续更新)
2010/03/04 Javascript
使用javascript创建快捷方式的简单实例
2013/08/09 Javascript
Jquery绑定事件(bind和live的区别介绍)
2013/08/23 Javascript
利用js读取动态网站从服务器端返回的数据
2014/02/10 Javascript
jquery attr方法获取input的checked属性问题
2014/05/26 Javascript
javascript定时器完整实例
2015/02/10 Javascript
基于jQuery Bar Indicator 插件实现进度条展示效果
2015/09/30 Javascript
AngularJs bootstrap详解及示例代码
2016/09/01 Javascript
nodejs读写json文件的简单方法(必看)
2017/03/09 NodeJs
React Native仿美团下拉菜单的实例代码
2017/08/08 Javascript
jQuery图片加载失败替换默认图片方法汇总
2017/11/29 jQuery
opencv 识别微信登录验证滑动块位置
2018/08/07 Javascript
jQuery的Ajax接收java返回数据方法
2018/08/11 jQuery
详解Vue-cli3 项目在安卓低版本系统和IE上白屏问题解决
2019/04/14 Javascript
JavaScript实现的滚动公告特效【基于jQuery】
2019/07/10 jQuery
简述vue-cli中chainWebpack的使用方法
2019/07/30 Javascript
解决nuxt页面中mounted、created、watch执行两遍的问题
2020/11/05 Javascript
在ironpython中利用装饰器执行SQL操作的例子
2015/05/02 Python
python中requests库session对象的妙用详解
2017/10/30 Python
Python编写通讯录通过数据库存储实现模糊查询功能
2019/07/18 Python
python实现图片插入文字
2019/11/26 Python
如何基于Python + requests实现发送HTTP请求
2020/01/13 Python
Python本地及虚拟解释器配置过程解析
2020/10/13 Python
DHC中国官方购物网站:日本通信销售No.1化妆品
2016/08/20 全球购物
Java多态性的定义以及类型
2014/09/16 面试题
管理站站长岗位职责
2013/11/27 职场文书
学年末自我鉴定
2014/01/21 职场文书
淘宝中秋节活动方案
2014/01/31 职场文书
销售内勤岗位职责
2014/04/15 职场文书
运动会广播稿200字
2014/10/18 职场文书
少先队大队委竞选口号
2015/12/25 职场文书
幼儿园科学课教学反思
2016/03/03 职场文书
2019年“红色之旅”心得体会1000字(3篇)
2019/09/27 职场文书
python多线程方法详解
2022/01/18 Python