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 框架使用教程 AJAX篇
Oct 11 Javascript
Jquery Ajax学习实例5 向WebService发出请求,返回泛型集合数据的异步调用
Mar 17 Javascript
IE JS无提示关闭窗口不提示的方法
Apr 29 Javascript
jQuery弹出(alert)select选择的值
Apr 21 Javascript
jQuery常用知识点总结以及平时封装常用函数
Feb 23 Javascript
jQuery实现订单提交页发送短信功能前端处理方法
Jul 04 Javascript
jQuery中fadein与fadeout方法用法示例
Sep 16 Javascript
vue2.x 父组件监听子组件事件并传回信息的方法
Jul 17 Javascript
客户端(vue框架)与服务器(koa框架)通信及服务器跨域配置详解
Aug 26 Javascript
让网站自动生成章节目录索引的多个js代码
Jan 07 Javascript
vue双向数据绑定知识点总结
Apr 18 Javascript
基于React+Redux的SSR实现方法
Jul 03 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之COOKIE支持详解
2010/09/20 PHP
PHP游戏编程25个脚本代码
2011/02/08 PHP
php UBB 解析实现代码
2011/11/27 PHP
用PHP实现浏览器点击下载TXT文档的方法详解
2013/06/02 PHP
php实现httpclient类示例
2014/04/08 PHP
PHP房贷计算器实例代码,等额本息,等额本金
2017/04/01 PHP
PHP中通过getopt解析GNU C风格命令行选项
2019/11/18 PHP
云网广告中的代码,提示出错,大家找找
2006/11/21 Javascript
在html页面中包含共享页面的方法
2008/10/24 Javascript
javascript实现的在当前窗口中漂浮框的代码
2010/03/15 Javascript
jcarousellite.js 基于Jquery的图片无缝滚动插件
2010/12/30 Javascript
js判断滚动条是否已到页面最底部或顶部实例
2014/11/20 Javascript
JQuery控制radio选中和不选中方法总结
2015/04/15 Javascript
JS实现可展开折叠层的鼠标拖曳效果
2015/10/09 Javascript
jQuery实现返回顶部功能
2016/02/23 Javascript
基于jQuery和Bootstrap框架实现仿知乎前端动态列表效果
2016/11/09 Javascript
Vue制作Todo List网页
2017/04/26 Javascript
使用vue2实现带地区编号和名称的省市县三级联动效果
2018/11/05 Javascript
通过javascript实现段落的收缩与展开
2019/06/26 Javascript
json字符串对象转换代码实例
2019/09/28 Javascript
python实现给数组按片赋值的方法
2015/07/28 Python
在 Python 应用中使用 MongoDB的方法
2017/01/05 Python
使用Python的package机制如何简化utils包设计详解
2017/12/11 Python
Python实现识别图片内容的方法分析
2018/07/11 Python
pandas中read_csv、rolling、expanding用法详解
2020/04/21 Python
Python求区间正整数内所有素数之和的方法实例
2020/10/13 Python
家庭户外服装:Hawkshead
2017/11/02 全球购物
Mansur Gavriel官网:纽约市的一个设计品牌
2019/05/02 全球购物
优秀毕业生推荐信范文
2014/03/07 职场文书
保护母亲河倡议书
2014/04/14 职场文书
对照检查剖析材料
2014/09/30 职场文书
师德师风剖析材料
2014/09/30 职场文书
个人催款函范文
2015/06/24 职场文书
什么是执行力?9个故事告诉您:成功绝非偶然!
2019/07/05 职场文书
python编程简单几行代码实现视频转换Gif示例
2021/10/05 Python
mysql自增长id用完了该怎么办
2022/02/12 MySQL