Browse Source

chore: fix link address

HcySunYang 7 years ago
parent
commit
387a5c657d

+ 1 - 1
docs/appendix/core-util.md

@@ -441,7 +441,7 @@ export function def (obj: Object, key: string, val: any, enumerable?: boolean) {
 
 ## options.js 文件代码说明
 
-*该文件的讲解集中在 [4Vue选项的规范化](/note/4Vue选项的规范化) 以及 [5Vue选项的合并](/note/5Vue选项的合并) 这两个小节中*。
+*该文件的讲解集中在 [Vue选项的规范化](../art/4vue-normalize.md) 以及 [Vue选项的合并](../art/5vue-merge.md) 这两个小节中*。
 
 ## perf.js 文件代码说明
 

+ 2 - 2
docs/appendix/web-util.md

@@ -209,7 +209,7 @@ export const isHTMLTag = makeMap(
 
 * 源码分析
 
-`isHTMLTag` 是一个使用 `makeMap` 生成的函数,可以在 [shared/util.js 文件工具方法全解](/note/附录/shared-util) 中查看 `makeMap` 方法。
+`isHTMLTag` 是一个使用 `makeMap` 生成的函数,可以在 [shared/util.js 文件工具方法全解](../shared-util) 中查看 `makeMap` 方法。
 
 ### isSVG
 
@@ -230,7 +230,7 @@ export const isSVG = makeMap(
 
 * 源码分析
 
-`isSVG` 是一个使用 `makeMap` 生成的函数,可以在 [shared/util.js 文件工具方法全解](/note/附录/shared-util) 中查看 `makeMap` 方法。
+`isSVG` 是一个使用 `makeMap` 生成的函数,可以在 [shared/util.js 文件工具方法全解](../shared-util) 中查看 `makeMap` 方法。
 
 ### isPreTag
 

+ 6 - 6
docs/art/3vue-example.md

@@ -1,6 +1,6 @@
 # 以一个例子为线索
 
-在上一节 [Vue构造函数](/note/Vue构造函数) 中,我们整理了完整的 `Vue` 构造函数,包括原型的设计和全局API的设计,并且我们专门为其整理了附录,目的是便于查看相应的方法和属性是在哪里被添加的,同时也让我们对 `Vue` 构造函数有一个大局观的认识。
+在上一节 [Vue构造函数](./2vue-constructor.md) 中,我们整理了完整的 `Vue` 构造函数,包括原型的设计和全局API的设计,并且我们专门为其整理了附录,目的是便于查看相应的方法和属性是在哪里被添加的,同时也让我们对 `Vue` 构造函数有一个大局观的认识。
 
 从这一章节开始,我们将逐渐走进 `Vue`,我们采用一种由浅入深,由宽到窄的思路,一开始我们会从宏观来看 `Vue` 是如何设计的,然后在一点点“追究”进去,进而逐步搞清楚 `Vue` 为什么这么设计。
 
@@ -45,7 +45,7 @@ vm.test = 2
 
 看上去这个例子很简单(好吧,确实很简单),但其实这么简单的例子足够我们搞清楚 `Vue` 的思路了,当你明白 `Vue` 的思路之后,再去搞清楚其他的问题将会变得异常轻松。接下来我们就看看上面的例子中,到底发生了什么。
 
-首先我们要找到当我们调用 `Vue` 构造函数的时候,第一句执行的代码是什么,所以我们要找到 `Vue` 的构造函数,还记的 `Vue` 的构造函数定义在哪里吗?不记得没关系,只要查阅一下 [附录/Vue构造函数整理-原型](/note/附录/Vue构造函数整理-原型) 就ok了,`Vue` 的构造函数定义在 `core/instance/index.js` 文件中,我们找到它:
+首先我们要找到当我们调用 `Vue` 构造函数的时候,第一句执行的代码是什么,所以我们要找到 `Vue` 的构造函数,还记的 `Vue` 的构造函数定义在哪里吗?不记得没关系,只要查阅一下 [附录/Vue构造函数整理-原型](../appendix/vue-prototype.md) 就ok了,`Vue` 的构造函数定义在 `core/instance/index.js` 文件中,我们找到它:
 
 ```js
 function Vue (options) {
@@ -69,7 +69,7 @@ options = {
 }
 ```
 
-既然如此,我们就找到 `_init` 方法,查阅 [附录/Vue构造函数整理-原型](/note/附录/Vue构造函数整理-原型) 可知,`_init` 方法在 `src/core/instance/init.js` 文件被添加到 `Vue` 的原型上,下面我们就看看 `_init` 做了什么。
+既然如此,我们就找到 `_init` 方法,查阅 [附录/Vue构造函数整理-原型](../appendix/vue-prototype.md) 可知,`_init` 方法在 `src/core/instance/init.js` 文件被添加到 `Vue` 的原型上,下面我们就看看 `_init` 做了什么。
 
 `_init` 方法的一开始,是这两句代码:
 
@@ -81,7 +81,7 @@ vm._uid = uid++
 
 首先声明了变量 `vm`,其值为 `this` 也就是当前这个 `Vue` 实例啦,然后在实例上添加了一个唯一标示:`_uid`,其值为 `uid`,`uid` 这个变量定义在 `initMixin` 方法的上面,初始化为 `0`,可以看到每次实例化一个 `Vue` 实例之后,`uid` 的值都会 `++`。
 
-所以实际 `_uid` 就是一个 `Vue` 实例的实例属性,在之后的分析中,我们将会在很多地方遇到很多的实例属性被逐渐添加到 `Vue` 实例上,所以我们同样整理了一个附录:[附录/Vue实例的设计](/note/附录/Vue实例的设计) 来对 `Vue` 实例进行整理,就像我们对 `Vue` 构造函数的整理一样,大家可以在这里查阅。
+所以实际 `_uid` 就是一个 `Vue` 实例的实例属性,在之后的分析中,我们将会在很多地方遇到很多的实例属性被逐渐添加到 `Vue` 实例上,所以我们同样整理了一个附录:[附录/Vue实例的设计](../appendix/vue-ins.md) 来对 `Vue` 实例进行整理,就像我们对 `Vue` 构造函数的整理一样,大家可以在这里查阅。
 
 回过头来继续看代码,接下来是这样一段:
 
@@ -121,9 +121,9 @@ if (process.env.NODE_ENV !== 'production' && config.performance && mark)
 * 3、渲染(`render`),其实就是渲染函数的性能,或者说渲染函数执行且生成虚拟DOM(`vnode`)的性能
 * 4、打补丁(`patch`),将虚拟DOM渲染为真实DOM的性能
 
-其中第*组件初始化*的性能追踪就是我们在 `_init` 方法中看到的那样去实现的,其实现的方式就是在初始化的代码的开头和结尾分别使用 `mark` 函数打上两个标记,然后通过 `measure` 函数对这两个标记点进行性能计算。`mark` 和 `measure` 这两个函数可以在附录 [core/util 目录下的工具方法全解](/note/附录/core-util) 中查看其作用和实现方式。
+其中第*组件初始化*的性能追踪就是我们在 `_init` 方法中看到的那样去实现的,其实现的方式就是在初始化的代码的开头和结尾分别使用 `mark` 函数打上两个标记,然后通过 `measure` 函数对这两个标记点进行性能计算。`mark` 和 `measure` 这两个函数可以在附录 [core/util 目录下的工具方法全解](../appendix/core-util.md) 中查看其作用和实现方式。
 
-此时大家应该打开 `core/util/perf.js` 文件,然后对照着附录 [core/util 目录下的工具方法全解](/note/附录/core-util) 搞清楚 `mark` 和 `measure` 这两个方法了,通过 `core/util/perf.js` 文件的代码我们可知,只有在非生产环境,且浏览器必须支持 `window.performance` API的情况下才会导出有用的 `mark` 和 `measure` 函数,也就是说,如果你的浏览器不支持 `window.performance` 那么在 `core/instance/init.js` 文件中导入的 `mark` 和 `measure` 就都是 `undefined`,也就不会执行 `if` 语句里面的内容。
+此时大家应该打开 `core/util/perf.js` 文件,然后对照着附录 [core/util 目录下的工具方法全解](../appendix/core-util.md) 搞清楚 `mark` 和 `measure` 这两个方法了,通过 `core/util/perf.js` 文件的代码我们可知,只有在非生产环境,且浏览器必须支持 `window.performance` API的情况下才会导出有用的 `mark` 和 `measure` 函数,也就是说,如果你的浏览器不支持 `window.performance` 那么在 `core/instance/init.js` 文件中导入的 `mark` 和 `measure` 就都是 `undefined`,也就不会执行 `if` 语句里面的内容。
 
 那么大家可能比较关心如何查看追踪到的性能数据,很简单,如下图,打开 `chrome` 开发者工具即可查看:
 

+ 5 - 5
docs/art/4vue-normalize.md

@@ -104,7 +104,7 @@ export function resolveConstructorOptions (Ctor: Class<Component>) {
 }
 ```
 
-所以,根据我们的例子,此时的 `mergeOptions` 函数的第一个参数就是 `Vue.options`,那么大家还记得 `Vue.options` 长成什么样子吗?不记得也没关系,这就得益于我们整理的 [附录/Vue构造函数整理-全局API](/note/附录/Vue构造函数整理-全局API) 了,通过查看我们可知 `Vue.options` 如下:
+所以,根据我们的例子,此时的 `mergeOptions` 函数的第一个参数就是 `Vue.options`,那么大家还记得 `Vue.options` 长成什么样子吗?不记得也没关系,这就得益于我们整理的 [附录/Vue构造函数整理-全局API](../appendix/vue-global-api.md) 了,通过查看我们可知 `Vue.options` 如下:
 
 ```js
 Vue.options = {
@@ -235,7 +235,7 @@ export function validateComponentName (name: string) {
 
 对于第一条规则,`Vue` 限定组件的名字由普通的字符和中横线(-)组成,且必须以字母开头。
 
-对于第二条规则,首先将 `options.components` 对象的 `key` 小写化作为组件的名字,然后以组件的名字为参数分别调用两个方法:`isBuiltInTag` 和 `config.isReservedTag`,其中 `isBuiltInTag` 方法的作用是用来检测你所注册的组件是否是内置的标签,这个方法可以在 [shared/util.js 文件工具方法全解](/note/附录/shared-util) 中查看其实现,于是我们可知:`slot` 和 `component` 这个两个名字被 `Vue` 作为内置标签而存在的,你是不能够使用的,比如这样:
+对于第二条规则,首先将 `options.components` 对象的 `key` 小写化作为组件的名字,然后以组件的名字为参数分别调用两个方法:`isBuiltInTag` 和 `config.isReservedTag`,其中 `isBuiltInTag` 方法的作用是用来检测你所注册的组件是否是内置的标签,这个方法可以在 [shared/util.js 文件工具方法全解](../appendix/shared-util.md) 中查看其实现,于是我们可知:`slot` 和 `component` 这个两个名字被 `Vue` 作为内置标签而存在的,你是不能够使用的,比如这样:
 
 ```js
 new Vue({
@@ -266,7 +266,7 @@ Vue.config.isUnknownElement = isUnknownElement
 Vue.config.isReservedTag = isReservedTag
 ```
 
-就是在给 `config.isReservedTag` 赋值,其值为来自于 `platforms/web/util/element.js` 文件的 `isReservedTag` 函数,大家可以在附录 [platforms/web/util 目录下的工具方法全解](/note/附录/web-util) 中查看该方法的作用及实现,可知在 `Vue` 中 `html` 标签和部分 `SVG` 标签被认为是保留的。所以这段代码是在保证选项被合并前的合理合法。最后大家注意一点,这些工作是在非生产环境下做的,所以在非生产环境下开发者就能够发现并修正这些问题,所以在生产环境下就不需要再重复做一次校验检测了。
+就是在给 `config.isReservedTag` 赋值,其值为来自于 `platforms/web/util/element.js` 文件的 `isReservedTag` 函数,大家可以在附录 [platforms/web/util 目录下的工具方法全解](../appendix/web-util.md) 中查看该方法的作用及实现,可知在 `Vue` 中 `html` 标签和部分 `SVG` 标签被认为是保留的。所以这段代码是在保证选项被合并前的合理合法。最后大家注意一点,这些工作是在非生产环境下做的,所以在非生产环境下开发者就能够发现并修正这些问题,所以在生产环境下就不需要再重复做一次校验检测了。
 
 另外要说一点,我们的例子中并没有使用 `components` 选项,但是这里还是给大家顺便介绍了一下。如果按照我们的例子的话,`mergeOptions` 函数中的很多代码都不会执行,但是为了保证让大家理解整个选项合并所做的事情,这里都会有所介绍。
 
@@ -457,7 +457,7 @@ name = camelize(val)
 res[name] = { type: null }
 ```
 
-首先将数组的元素传递给 `camelize` 函数,这个函数来自于 `shared/util.js` 文件,可以在附录 [shared/util.js 文件工具方法全解](/note/附录/shared-util) 中查看详细解析,这个函数的作用是将中横线转驼峰。
+首先将数组的元素传递给 `camelize` 函数,这个函数来自于 `shared/util.js` 文件,可以在附录 [shared/util.js 文件工具方法全解](../appendix/shared-util.md) 中查看详细解析,这个函数的作用是将中横线转驼峰。
 
 然后在 `res` 对象上添加了与转驼峰后的 `props` 同名的属性,其值为 `{ type: null }`,这就是实现了对字符串数组的规范化,将其规范为对象的写法,只不过 `type` 的值为 `null`。
 
@@ -479,7 +479,7 @@ if (Array.isArray(props)) {
 }
 ```
 
-首先使用 `isPlainObject` 函数判断 `props` 是否是一个纯的对象,其中 `isPlainObject` 函数来自于 `shared/util.js` 文件,可以在附录 [shared/util.js 文件工具方法全解](/note/附录/shared-util) 中查看详细解析。
+首先使用 `isPlainObject` 函数判断 `props` 是否是一个纯的对象,其中 `isPlainObject` 函数来自于 `shared/util.js` 文件,可以在附录 [shared/util.js 文件工具方法全解](../appendix/shared-util.md) 中查看详细解析。
 
 如果是一个纯对象,也是需要规范化的,我们知道即使是纯对象也是有两种写法的如下:
 

+ 4 - 4
docs/art/5vue-merge.md

@@ -66,7 +66,7 @@ for (key in child) {
 if (!hasOwn(parent, key))
 ```
 
-其中 `hasOwn` 函数来自于 `shared/util.js` 文件,可以在 [shared/util.js 文件工具方法全解](/note/附录/shared-util) 中查看其详解,其作用是用来判断一个属性是否是对象自身的属性(不包括原型上的)。所以这个判断语句的意思是,如果 `child` 对象的键也在 `parent` 上出现,那么就不要再调用 `mergeField` 的了,因为在上一个 `for in` 循环中已经调用过了,这就避免了重复调用。
+其中 `hasOwn` 函数来自于 `shared/util.js` 文件,可以在 [shared/util.js 文件工具方法全解](../appendix/shared-util.md) 中查看其详解,其作用是用来判断一个属性是否是对象自身的属性(不包括原型上的)。所以这个判断语句的意思是,如果 `child` 对象的键也在 `parent` 上出现,那么就不要再调用 `mergeField` 的了,因为在上一个 `for in` 循环中已经调用过了,这就避免了重复调用。
 
 总之这两个 `for in` 循环的目的就是使用在 `parent` 或者 `child` 对象中出现的 `key(即选项的名字)` 作为参数调用 `mergeField` 函数,真正合并的操作实际在 `mergeField` 函数中。
 
@@ -1176,7 +1176,7 @@ if (parentVal === nativeWatch) parentVal = undefined
 if (childVal === nativeWatch) childVal = undefined
 ```
 
-其中 `nativeWatch` 来自于 `core/util/env.js` 文件,大家可以在 [core/util 目录下的工具方法全解](/note/附录/core-util) 中查看其作用。在 `Firefox` 浏览器中 `Object.prototype` 拥有原生的 `watch` 函数,所以即便一个普通的对象你没有定义 `watch` 属性,但是依然可以通过原型链访问到原生的 `watch` 属性,这就会给 `Vue` 在处理选项的时候造成迷惑,因为 `Vue` 也提供了一个叫做 `watch` 的选项,即使你的组件选项中没有写 `watch` 选项,但是 `Vue` 通过原型访问到了原生的 `watch`。这不是我们想要的,所以上面两句代码的目的是一个变通方案,当发现组件选项是浏览器原生的 `watch` 时,那说明用户并没有提供 `Vue` 的 `watch` 选项,直接重置为 `undefined`。
+其中 `nativeWatch` 来自于 `core/util/env.js` 文件,大家可以在 [core/util 目录下的工具方法全解](../appendix/core-util.md) 中查看其作用。在 `Firefox` 浏览器中 `Object.prototype` 拥有原生的 `watch` 函数,所以即便一个普通的对象你没有定义 `watch` 属性,但是依然可以通过原型链访问到原生的 `watch` 属性,这就会给 `Vue` 在处理选项的时候造成迷惑,因为 `Vue` 也提供了一个叫做 `watch` 的选项,即使你的组件选项中没有写 `watch` 选项,但是 `Vue` 通过原型访问到了原生的 `watch`。这不是我们想要的,所以上面两句代码的目的是一个变通方案,当发现组件选项是浏览器原生的 `watch` 时,那说明用户并没有提供 `Vue` 的 `watch` 选项,直接重置为 `undefined`。
 
 然后是这句代码:
 
@@ -1377,7 +1377,7 @@ strats.computed = function (
 
 这段代码的作用是在 `strats` 策略对象上添加 `props`、`methods`、`inject` 以及 `computed` 策略函数,顾名思义这些策略函数分别用来合并处理同名选项的,并且所使用的策略相同。
 
-对于 `props`、`methods`、`inject` 以及 `computed` 这四个选项有一个共同点,就是它们的结构都是纯对象,虽然我们在书写 `props` 或者 `inject` 选项的时候可能是一个数组,但是在 [Vue的思路之选项的规范化](/note/Vue的思路之选项的规范化) 一节中我们知道,`Vue` 内部都将其规范化为了一个对象。所以我们看看 `Vue` 是如何处理这些对象散列的。
+对于 `props`、`methods`、`inject` 以及 `computed` 这四个选项有一个共同点,就是它们的结构都是纯对象,虽然我们在书写 `props` 或者 `inject` 选项的时候可能是一个数组,但是在 [Vue的思路之选项的规范化](./4vue-normalize.md) 一节中我们知道,`Vue` 内部都将其规范化为了一个对象。所以我们看看 `Vue` 是如何处理这些对象散列的。
 
 策略函数内容如下:
 
@@ -1430,7 +1430,7 @@ strats.provide = mergeDataOrFn
 
 ## 再看 mixins 和 extends
 
-在 [4Vue选项的规范化](/note/4Vue选项的规范化) 一节中,我们讲到了 `mergeOptions` 函数中的如下这段代码:
+在 [Vue选项的规范化](./4vue-normalize.md) 一节中,我们讲到了 `mergeOptions` 函数中的如下这段代码:
 
 ```js
 const extendsFrom = child.extends

+ 6 - 6
docs/art/6vue-init-start.md

@@ -2,7 +2,7 @@
 
 ## 用于初始化的最终选项 $options
 
-在 [Vue的思路之以一个例子为线索](/note/Vue的思路之以一个例子为线索) 一节中,我们写了一个很简单的例子,这个例子如下:
+在 [Vue的思路之以一个例子为线索](./vue-example.md) 一节中,我们写了一个很简单的例子,这个例子如下:
 
 ```js
 var vm = new Vue({
@@ -23,7 +23,7 @@ vm.$options = mergeOptions(
 )
 ```
 
-正是因为上面的代码,使得我们花了大篇章来讲解其内部实现和运作,也就是 [Vue的思路之选项的规范化](/note/Vue的思路之选项的规范化) 和 [Vue的思路之选项的合并](/note/Vue的思路之选项的合并) 这两节所介绍的内容。现在我们已经知道了 `mergeOptions` 函数是如何对父子选项进行合并处理的,也知道了它的作用。
+正是因为上面的代码,使得我们花了大篇章来讲解其内部实现和运作,也就是 [Vue的思路之选项的规范化](./vue-normalize.md) 和 [Vue的思路之选项的合并](./vue-normalize.md) 这两节所介绍的内容。现在我们已经知道了 `mergeOptions` 函数是如何对父子选项进行合并处理的,也知道了它的作用。
 
 我们打开 `core/util/options.js` 文件,找到 `mergeOptions` 函数,看其最后一句代码:
 
@@ -869,7 +869,7 @@ vm.$slots
 vm.$scopedSlots
 ```
 
-我们把这些属性都整理到 [Vue实例的设计](/note/附录/Vue实例的设计) 中。
+我们把这些属性都整理到 [Vue实例的设计](../appendix/vue-ins.md) 中。
 
 再往下是这段代码:
 
@@ -923,7 +923,7 @@ if (process.env.NODE_ENV !== 'production') {
 }
 ```
 
-上面的代码主要作用就是在 `Vue` 实例对象上定义两个属性:`vm.$attrs` 以及 `vm.$listeners`。这两个属性在 `Vue` 的文档中是有说明的,由于这两个属性的存在使得在 `Vue` 中创建高阶组件变得更容易,感兴趣的同学可以阅读 [Vue 中创建高阶组件](/note/扩展阅读/Vue中创建高阶组件)。
+上面的代码主要作用就是在 `Vue` 实例对象上定义两个属性:`vm.$attrs` 以及 `vm.$listeners`。这两个属性在 `Vue` 的文档中是有说明的,由于这两个属性的存在使得在 `Vue` 中创建高阶组件变得更容易,感兴趣的同学可以阅读 [Vue 中创建高阶组件](../more/vue-hoc.md)。
 
 我们注意到,在为实例对象定义 `$attrs` 属性和 `$listeners` 属性时,使用了 `defineReactive` 函数,该函数的作用就是为一个对象定义响应式的属性,所以 `$attrs` 和 `$listeners` 这两个属性是响应式的,至于 `defineReactive` 函数的讲解,我们会放到 `Vue` 的响应系统中讲解。
 
@@ -1025,7 +1025,7 @@ const handlers = vm.$options[hook]
 const handlers = vm.$options.created
 ```
 
-在 [5Vue选项的合并](/note/5Vue选项的合并) 一节中我们讲过,对于生命周期钩子选项最终会被合并处理成一个数组,所以得到的 `handlers` 就是对应生命周期钩子的数组。接着执行的是这段代码:
+在 [Vue选项的合并](./vue-merge.md) 一节中我们讲过,对于生命周期钩子选项最终会被合并处理成一个数组,所以得到的 `handlers` 就是对应生命周期钩子的数组。接着执行的是这段代码:
 
 ```js
 if (handlers) {
@@ -1045,7 +1045,7 @@ if (handlers) {
 handlers[i].call(vm)
 ```
 
-为了保证生命周期钩子函数内可以通过 `this` 访问实例对象,所以使用 `.call(vm)` 执行这些函数。另外由于生命周期钩子函数的函数体是开发者编写的,为了捕获可能出现的错误,使用 `try...catch` 语句块,并在 `catch` 语句块内使用 `handleError` 处理错误信息。其中 `handleError` 来自于 `core/util/error.js` 文件,大家可以在附录 [core/util 目录下的工具方法全解](/note/附录/core-util) 中查看关于 `handleError` 的讲解。
+为了保证生命周期钩子函数内可以通过 `this` 访问实例对象,所以使用 `.call(vm)` 执行这些函数。另外由于生命周期钩子函数的函数体是开发者编写的,为了捕获可能出现的错误,使用 `try...catch` 语句块,并在 `catch` 语句块内使用 `handleError` 处理错误信息。其中 `handleError` 来自于 `core/util/error.js` 文件,大家可以在附录 [core/util 目录下的工具方法全解](../appendix/core-util.md) 中查看关于 `handleError` 的讲解。
 
 所以我们发现,对于生命周期钩子的调用,其实就是通过 `this.$options` 访问处理过的对应的生命周期钩子函数数组,遍历并执行它们。原理还是很简单的。
 

+ 3 - 3
docs/art/7vue-reactive.md

@@ -35,7 +35,7 @@ data = vm._data = typeof data === 'function'
   : data || {}
 ```
 
-首先定义 `data` 变量,它是 `vm.$options.data` 的引用。在 [5Vue选项的合并](/note/5Vue选项的合并) 一节中我们知道 `vm.$options.data` 其实最终被处理成了一个函数,且该函数的执行结果才是真正的数据。在上面的代码中我们发现其中依然存在一个使用 `typeof` 语句判断 `data` 数据类型的操作,实际上这个判断是完全没有必要的,原因是当 `data` 选项存在的时候,那么经过 `mergeOptions` 函数处理后,`data` 选项必然是一个函数,只有当 `data` 选项不存在的时候它的值是 `undefined`,而在 `initState` 函数中如果 `opts.data` 不存在则根本不会执行 `initData` 函数,所以既然执行了 `initData` 函数那么 `vm.$options.data` 必然是一个函数,所以这里的判断是没有必要的。可以直接写成:
+首先定义 `data` 变量,它是 `vm.$options.data` 的引用。在 [Vue选项的合并](./5vue-merge.md) 一节中我们知道 `vm.$options.data` 其实最终被处理成了一个函数,且该函数的执行结果才是真正的数据。在上面的代码中我们发现其中依然存在一个使用 `typeof` 语句判断 `data` 数据类型的操作,实际上这个判断是完全没有必要的,原因是当 `data` 选项存在的时候,那么经过 `mergeOptions` 函数处理后,`data` 选项必然是一个函数,只有当 `data` 选项不存在的时候它的值是 `undefined`,而在 `initState` 函数中如果 `opts.data` 不存在则根本不会执行 `initData` 函数,所以既然执行了 `initData` 函数那么 `vm.$options.data` 必然是一个函数,所以这里的判断是没有必要的。可以直接写成:
 
 ```js
 data = vm._data = getData(data, vm)
@@ -175,7 +175,7 @@ if (props && hasOwn(props, key)) {
 
 同样的 `Vue` 实例对象除了代理访问 `data` 数据和 `methods` 中的方法之外,还代理访问了 `props` 中的数据,所以上面这段代码的作用是如果发现 `data` 数据字段的 `key` 已经在 `props` 中有定义了,那么就会打印警告。另外这里有一个优先级的关系:**props优先级 > data优先级 > methods优先级**。即如果一个 `key` 在 `props` 中有定义了那么就不能在 `data` 中出现;如果一个 `key` 在 `data` 中出现了那么就不能在 `methods` 中出现了。
 
-另外上面的代码中当 `if` 语句的条件不成立,则会判断 `else if` 语句中的条件:`!isReserved(key)`,该条件的意思是判断定义在 `data` 中的 `key` 是否是保留键,大家可以在 [core/util 目录下的工具方法全解](/note/附录/core-util) 中查看对于 `isReserved` 函数的讲解。`isReserved` 函数通过判断一个字符串的第一个字符是不是 `$` 或 `_` 来决定其是否是保留的,`Vue` 是不会代理那些键名以 `$` 或 `_` 开头的字段的,因为 `Vue` 自身的属性和方法都是以 `$` 或 `_` 开头的,所以这么做是为了避免与 `Vue` 自身的属性和方法相冲突。
+另外上面的代码中当 `if` 语句的条件不成立,则会判断 `else if` 语句中的条件:`!isReserved(key)`,该条件的意思是判断定义在 `data` 中的 `key` 是否是保留键,大家可以在 [core/util 目录下的工具方法全解](../appendix/core-util.md) 中查看对于 `isReserved` 函数的讲解。`isReserved` 函数通过判断一个字符串的第一个字符是不是 `$` 或 `_` 来决定其是否是保留的,`Vue` 是不会代理那些键名以 `$` 或 `_` 开头的字段的,因为 `Vue` 自身的属性和方法都是以 `$` 或 `_` 开头的,所以这么做是为了避免与 `Vue` 自身的属性和方法相冲突。
 
 如果 `key` 既不是以 `$` 开头,又不是以 `_` 开头,那么将执行 `proxy` 函数,实现实例对象的代理访问:
 
@@ -1448,7 +1448,7 @@ augment(value, arrayMethods, arrayKeys)
 this.observeArray(value)
 ```
 
-首先定义了 `augment` 常量,这个常量的值根据 `hasProto` 的真假而定,如果 `hasProto` 为真则 `augment` 的值为 `protoAugment`,否则值为 `copyAugment`。那么 `hasProto` 是什么呢?大家可以在附录 [core/util 目录下的工具方法全解](/note/附录/core-util) 中查看其讲解,其实 `hasProto` 是一个布尔值,它用来检测当前环境是否可以使用 `__proto__` 属性,如果 `hasProto` 为真则当前环境支持 `__proto__` 属性,否则意味着当前环境不能够使用 `__proto__` 属性。
+首先定义了 `augment` 常量,这个常量的值根据 `hasProto` 的真假而定,如果 `hasProto` 为真则 `augment` 的值为 `protoAugment`,否则值为 `copyAugment`。那么 `hasProto` 是什么呢?大家可以在附录 [core/util 目录下的工具方法全解](../appendix/core-util.md) 中查看其讲解,其实 `hasProto` 是一个布尔值,它用来检测当前环境是否可以使用 `__proto__` 属性,如果 `hasProto` 为真则当前环境支持 `__proto__` 属性,否则意味着当前环境不能够使用 `__proto__` 属性。
 
 如果当前环境支持使用 `__proto__` 属性,那么 `augment` 的值是 `protoAugment`,其中 `protoAugment` 就定义在 `Observer` 类的下方。源码如下:
 

+ 7 - 7
docs/art/80vue-compiler-start.md

@@ -203,7 +203,7 @@ const { render, staticRenderFns } = compileToFunctions(template, {
 }
 ```
 
-其中 `shouldDecodeNewlines` 和 `shouldDecodeNewlinesForHref` 这两个变量来自于 `platforms/web/util.js` 文件,大家可以在附录 [platforms/web/util 目录下的工具方法全解](/note/附录/web-util) 中查看这两个变量的作用,其目的是对浏览器的怪癖做兼容,具体在附录中都有讲到,并且这两个变量的类型都是布尔值。
+其中 `shouldDecodeNewlines` 和 `shouldDecodeNewlinesForHref` 这两个变量来自于 `platforms/web/util.js` 文件,大家可以在附录 [platforms/web/util 目录下的工具方法全解](../appendix/web-util.md) 中查看这两个变量的作用,其目的是对浏览器的怪癖做兼容,具体在附录中都有讲到,并且这两个变量的类型都是布尔值。
 
 对于 `options.delimiters` 和 `options.comments`,其中 `options` 就是当前 `Vue` 实例的 `$options` 属性,并且 `delimiters` 和 `comments` 都是 `Vue` 提供的选项。所以这里只是简单的将这两个选项透传了过去。
 
@@ -433,7 +433,7 @@ const compiled = compile(template, options)
 }
 ```
 
-其中 `warn` 属性被 `delete` 操作符删除。这里只是给大家做一个简短的回顾,并且我们对 `Vue` 的编译器所接收的参数进行归纳,并整理了附录 [编译器选项整理](/note/附录/compiler-options),后面遇到的任何编译器选项都会整理到该附录里,大家可以在这里查阅 `Vue` 编译器所接收的选项。
+其中 `warn` 属性被 `delete` 操作符删除。这里只是给大家做一个简短的回顾,并且我们对 `Vue` 的编译器所接收的参数进行归纳,并整理了附录 [编译器选项整理](../appendix/compiler-options.md),后面遇到的任何编译器选项都会整理到该附录里,大家可以在这里查阅 `Vue` 编译器所接收的选项。
 
 知道了这些我们就可以去看 `compile` 函数的代码了,我们知道 `compile` 函数是 `createCompileToFunctionFn` 函数的形参,也就是说,`compile` 函数是被从其他地方传递过来了,其实前面我们都分析过,这里的 `compile` 函数就是 `src/compiler/create-compiler.js` 文件中定义在 `createCompiler` 函数内的 `compile` 函数,如下:
 
@@ -627,7 +627,7 @@ export default function text (el: ASTElement, dir: ASTDirective) {
 
 它是一个包含三个属性的对象,且属性的值都是函数。
 
-`baseOptions` 的第四个属性是 `isPreTag`,它是一个函数,可以在附录 [platforms/web/util 目录下的工具方法全解](/note/附录/web-util) 中查看其实现讲解,其作用是通过给定的标签名字检查标签是否是 `'pre'` 标签。
+`baseOptions` 的第四个属性是 `isPreTag`,它是一个函数,可以在附录 [platforms/web/util 目录下的工具方法全解](../appendix/web-util.md) 中查看其实现讲解,其作用是通过给定的标签名字检查标签是否是 `'pre'` 标签。
 
 `baseOptions` 的第五个属性是 `isUnaryTag`,它来自于与 `options.js` 文件同级目录下的 `util.js` 文件,即 `src/platforms/web/compiler/util.js` 文件,再看这个文件,找到 `isUnaryTag` 如下:
 
@@ -640,7 +640,7 @@ export const isUnaryTag = makeMap(
 
 可以看到 `isUnaryTag` 是一个通过 `makeMap` 生成的函数,该函数的作用是检测给定的标签是否是一元标签。
 
-`baseOptions` 的第六个属性是 `mustUseProp`,它是一个函数,可以在附录 [platforms/web/util 目录下的工具方法全解](/note/附录/web-util) 中查看其实现讲解,其作用是用来检测一个属性在标签中是否要使用 `props` 进行绑定。
+`baseOptions` 的第六个属性是 `mustUseProp`,它是一个函数,可以在附录 [platforms/web/util 目录下的工具方法全解](../appendix/web-util.md) 中查看其实现讲解,其作用是用来检测一个属性在标签中是否要使用 `props` 进行绑定。
 
 `baseOptions` 的第七个属性是 `canBeLeftOpenTag`,它也是一个函数,来自于 `src/platforms/web/compiler/util.js` 文件,源码如下:
 
@@ -654,11 +654,11 @@ export const canBeLeftOpenTag = makeMap(
 
 该函数也是一个使用 `makeMap` 生成的函数,它的作用是检测一个标签是否是那些虽然不是一元标签,但却可以自己补全并闭合的标签。比如 `p` 标签是一个双标签,你需要这样使用 `<p>Some content</p>`,但是你依然可以省略闭合标签,直接这样写:`<p>Some content`,且浏览器会自动补全。但是有些标签你不可以这样用,它们是严格的双标签。
 
-`baseOptions` 的第八个属性是 `isReservedTag`,它是一个函数,可以在附录 [platforms/web/util 目录下的工具方法全解](/note/附录/web-util) 中查看其实现讲解,其作用是检查给定的标签是否是保留的标签。
+`baseOptions` 的第八个属性是 `isReservedTag`,它是一个函数,可以在附录 [platforms/web/util 目录下的工具方法全解](../appendix/web-util.md) 中查看其实现讲解,其作用是检查给定的标签是否是保留的标签。
 
-`baseOptions` 的第九个属性是 `getTagNamespace`,它也是一个函数,同样可以在附录 [platforms/web/util 目录下的工具方法全解](/note/附录/web-util) 中查看其实现讲解,其作用是获取元素(标签)的命名空间。
+`baseOptions` 的第九个属性是 `getTagNamespace`,它也是一个函数,同样可以在附录 [platforms/web/util 目录下的工具方法全解](../appendix/web-util.md) 中查看其实现讲解,其作用是获取元素(标签)的命名空间。
 
-`baseOptions` 的第十个属性是 `staticKeys`,它的值是通过以 `modules` 为参数调用 `genStaticKeys` 函数的返回值得到的。其中 `modules` 就是 `baseOptions` 的第二个属性,而 `genStaticKeys` 来自于 `src/shared/util.js` 文件,大家可以在附录 [shared/util.js 文件工具方法全解](/note/附录/shared-util) 中查看该函数的讲解,其作用是根据编译器选项的 `modules` 选项生成一个静态键字符串。
+`baseOptions` 的第十个属性是 `staticKeys`,它的值是通过以 `modules` 为参数调用 `genStaticKeys` 函数的返回值得到的。其中 `modules` 就是 `baseOptions` 的第二个属性,而 `genStaticKeys` 来自于 `src/shared/util.js` 文件,大家可以在附录 [shared/util.js 文件工具方法全解](../appendix/shared-util.md) 中查看该函数的讲解,其作用是根据编译器选项的 `modules` 选项生成一个静态键字符串。
 
 现在我们已经弄清楚 `baseOptions` 对象的各个属性都是什么了,这些属性作为编译器的基本参数选项,但是我们还不清楚其各个属性的意义,比如 `modules` 数组和 `directives` 对象等,不过不急,随着后面的深入,这些疑惑都将慢慢解开。
 

+ 5 - 5
docs/art/81vue-parse-ast.md

@@ -1,6 +1,6 @@
 # 词法分析 - 为生成AST做准备
 
-在 [Vue的编译器初探](/note/7Vue的编译器初探) 这一章节中,我们对 `Vue` 如何创建编译器,以及在这个过程中经历过的几个重要的函数做了分析,比如 `compileToFunctions` 函数以及 `compile` 函数,并且我们知道真正对模板进行编译工作的实际是 `baseCompile` 函数,而接下来我们任务就是搞清楚 `baseCompile` 函数的内容。
+在 [Vue的编译器初探](./80vue-compiler-start.md) 这一章节中,我们对 `Vue` 如何创建编译器,以及在这个过程中经历过的几个重要的函数做了分析,比如 `compileToFunctions` 函数以及 `compile` 函数,并且我们知道真正对模板进行编译工作的实际是 `baseCompile` 函数,而接下来我们任务就是搞清楚 `baseCompile` 函数的内容。
 
 `baseCompile` 函数是在 `src/compiler/index.js` 中作为 `createCompilerCreator` 函数的参数使用的,代码如下:
 
@@ -23,7 +23,7 @@ export const createCompiler = createCompilerCreator(function baseCompile (
 })
 ```
 
-可以看到 `baseCompile` 函数接收两个参数,分别是字符串模板(`template`)和选项参数(`options`),其中选项参数 `options` 我们已经分析过了,并且我们有对应的附录专门整理编译器的选项参数,可以在 [编译器选项整理](/note/附录/compiler-options) 中查看。
+可以看到 `baseCompile` 函数接收两个参数,分别是字符串模板(`template`)和选项参数(`options`),其中选项参数 `options` 我们已经分析过了,并且我们有对应的附录专门整理编译器的选项参数,可以在 [编译器选项整理](../appendix/compiler-options.md) 中查看。
 
 `baseCompile` 函数很简短,由三句代码和一个 `return` 语句组成,这三句代码的作用如以下:
 
@@ -319,7 +319,7 @@ const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10|#9);/g
 
 然后定义了 `reCache` 常量,它被初始化为一个空的 `JSON` 对象字面量。
 
-再往下定义了 `decodingMap` 常量,它也是一个 `JOSN` 对象字面量,其中 `key` 是一些特殊的 `html` 实体,值则是这些实体对应的字符。在 `decodingMap` 常量下面的是两个正则常量:`encodedAttr` 和 `encodedAttrWithNewLines`。可以发现正则 `encodedAttrWithNewLines` 会比 `encodedAttr` 多匹配两个 `html` 实体字符,分别是 `&#10;` 和 `&#9;`。对于 `decodingMap` 以及下面两个正则的作用不知道大家能不能猜得到,其实我们 [创建编译器](http://localhost:8080/#/note/7Vue%E7%9A%84%E7%BC%96%E8%AF%91%E5%99%A8%E5%88%9D%E6%8E%A2) 一节中有讲到 `shouldDecodeNewlines` 和 `shouldDecodeNewlinesForHref` 这两个编译器选项,当时我们就有针对这两个选项的作用做讲解,可以在附录 [platforms/web/util 目录下的工具方法全解](http://localhost:8080/#/note/%E9%99%84%E5%BD%95/web-util?id=compat-js-%E6%96%87%E4%BB%B6) 中查看。
+再往下定义了 `decodingMap` 常量,它也是一个 `JOSN` 对象字面量,其中 `key` 是一些特殊的 `html` 实体,值则是这些实体对应的字符。在 `decodingMap` 常量下面的是两个正则常量:`encodedAttr` 和 `encodedAttrWithNewLines`。可以发现正则 `encodedAttrWithNewLines` 会比 `encodedAttr` 多匹配两个 `html` 实体字符,分别是 `&#10;` 和 `&#9;`。对于 `decodingMap` 以及下面两个正则的作用不知道大家能不能猜得到,其实我们讲解编译器的创建时有讲到 `shouldDecodeNewlines` 和 `shouldDecodeNewlinesForHref` 这两个编译器选项,当时我们就有针对这两个选项的作用做讲解,可以在附录 [platforms/web/util 目录下的工具方法全解](../appendix/web-util.md) 中查看。
 
 所以这里的常量 `decodingMap` 以及两个正则 `encodedAttr` 和 `encodedAttrWithNewLines` 的作用就是用来完成对 `html` 实体进行解码的。
 
@@ -1026,7 +1026,7 @@ const l = match.attrs.length
 const attrs = new Array(l)
 ```
 
-其中常量 `unary` 是一个布尔值,当它为真时代表着标签是一元标签,否则是二元标签。对于一元标签判断的方法是首先调用 `isUnaryTag` 函数,并将标签名(`tagName`)作为参数传递,其中 `isUnaryTag` 函数前面提到过它是 `parser` 选项,实际上它是编译器选项透传过来的,我们在 [7Vue的编译器初探](/note/7Vue的编译器初探) 一节中对 `isUnaryTag` 函数有过讲解,简单的说 `isUnaryTag` 函数能够判断标准 `HTML` 中规定的那些一元标签,但是仅仅使用这一个判断条件是不够的,因为在 `Vue` 中我们免不了会写组件,而组件又是以自定义标签的形式存在的,比如:
+其中常量 `unary` 是一个布尔值,当它为真时代表着标签是一元标签,否则是二元标签。对于一元标签判断的方法是首先调用 `isUnaryTag` 函数,并将标签名(`tagName`)作为参数传递,其中 `isUnaryTag` 函数前面提到过它是 `parser` 选项,实际上它是编译器选项透传过来的,我们在 [7Vue的编译器初探](./80vue-compiler-start.md) 一节中对 `isUnaryTag` 函数有过讲解,简单的说 `isUnaryTag` 函数能够判断标准 `HTML` 中规定的那些一元标签,但是仅仅使用这一个判断条件是不够的,因为在 `Vue` 中我们免不了会写组件,而组件又是以自定义标签的形式存在的,比如:
 
 ```js
 <my-component />
@@ -1095,7 +1095,7 @@ attrs[i] = {
 
 与我们之前所说的一样,`attrs` 数组的每个元素对象只包含两个元素,即属性名 `name` 和属性值 `value`,对于属性名直接从 `args[1]` 中即可获取,但我们发现属性值却没有直接使用前面获取到的 `value`,而是将 `value` 传递给了 `decodeAttr` 函数,并使用该函数的返回值作为最终的属性值。
 
-实际上 `decodeAttr` 函数的作用是对属性值中所包含的 `html` 实体进行解码,将其转换为实体对应的字符。更多关于 `shouldDecodeNewlinesForHref` 与 `shouldDecodeNewlines` 的内容我们曾经提到过,大家可以在附录 [platforms/web/util 目录下的工具方法全解](/note/附录/web-util) 中找到详细讲解。
+实际上 `decodeAttr` 函数的作用是对属性值中所包含的 `html` 实体进行解码,将其转换为实体对应的字符。更多关于 `shouldDecodeNewlinesForHref` 与 `shouldDecodeNewlines` 的内容我们曾经提到过,大家可以在附录 [platforms/web/util 目录下的工具方法全解](../appendix/web-util.md) 中找到详细讲解。
 
 这样 `for` 循环语句块的代码我们就讲完了,在 `for` 循环语句块的下面是这样一段代码: