古人有云:码农爱coding,则为之计深远。

众人问:何为之?

古人曰:底层、算法和架构。

众木然。

古人又曰:多看源码。

以下内容是我在学习 Vue-2.5.2 源码时的一个总结。

第一章 活捉Vue

旁白:既然是学习Vue源码,首先要搞清楚的是——Vue是什么东西?不然,天知道你在学什么玩意儿。所以,找到Vue对象就是本次学习的一条主线。本次任务的目标就是——活捉Vue

盖工欲善其事必先利其器。出发之前,应该要有一件趁手的武器,呐,这套祖传的vs code就送给你了。

第一回 不入虎穴焉得虎子

欲活捉Vue,最紧要的是找到它大概在哪里,然后根据线索顺藤摸瓜。那么,它到底在哪儿呢?

看着眼前的武器,你灵光一闪:git clone https://github.com/vuejs/vue.git。恭喜,Vue的老巢已经被你发现,令人激动的是,入口package.json也被你找到了。但紧闭的大门阻碍了你的步伐,于是你运用所学姿势,很快找到破解开关的关键scripts属性:

  "scripts": {
"dev": "rollup -w -c build/config.js --environment TARGET:web-full-dev",
...
"build": "node build/build.js",
...
}

P.S.package.json几乎是所有成熟库/框架必备的入口文件。

你命令终端执行npm run dev,看到rollup构建工具正在自动执行build文件夹下的config.js,并在环境中注入参数TARGET:web-full-dev,你紧跟线索,找到了build/config.js。看着两百多行代码,你微微一笑,心想,这等雕虫小技也敢造次?径直走向exports,看它导出了什么?

P.S.s 一般而言,导出对象在文件末尾。

// build/config.js

...
if (process.env.TARGET) {
module.exports = genConfig(process.env.TARGET); // (1)
} else {
exports.getBuild = genConfig
exports.getAllBuilds = () => Object.keys(builds).map(genConfig)
}

脑回路高速运行——因为执行npm run dev会植入环境变量TARGET:web-full-dev,上述代码会走(1),所以结合上下文,build/config.js实际导出的对象应该是这样的:

module.exports = {
input: resolve('web/entry-runtime-with-compiler.js'),
plugins: [
replace({__VERSION__: version}),
{
vue: resolve('src/platforms/web/entry-runtime-with-compiler'),
compiler: resolve('src/compiler'),
core: resolve('src/core'),
shared: resolve('src/shared'),
web: resolve('src/platforms/web'),
weex: resolve('src/platforms/weex'),
server: resolve('src/server'),
entries: resolve('src/entries'),
sfc: resolve('src/sfc'),
he: './entity-decoder'
}
],
output: {
file: resolve('dist/vue.js'),
format: 'umd',
banner: banner,
name: 'Vue'
}
}

直到这里,Vue的庐山真面目依然没有揭开。“果然是狡兔三窟!”你不屑道,然而你明白,已经越来越接近了...

此地唯一的入口就是input,小小的障眼法对你来讲不足挂齿,轻轻旋转机关,来到了src/platforms/web/entry-runtime-with-compiler.js。只一眼,你便看到了import Vue from './runtime/index'。"hehe,总算把你逮住了,老东西!"

你小心翼翼的进入./runtime/index,以为终于抓到了Vue。突然,一支利箭飞来import Vue from 'core/index',险险的避过后,一群彪形大汉又蜂拥而至:

./runtime/index.js

import Vue from 'core/index'
...
Vue.config.mustUseProp = mustUseProp
...
extend(Vue.options.directives, platformDirectives)
...
Vue.prototype.$mount = function (
el?: string | Element,
hydrating?: boolean
): Component {
el = el && inBrowser ? query(el) : undefined
return mountComponent(this, el, hydrating)
}
...

第二回 降服Vue

面对群魔乱舞,你开始受伤、流血,一波又一波的攻势逐渐让你体力不支,更糟糕的是,你,只是一个人。“就这样结束了么?”你喘着粗气暗问自己,恍惚间,往昔在脑海中一幕幕重现,从一无所知的小白到现在敢于挑战Vue,经历了重重历练,你不甘心,不甘心就这样失败。放手一搏吧,骚年!!!

体内的能量在积累,终于,你用尽全力使出了终极必杀技:404 Page Not Found。一时间,大汉们应声而倒,就连./runtime/index也开始坍塌,电光火石间,一股大力将你震晕击飞,醒来之时,已经到了另一个世界:src/core/index.js

这里就是Vue的核心了么?环顾四周,只见一间虚掩着房门的小屋./instance/index,推开门,Vue端坐在那里:

...
function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword')
} this._init(options)
}
...

终于找到了,此刻,你可以轻松的把它杀死,成为万众瞩目的英雄,于是乎你挥起手中利刃,直直的刺向Vue。当刃尖离Vue只有0.0001公分的时候,你看着眼前的Vue,原来,鼎鼎大名的Vue只是一个普普通通的构造函数,好像看到了最初的自己,刹那间,你顿住了。

Vue却开口到:“骚年,你终于来了!看你风流倜傥、天资聪颖,老夫这一身绝学总算是后继有人了。”说罢,万丈金光从Vue身上迸发而出,场面一度失控。待金光散去,Vue却不见了,只留下一本《Vue 编程房内考》...

《Vue 编程房内考》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. [Groovy] 学习Groovy的好网站(内容全面)

    https://www.tutorialspoint.com/groovy/index.htm

  2. Java数据结构和算法(一)线性结构

    Java数据结构和算法(一)线性结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 线性表 是一种逻辑结构,相同数据类型的 ...

  3. NAND FLASH和LCD电路图

  4. 2018.07.20 bzoj3211: 花神游历各国(线段树)

    传送门 维护区间开方,区间求和.这个是线段树常规操作. 显然一个数被开方若干次之后要么是1,要么是0,所以用线段树维护区间最大和区间和,如果区间最大不超过1就剪枝剪掉,不然就继续递归直到叶节点时停下进 ...

  5. asp.net Hessian 服务的注册

    Hessian服务端实现了IHttpHandle, 默认情况下是在Web.Config中的handles接点中注册,这样当有 很多实现时比较麻烦 这个时候可以实现IHttpHandleFactory注 ...

  6. java中File的delete和deleteOnExit区别(转)

    Java的File类中有两个delete方法:delete和deleteOnExit delete无需解释,为直接删除,deleteOnExit文档解释为:在虚拟机终止时,请求删除此抽象路径名表示的文 ...

  7. org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'testService' is defined

    org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'testService' is defi ...

  8. python-optparse模块给脚本增加参数选项

    import optparse parser = optparse.OptionParser('[-] Usage %prog '+ '-H <RHOST[s]> -l [-p -F ]' ...

  9. Apache Struts 2 Documentation Core Developers Guide

    http://struts.apache.org/docs/core-developers-guide.html

  10. html5获取经纬度

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...