源码阅读:究竟怎样才算是读懂了?

市面上有很多源码分析的文章,就我看到的而言,基本的套路就是梳理流程,讲一讲每个模块的功能,整篇文章有一大半都是直接挂源码。我不禁怀疑,作者真的看懂了吗?为什么我看完后还是什么都不懂呢?

事实上一个经过无数次版本迭代的框架源码并不适合初学者直接阅读,因为里面有太多细节,太多噪点,太多枝枝蔓蔓。要想真正理解框架的核心逻辑,必须剥茧抽丝,还原出一个纯净的雏形。如同 jQuery 最早的版本只有六百多行,我相信 Vue 的核心功能也只需要几百行就能实现。所以,读懂源码的标志就是还原,码越薄,真相就越清晰。

如何还原雏形?

一开始我设想的还原过程就是先删后拆。什么报错信息、参数校验、非核心功能全部砍掉,八千行变成了五千行。然后再拆,按功能模块将一个 Vue.js 拆分成 util.js, observer.js, watcher.js …

理想状态下,我应该能够理解源码了吧,可做完解剖手术后,我发现里面的逻辑依然纷繁复杂,剪不断,理还乱,草蛇灰线,伏脉千里,即便换了一个更早期更简短的版本,仍然很快又陷入了永无止境的细节中。

最终我得出结论:与其根据源码还原雏形,不如参考源码自己从头实现一个雏形。

定义核心

Version:2.0.4

只考虑 runtime 版本,不考虑模板编译,不考虑服务端渲染。

核心功能:响应式的数据绑定、虚拟 DOM、diff 算法、patch 方法(用于更新真实 DOM)

如果你对上述基础概念完全不熟,建议先积累一些背景知识:关于响应式绑定参考这篇文章,关于 virtual dom 和 diff 算法参考这个视频。当然,这些并不是必须的。

目标

事实上,Vue-cli 生成的项目中,<template> 标签中的内容都会被编译为 render 函数,render 函数返回整棵虚拟节点树。我们最终要实现一个 Vue,来完成上面的示例。

当 new Vue() 的时候发生了什么?

我们的实现会参考源码的套路,但会大量的简化其中的细节。为了理解源码的结构,最好的突破口就是了解程序的起点 new Vue() 的背后究竟发生了什么。

简单梳理下源码的执行流:

=> 初始化生命周期

=> 初始化事件系统

=> 初始化state,依次处理 props、data、computed …

=> 开始渲染 _mount() => _render() 返回 vdom=> _update() => __patch__() 更新真实DOM

更详细的说明可以参考这篇文章,我们只会实现其中最核心的部分

第一步:将虚拟 DOM 树渲染到真实的 DOM

每一个 DOM 节点都是一个 node 对象,这个对象含有大量的属性与方法,虚拟 DOM 其实就是超轻量版的 node 对象。

我们要生成的 DOM 树看上去是这样的:

关于 data 参数的属性,请参考官方文档

随后我们会通过 createElm 方法和 createChildren 方法的相互调用,遍历整棵虚拟节点树,生成真实的 DOM 节点树,最后替换到挂载点。

完整代码

第二步:修改数据,执行 diff 算法,并将变化的部分 patch 到真实 DOM

diff 算法的逻辑比较复杂,可以单独摘出来研究,由于我们的目的是理解框架的核心逻辑,因此代码实现里只考虑了最简单的情形。

完整代码

第三步:对数据做响应式处理,当数据变化时,自动执行更新方法

data 中的每一个属性都会被处理为存取器属性,同时每一个属性都会在闭包中维护一个属于自己的 dep 对象,用于存放该属性的依赖项。当属性被赋予新的值时,就会触发 set 方法,并通知所有依赖项进行更新。

完整代码

Vue 渐进式的特点,使其上手极其容易,我相信,渐进式的展现框架逻辑的实现过程,也会使理解变得更容易。

读懂源码:一步一步实现一个 Vue的更多相关文章

  1. Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码

    在文章:Mybatis源码解析,一步一步从浅入深(一):创建准备工程,中我们为了解析mybatis源码创建了一个mybatis的简单工程(源码已上传github,链接在文章末尾),并实现了一个查询功能 ...

  2. Mybatis源码解析,一步一步从浅入深(一):创建准备工程

    Spring SpringMVC Mybatis(简称ssm)是一个很流行的java web框架,而Mybatis作为ORM 持久层框架,因其灵活简单,深受青睐.而且现在的招聘职位中都要求应试者熟悉M ...

  3. Mybatis源码解析,一步一步从浅入深(三):实例化xml配置解析器(XMLConfigBuilder)

    在上一篇文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码 ,中我们看到 代码:XMLConfigBuilder parser = new XMLConfigBuilder(read ...

  4. Mybatis源码解析,一步一步从浅入深(四):将configuration.xml的解析到Configuration对象实例

    在Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码中我们看到了XMLConfigBuilder(xml配置解析器)的实例化.而且这个实例化过程在文章:Mybatis源码解析,一步一步从浅 ...

  5. Mybatis源码解析,一步一步从浅入深(五):mapper节点的解析

    在上一篇文章Mybatis源码解析,一步一步从浅入深(四):将configuration.xml的解析到Configuration对象实例中我们谈到了properties,settings,envir ...

  6. Mybatis源码解析,一步一步从浅入深(六):映射代理类的获取

    在文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码中我们提到了两个问题: 1,为什么在以前的代码流程中从来没有addMapper,而这里却有getMapper? 2,UserDao ...

  7. Mybatis源码解析,一步一步从浅入深(七):执行查询

    一,前言 我们在文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码的最后一步说到执行查询的关键代码: result = sqlSession.selectOne(command.ge ...

  8. 读jQuery源码 - Deferred

    Deferred首次出现在jQuery 1.5中,在jQuery 1.8之后被改写,它的出现抹平了javascript中的大量回调产生的金字塔,提供了异步编程的能力,它主要服役于jQuery.ajax ...

  9. 读 Zepto 源码之集合元素查找

    这篇依然是跟 dom 相关的方法,侧重点是跟集合元素查找相关的方法. 读Zepto源码系列文章已经放到了github上,欢迎star: reading-zepto 源码版本 本文阅读的源码为 zept ...

随机推荐

  1. 改变 font Awesome、Ionic 图标属性

    可使用 -webkit-text-stroke属性. 例如: -webkit-text-stroke:1px red 使用color属性,可改变 图标颜色: 例如: color: red: 使用fon ...

  2. 如何线上部署node.js项目

    来源:http://blog.csdn.net/chenlinIT/article/details/73343793 前言 最近工作不是很忙,在空闲时间学习用node+express搭建自己的个人博客 ...

  3. .NET在VS2008中生成DLL并调用

    1.生成DLL 打开VS2008 - >新建->项目->类库->ClassLibrary1,在ClassLibrary1中会自动创建一个Class1类 class1中加入代码如 ...

  4. GCD Again

    GCD Again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  5. PHP(一)OOP基础

    [面向过程&面向对象] 1.面向过程:专注于解决一件事情的过程.最大的特点,是有一个个函数来实现功能需求 2.面向对象:专注于有哪一个对象来实现这个功能,最大的特点,时产生一个个具有属性和方法 ...

  6. escape、unescape、encodeURIComponent、decodeURLComponent

    项目中遇到的问题,当我设置一个标签的属性,这个属性值含有js内容,这样就会被执行产生安全问题 解决办法:,可以将后端给的内容先encodeURIComponent,获取的时候再decodeURICom ...

  7. JavaScript instanceof 运算符深入剖析【转载】

    http://www.ibm.com/developerworks/cn/web/1306_jiangjj_jsinstanceof/   instanceof 运算符简介 在 JavaScript ...

  8. 从零开始搭建Vue组件库 VV-UI

    前言: 前端组件化是当今热议的话题之一,也是我们在开发单页应用经常会碰到的一个问题,现在我们有了功能非常完善的Element-UI.各个大厂也相继宣布开源XXX-UI.但是也会存在一些问题,比如每个公 ...

  9. 高阶函数实现AOP

    AOP(面向切面程序)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,这些跟业务逻辑无关的功能通常包括日至统计.安全控制.异常处理等.把这些功能抽离出来之后,再通过"动态织入&quo ...

  10. tomcat不编译webapps下的war包的解决办法

    1.首先看看tomcat是否能正常启动,如果启动tomcat一闪而过那么就使用dos命令启动tomcat看看报什么错 如果是端口占用的错误.使用netstat -ano命令查看占用端口的程序 然后用任 ...