Pārlūkot izejas kodu

chore: modify typos

miaoyuxinbaby 7 gadi atpakaļ
vecāks
revīzija
add4d507a3
1 mainītis faili ar 17 papildinājumiem un 17 dzēšanām
  1. 17 17
      docs/art/82vue-parsing.md

+ 17 - 17
docs/art/82vue-parsing.md

@@ -463,7 +463,7 @@ el = {
 }
 ```
 
-那么 `process*` 类的函数接收 `el` 参数后都做了什么呢?实际上 `process*` 类函数的作用就是对元素描述对象做进一步处理,比如其中一个函数叫做 `processPre`,这个函数的作用就是用来检测 `el` 元素是否拥有 `v-pre` 属性,如果有 `v-pre` 属性则会在 `el` 描述对象上添加一个 `pre` 属性,如下:
+那么 `process*` 系列的函数接收 `el` 参数后都做了什么呢?实际上 `process*` 系列函数的作用就是对元素描述对象做进一步处理,比如其中一个函数叫做 `processPre`,这个函数的作用就是用来检测 `el` 元素是否拥有 `v-pre` 属性,如果有 `v-pre` 属性则会在 `el` 描述对象上添加一个 `pre` 属性,如下:
 
 ```js {8}
 el = {
@@ -477,9 +477,9 @@ el = {
 }
 ```
 
-类似的,所有 `process*` 函数的作用都是为了让一个元素的描述对象更加充实,使这个对象能更加详细地描述一个元素,并且这些函数都会用在 `parseHTML` 函数的钩子选项函数中。
+类似的,所有 `process*` 系列函数的作用都是为了让一个元素的描述对象更加充实,使这个对象能更加详细地描述一个元素,并且这些函数都会用在 `parseHTML` 函数的钩子选项函数中。
 
-另外我们也能看到很多非 `process*` 的函数,例如 `findPrevElement`、`makeAttrsMap` 等等,这些函数实际上就是工具函数。
+另外我们也能看到很多非 `process*` 系列的函数,例如 `findPrevElement`、`makeAttrsMap` 等等,这些函数实际上就是工具函数。
 
 以上就是 `src/compiler/parser/index.js` 文件的整体结构。接下来我们将重新回到该文件的开头部分,来看看都定义了哪些常量或变量。
 
@@ -1788,7 +1788,7 @@ if (children[i].type === 1) {
 * 1、`start` 钩子函数是当解析 `html` 字符串遇到开始标签时被调用的。
 * 2、模板中禁止使用 `<style>` 标签和那些没有指定 `type` 属性或 `type` 属性值为 `text/javascript` 的 `<script>` 标签。
 * 3、在 `start` 钩子函数中会调用前置处理函数,这些前置处理函数都放在 `preTransforms` 数组中,这么做的目的是为不同平台提供对应平台下的解析工作。
-* 4、前置处理函数执行完之后会调用一系列 `process*` 函数继续对元素描述对象进行加工。
+* 4、前置处理函数执行完之后会调用一系列 `process*` 函数继续对元素描述对象进行加工。
 * 5、通过判断 `root` 是否存在来判断当前解析的元素是否为根元素。
 * 6、`slot` 标签和 `template` 标签不能作为根元素,并且根元素不能使用 `v-for` 指令。
 * 7、可以定义多个根元素,但必须使用 `v-if`、`v-else-if` 以及 `v-else` 保证有且仅有一个根元素被渲染。
@@ -2452,7 +2452,7 @@ function processIf (el) {
 }
 ```
 
-如上这种比较方式实际上是 `v-if` 指令的值与 `null` 做对比,只要值不等于 `null` 则该条件就会成立,所以如果你在编写 `v-if` 指令时没有写属性值,则通过 `getAndRemoveAttr` 函数获取到的 `v-if` 属性值将是一个空字符串,由于空字符串不等于 `null`,所以如上条件会成立。但是源码中的比较方式不会这样,如果你在编写 `v-if` 指令时没有写属性值,则 `exp` 常量就是空字符串,所以 `if` 条件语句不会被执行。哪一种更合理呢?实际上是源码的实现方式更合理,源码的逻辑是只要你没有写 `v-if` 指令的属性值,那么就当做你根本没有使用 `v-if` 指令,不然的话该元素将永远不会被渲染。
+如上这种比较方式实际上是 `v-if` 指令的值与 `null` 做对比,只要值不等于 `null` 则该条件就会成立,所以如果你在编写 `v-if` 指令时没有写属性值,则通过 `getAndRemoveAttr` 函数获取到的 `v-if` 属性值将是一个空字符串,由于空字符串不等于 `null`,所以如上条件会成立。但是源码中的比较方式不会这样,如果你在编写 `v-if` 指令时没有写属性值,则 `exp` 常量就是空字符串,所以 `if` 条件语句不会被执行。哪一种更合理呢?实际上是源码的实现方式更合理,源码的逻辑是只要你没有写 `v-if` 指令的属性值,那么就当做你根本没有使用 `v-if` 指令,不然的话该元素将永远不会被渲染。
 
 假设我们读取到了 `v-if` 指令的值,此时 `if` 语句块内的代码将被执行,如下:
 
@@ -2583,7 +2583,7 @@ if (inVPre) {
 }
 ```
 
-实际上 `processElement` 函数是其他一列 `process*` 函数的集合,如下:
+实际上 `processElement` 函数是其他一列 `process*` 函数的集合,如下:
 
 ```js
 export function processElement (element: ASTElement, options: CompilerOptions) {
@@ -2679,11 +2679,11 @@ if (dynamicValue != null) {
 }
 ```
 
-这段代码是一段 `if...elseif` 添加语句块,这里再次强调 `if` 语句的条件是在判断绑定的属性是否存在,而非判断属性值 `dynamicValue` 是否存在,因为即使获取到的属性值为空字符串,但由于空字符串不与 `null` 相等,所以 `if` 条件语句成立。只有当绑定属性本身就不存在时,此时获取到的属性值为 `undefined`,与 `null` 相等,这时才会执行 `elseif` 分支的判断。
+这段代码是一段 `if...elseif` 添加语句块,这里再次强调 `if` 语句的条件是在判断绑定的属性是否存在,而非判断属性值 `dynamicValue` 是否存在,因为即使获取到的属性值为空字符串,但由于空字符串不与 `null` 相等,所以 `if` 条件语句成立。只有当绑定属性本身就不存在时,此时获取到的属性值为 `undefined`,与 `null` 相等,这时才会执行 `elseif` 分支的判断。
 
-假设成功到了获取绑定的属性值,那么 `if` 语句块内的代码将被执行,可以看到在 `if` 语句块内直接调用了 `parseFilters` 函数并将该函数的返回值作为 `getBindingAttr` 函数的返回值。其中 `parseFilters` 函数使我们接下来将要重点讲解的函数,不过现在我们扔需要将目光聚焦在 `getBindingAttr` 函数上。
+假设成功到了获取绑定的属性值,那么 `if` 语句块内的代码将被执行,可以看到在 `if` 语句块内直接调用了 `parseFilters` 函数并将该函数的返回值作为 `getBindingAttr` 函数的返回值。其中 `parseFilters` 函数是我们接下来将要重点讲解的函数,不过现在我们仍需要将目光聚焦在 `getBindingAttr` 函数上。
 
-如果获取绑定的值失败,则会执行 `elseif` 分支的判断,可以看到 `elseif` 分支检测了 `getBindingAttr` 函数的第三个参数 `getStatic` 是否与 `false` 全等,这里的关键是一定要全等才行,也就是说如果调用 `getBindingAttr` 函数不传递第三个参数,则参数 `getStatic` 的值为 `undefined`,它不全等于 `false`,所以可以理解为当不传递第三个参数时 `elseif` 分支的条件默认成立。`elseif` 语句块内代码的作用是用来获取非绑定的属性值,因为代码既然执行到了 `elseif` 分支,则说明此时获取绑定的属性值失败,我们知道当我们为元素或组件添加属性时,这个属性可以是绑定的也可以是非绑定的,所以当获取绑定的属性失败时我们不能够武断的认为开发者没有编写该属性,而是应该继续尝试获取非绑定的属性值,如下高亮的代码所示:
+如果获取绑定的值失败,则会执行 `elseif` 分支的判断,可以看到 `elseif` 分支检测了 `getBindingAttr` 函数的第三个参数 `getStatic` 是否与 `false` 全等,这里的关键是一定要全等才行,也就是说如果调用 `getBindingAttr` 函数不传递第三个参数,则参数 `getStatic` 的值为 `undefined`,它不全等于 `false`,所以可以理解为当不传递第三个参数时 `elseif` 分支的条件默认成立。`elseif` 语句块内代码的作用是用来获取非绑定的属性值,因为代码既然执行到了 `elseif` 分支,则说明此时获取绑定的属性值失败,我们知道当我们为元素或组件添加属性时,这个属性可以是绑定的也可以是非绑定的,所以当获取绑定的属性失败时我们不能够武断的认为开发者没有编写该属性,而是应该继续尝试获取非绑定的属性值,如下高亮的代码所示:
 
 ```js {4}
 if (dynamicValue != null) {
@@ -2696,9 +2696,9 @@ if (dynamicValue != null) {
 }
 ```
 
-非绑定属性值的获取方式同是使用 `getAndRemoveAttr` 函数,只不过此时传递给该函数的第二个参数是原始的属性名字,不带有 `v-bind` 或 `:`。同时将获取结果保存在 `staticValue` 常量中,接着进入一个条件判断,如果开发者属性存在则使用 `JSON.stringify` 函数对属性值进行处理后将其返回。
+非绑定属性值的获取方式同是使用 `getAndRemoveAttr` 函数,只不过此时传递给该函数的第二个参数是原始的属性名字,不带有 `v-bind` 或 `:`。同时将获取结果保存在 `staticValue` 常量中,接着进入一个条件判断,如果开发者属性存在则使用 `JSON.stringify` 函数对属性值进行处理后将其返回。
 
-大家注意 `JSON.stringify` 函数对属性值的处理至关重要,这么做能够保证对于非绑定的属性来讲,总是会将该属性的值作为字符串处理。为了让大家更好理解,我们举个例子。我们知道编译器所生成的渲染函数其实是字符串形式的渲染函数,该字符串要通过 `new Function(str)` 之后才能变成真正的函数,对比如下代码:
+大家注意 `JSON.stringify` 函数对属性值的处理至关重要,这么做能够保证对于非绑定的属性来讲,总是会将该属性的值作为字符串处理。为了让大家更好理解,我们举个例子。我们知道编译器所生成的渲染函数其实是字符串形式的渲染函数,该字符串要通过 `new Function(str)` 之后才能变成真正的函数,对比如下代码:
 
 ```js
 // 代码一
@@ -2751,7 +2751,7 @@ if (dynamicValue != null) {
 <div :key="id | featId"></div>
 ```
 
-不过这只是从技术上讲,实际开发中更合适的方案是使用计算属性。总之对于绑定的属性值,为了让其拥有使用过滤器的能力,就需要使用 `parseFilters` 函数处理。`parseFilters` 函数来自于 `src/compiler/parser/filter-parser.js` 文件,它的作用简单说就是用来将绑定的值分为两部分,一部分称之为表达式,另外一部分则是过滤器函数,然后将这两部分结合在一起,举个例子,如下代码所示:
+不过这只是从技术上讲,实际开发中更合适的方案是使用计算属性。总之对于绑定的属性值,为了让其拥有使用过滤器的能力,就需要使用 `parseFilters` 函数处理。`parseFilters` 函数来自于 `src/compiler/parser/filter-parser.js` 文件,它的作用简单说就是用来将绑定的值分为两部分,一部分称之为表达式,另外一部分则是过滤器函数,然后将这两部分结合在一起,举个例子,如下代码所示:
 
 ```html
 <div :key="id | featId"></div>
@@ -2776,7 +2776,7 @@ if (dynamicValue != null) {
 <div :key="`id | featId`"></div>  <!-- 模板字符串内的管道符 -->
 ```
 
-除了这三种情况之外还有一种比较特殊的情况,就是正则表达式中的管道符,如下:
+除了这三种情况之外还有一种比较特殊的情况,就是正则表达式中的管道符,如下:
 
 ```html
 <div :key="/id|featId/.test(id).toString()"></div>  <!-- 正则表达式内的管道符 -->
@@ -2790,9 +2790,9 @@ if (dynamicValue != null) {
 <div :key="id || featId"></div>  <!-- 模板字符串内的管道符 -->
 ```
 
-如上代码所示,绑定属性 `key` 的属性值是一个表达式,该表达式里的 `||` 符号代表的是或运算符,而或运算符是由两个管道符 `|` 组成的,所以我们不能把这两个管道符中的任何一个作为过滤器的分界线。
+如上代码所示,绑定属性 `key` 的属性值是一个表达式,该表达式里的 `||` 符号代表的是逻辑或运算符,而逻辑或运算符是由两个管道符 `|` 组成的,所以我们不能把这两个管道符中的任何一个作为过滤器的分界线。
 
-实际上除了以上五情况之外,管道符存在歧义的地方还有**按位或**运算符,它是位运算中的一个运算符,该运算符就是由一个管道符组成,所以它与过滤器的分界线完全一样,这时我们必须选择做出选择,既然你希望管道符用来作为过滤器的分界线那就抛弃它按位或运算符的意义。有的同学会说,这不是得不到完全的语言能力了吗?实际上问题一点都不大,因为任何绑定属性的值理论上你都可以通过计算属性实现,而不是直接将表达式写在属性值的位置。话虽然这么说但是我们还是应该做一些基本的处理,比如以上列出的五种管道符存在歧义的地方我们是有能力处理的。
+实际上除了以上五情况之外,管道符存在歧义的地方还有**按位或**运算符,它是位运算中的一个运算符,该运算符就是由一个管道符组成,所以它与过滤器的分界线完全一样,这时我们必须做出选择:既然你希望管道符用来作为过滤器的分界线那就抛弃它按位或运算符的意义。有的同学会说,这不是得不到完全的语言能力了吗?实际上问题一点都不大,因为任何绑定属性的值理论上你都可以通过计算属性实现,而不是直接将表达式写在属性值的位置。话虽然这么说但是我们还是应该做一些基本的处理,比如以上列出的五种管道符存在歧义的地方我们是有能力处理的。
 
 接下来我们思考一下应该如何判断一个管道符到底是不是表达式与过滤器的分界线,我们依据五种情况逐个分析,首先对于单引号中的管道符:
 
@@ -2808,7 +2808,7 @@ if (dynamicValue != null) {
 <div :key="/id|featId/.test(id).toString()"></div>  <!-- 正则表达式内的管道符 -->
 ```
 
-这种情况会比较复杂,因为我们要有能力识别出管道符是否存在于正则表达中才行,难点在就于如何识别正则表达式,我们知道正则表达式由斜杠(`/`)开头,并以斜杠(`/`)结尾,但不要忘了斜杠在 `js` 这门语言中还被用作除法运算符。所以归根结底难点在于我们需要识别一个斜杠它所代表的意义到底是除法还是正则。
+这种情况会比较复杂,因为我们要有能力识别出管道符是否存在于正则表达中才行,难点在就于如何识别正则表达式,我们知道正则表达式由斜杠(`/`)开头,并以斜杠(`/`)结尾,但不要忘了斜杠在 `js` 这门语言中还被用作除法运算符。所以归根结底难点在于我们需要识别一个斜杠它所代表的意义到底是除法还是正则。
 
 实际上这是一个相当复杂的事情,引用 [ECMA 规范](http://www.ecma-international.org/ecma-262/9.0/index.html#sec-ecmascript-language-lexical-grammar) 中的一段例子:
 
@@ -2835,7 +2835,7 @@ var a = {}
 /1/g
 ```
 
-如上两段代码所示,这两段代码具有相同的特点,即第一句代码的最后一个字符为 `{`,第二句代码的第一个字符为 `/`。大家思考一下哪一段代码中的斜杠是除法运算符,哪一段代码中的斜杠是正则表达式的开头?实际上第一段代码中的斜杠是正则,因为该斜杠之前的语境是函数定义,而第二段代码中的斜杠是除法,因为该斜杠之前的语境为表达式并且花括号(`{}`)的意义为对象字面量。
+如上两段代码所示,这两段代码具有相同的特点,即第一句代码的最后一个字符为 `}`,第二句代码的第一个字符为 `/`。大家思考一下哪一段代码中的斜杠是除法运算符,哪一段代码中的斜杠是正则表达式的开头?实际上第一段代码中的斜杠是正则,因为该斜杠之前的语境是函数定义,而第二段代码中的斜杠是除法,因为该斜杠之前的语境为表达式并且花括号(`{}`)的意义为对象字面量。
 
 实际上判断一个斜杠到底代表什么意义,应该综合考虑上下文语境,[ECMA 规范中](http://www.ecma-international.org/ecma-262/9.0/index.html#sec-ecmascript-language-lexical-grammar) 中清楚的已经告诉大家需要多种标志符号类型(`goal symbols`)来综合判断,并且还要考虑 `javascript` 这门语言的自动插入分号机制,以及其他可能产生歧义的地方。