diff --git "a/blogs/frontEnd/Vue \345\255\246\344\271\240\347\254\224\350\256\260/Vue\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\344\270\200\357\274\211\357\274\232\346\250\241\347\211\210\350\257\255\346\263\225\343\200\201\346\235\241\344\273\266\346\270\262\346\237\223\343\200\201\345\210\227\350\241\250\346\270\262\346\237\223\343\200\201key\345\200\274\347\256\241\347\220\206.md" "b/blogs/frontEnd/Vue \345\255\246\344\271\240\347\254\224\350\256\260/Vue\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\344\270\200\357\274\211\357\274\232\346\250\241\347\211\210\350\257\255\346\263\225\343\200\201\346\235\241\344\273\266\346\270\262\346\237\223\343\200\201\345\210\227\350\241\250\346\270\262\346\237\223\343\200\201key\345\200\274\347\256\241\347\220\206.md" new file mode 100644 index 00000000..f0ca5da7 --- /dev/null +++ "b/blogs/frontEnd/Vue \345\255\246\344\271\240\347\254\224\350\256\260/Vue\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\344\270\200\357\274\211\357\274\232\346\250\241\347\211\210\350\257\255\346\263\225\343\200\201\346\235\241\344\273\266\346\270\262\346\237\223\343\200\201\345\210\227\350\241\250\346\270\262\346\237\223\343\200\201key\345\200\274\347\256\241\347\220\206.md" @@ -0,0 +1,286 @@ +--- +title: Vue笔记 +date: 2024/9/16 +categories: + - fe +author: aoxuexinghuo +tags: + - Vue + - 手写笔记 + - 前端框架 +--- +## Vue学习笔记(一):模版语法、条件渲染、列表渲染、key 值管理 + +[TOC] + +### 一、模版语法 + +Vue 使用一种基于 HTML 的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。所有的 Vue 模板都是语法层面合法的 HTML,可以被符合规范的浏览器和 HTML 解析器解析。 + +#### 1.文本插值 + +文本插值最基本的数据绑定语法,采用双大括号{{ }}的形式。 + +```vue + + + +``` + +{{ }}标签的内容将会被替代为对应组件实例中 message 属性的值,如果 message 属性的值发生了改变,{{ }} 标签内容也会更新。 + +因此,如果不想改变标签的内容,可以通过使用 `v-once` 指令执行一次性地插值,当数据改变时,插值处的内容不会更新。 + +```vue +

该值不会改变:{{ message }}

+``` + +在上面的演示中,我们绑定的只是简单的属性名,但实际上,Vue在所有的数据绑定中都支持完整的 JavaScript 表达式。例如: + +```vue +

{{ message.split("").reverse().join("") }}

+``` + +但需要注意的是,每个绑定仅支持单一表达式,也就是一段能够被求值的 JavaScript 代码。我们可以通过其能否合法放在`return`的后面来进行判断。 + +#### 2.原始 HTML + +双大括号会将数据插值为纯文本,而不是 HTML。若想插入 HTML,则需要使用`v-html`指令。我们可以通过下面的代码来观察两者的区别。 + +```vue + + + +``` + +![img](https://i-blog.csdnimg.cn/blog_migrate/688e7b6e19362ec0a89b1e8283fee227.png) + +我们可以看到,前者只是做了单纯的文本替换,后者则是将我们想要的链接成功渲染出来(渲染方式为在p标签里嵌套一个a标签)。 + +#### 3.属性绑定 + +从前文`v-html`指令的使用中,我们可以想到,既然双大括号不能用于插入 HTML,那么修改 HTML 属性显然也是不行的。当我们想要响应式地绑定一个属性,应该使用`v-bind`指令。而如果绑定的值是`null`或者`undefined`,那么该属性将会从渲染的元素上移除。 + +```vue + + + +``` + +![img](https://i-blog.csdnimg.cn/blog_migrate/058ad1e487ae154b573a3545313fefa0.png) + + 我们可以看到,在 HTML 中,`class`和`id`都被成功赋值,`title`由于被赋予的值为`null`而被移除。 + +由于`v-bind`指令使用过于频繁,我们可以通过简写的方式把`v-bind`省略,只保留冒号,如: + +```vue +

小火龙

+``` + +`v-bind`也可用于绑定布尔属性: + +```vue + + + +``` + +当我们想要动态绑定多属性时,也可以借助 JavaScript 对象: + +```vue + + + +``` + +### 二、条件渲染 + +条件渲染主要借助`v-if`,`v-else`,`v-else-if`,`v-show`指令。其具体的用法与逻辑很简单,我们可以通过下面的例子具体感受: + +```vue + + + +``` + +![img](https://i-blog.csdnimg.cn/blog_migrate/365223ab25db3d457e0bd3e7438665f7.png) + +有些同学可能会发现,`v-if`与`v-show`的功能似乎是一样的,那么我们又为什么要引入`v-show`指令呢?或者说两者有什么区别呢? + +**`v-if`与`v-show`区别:** + +`v-if`是“真实的”按条件渲染,因为它确保了在切换时,条件区块内的事件监听和子组件都会被销毁与重建。 + +同事`v-if`也是惰性的,如果在初次渲染时条件值为 false,则不会做任何事。条件区块只有当条件首次变为 true 时才会被渲染。 + +相比之下,`v-show`更加简单,元素无论初始条件如何,始终会被渲染,只有 CSS 的`display`属性会被切换。 + +总的来说,`v-if`有更高的切换开销,而`v-show`有更高的初始渲染开销。因此,如果需要频繁切换,则使用`v-show`比较好;如果在运行时绑定条件很少改变,则`v-if`会更合适。 + +### 三、列表渲染 + +我们可以使用`v-for`指令基于一个数组来渲染一个列表。`v-for`指令的值需要使用`item in items`形式的特殊语法,其中`items`是源数据的数组,而`item`是迭代项的别名(可自行更改)。 + +遍历的对象既可以是数组,也可以是对象,或者是更为复杂的对象数组。 + +```vue + + + +``` + +![img](https://i-blog.csdnimg.cn/blog_migrate/db52c75254542a9c62c41bd5491bdeed.png) + +`v-for`也支持使用可选的参数`index`,`key`,`value`等(`value`可以替换为`item`)。 + +```vue + + + +``` + + +此外,我们也可以用of作为分隔符来代替in,这更加接近JavaScript的迭代器语法: + +```vue +

{{ item }}

+``` + +### #通过 key 管理状态 + +Vue 默认按照“就地更新”的策略来更新通过`v-for`渲染的元素列表。当数据项的顺序改变时,Vue 不会随之移动DOM元素的顺序,而是就地更新每个元素,确保它们在原本指定的索引位置上渲染。为了给 Vue 一个提示,以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素,我们需要为每一个元素对应的块提供一个唯一的 key attribute。 + +```vue + + +``` + +`key`在这里是通过`v-blind`绑定的特殊 attribute(此处的`v-blind`被省略)。 + +推荐在任何可行的时候为`v-for`提供一个 key attribute(在 Vue2 版本中不添加key会导致出现警告信息,而在最新的 Vue3 版本中取消了这一限制,我们以最新的 Vue3 为基准)。 + +`key`绑定的值期望是一个基础类型的值,例如字符串或`number`类型。一般情况下,不建议使用`index`作为`key`值,因为数据的插入和删除会导致`index`的改变,而我们要确保每一条数据的唯一索引不会发生变化。例如,如果对象数据存在唯一的`id`属性,我们可以把`id`属性的值作为`key`。 \ No newline at end of file diff --git "a/blogs/frontEnd/Vue \345\255\246\344\271\240\347\254\224\350\256\260/Vue\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\344\270\211\357\274\211\357\274\232\350\256\241\347\256\227\345\261\236\346\200\247\343\200\201\347\261\273\344\270\216\346\240\267\345\274\217\347\273\221\345\256\232\343\200\201\350\241\250\345\215\225\350\276\223\345\205\245\347\273\221\345\256\232\343\200\201\344\276\246\345\220\254\345\231\250\343\200\201\346\250\241\347\211\210\345\274\225\347\224\250.md" "b/blogs/frontEnd/Vue \345\255\246\344\271\240\347\254\224\350\256\260/Vue\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\344\270\211\357\274\211\357\274\232\350\256\241\347\256\227\345\261\236\346\200\247\343\200\201\347\261\273\344\270\216\346\240\267\345\274\217\347\273\221\345\256\232\343\200\201\350\241\250\345\215\225\350\276\223\345\205\245\347\273\221\345\256\232\343\200\201\344\276\246\345\220\254\345\231\250\343\200\201\346\250\241\347\211\210\345\274\225\347\224\250.md" new file mode 100644 index 00000000..a1d98d88 --- /dev/null +++ "b/blogs/frontEnd/Vue \345\255\246\344\271\240\347\254\224\350\256\260/Vue\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\344\270\211\357\274\211\357\274\232\350\256\241\347\256\227\345\261\236\346\200\247\343\200\201\347\261\273\344\270\216\346\240\267\345\274\217\347\273\221\345\256\232\343\200\201\350\241\250\345\215\225\350\276\223\345\205\245\347\273\221\345\256\232\343\200\201\344\276\246\345\220\254\345\231\250\343\200\201\346\250\241\347\211\210\345\274\225\347\224\250.md" @@ -0,0 +1,267 @@ +--- +title: Vue笔记 +date: 2024/9/16 +categories: + - fe +author: aoxuexinghuo +tags: + - Vue + - 手写笔记 + - 前端框架 +--- +## Vue学习笔记(三):计算属性、类与样式绑定、表单输入绑定、侦听器、模版引用 + +[TOC] + +### 一、计算属性 + +#### 1.使用方式 + +在前面模版语法的学习中我们了解到,Vue 在所有的数据绑定中都支持使用完整地 JavaScript 表达式。但当模版中的表达式较为复杂时,可能会显得十分臃肿,难以维护。这时就要用到我们的计算属性了。下面以一个简单的代码为例,用来检查`names`数组中是否有元素: + +```vue + + + +``` + + + 我们通常将计算属性放在与`data`同级的`computed`中,与方法不同的是,我们在调用计算属性时不需要加括号,而是直接写函数名,使用方式与一般的属性相同。 + +既然提到方法,我们不免疑惑,我们使用方法似乎也能实现相同的功能,为什么又要引入所谓的计算属性呢?计算属性和传统的方法相比有什么优势? + +#### 2.计算属性与方法的区别 + +计算属性与方法的不同之处在于计算属性值会基于其响应式依赖而被缓存。一个计算属性只会在其响应式依赖更新时才会重新计算,否则无论被访问多少次都会直接返回先前的计算结果,而不用重复执行函数。以上面的代码为例,如果我们额外添加一行 `

{{ isNames }}

`,`isNames`函数也只会被执行一次,只有当其所依赖的`names`更新时,其才会被重新执行。 + +与此相对的,方法调用总是会在重渲染发生时再次执行函数。 + +### 二、类与样式绑定 + +为了方便使用,Vue 为`class`和`style`属性的`v-bind`用法提供了功能增强,使其除了能和一般的属性一样绑定字符串外,还能够进行对象或者数组的绑定。 + +#### 1.Class 的绑定 + +**绑定对象:** +我们可以通过给`v-bind: class`传递一个对象的方式来切换`class`: + +```vue + + + + + +``` + +**绑定数组:** +也可以将其修改为数组的形式: + +```vue + + + +``` + +`:class`指令可以也和一般的`class`属性共存: + +```vue +

{{ name }}

+``` + +#### 2.Style 绑定 + +`style`与对象绑定的使用方法与`class`相同: + +```vue + + + +``` + +`style`同样也可以与数组绑定,但其用处与对象绑定重合度较高且意义不大,这里就不在进行赘述。 + +### 三、表单输入绑定 + +#### 1.v-model 指令 + +在前端处理表单数据时,我们往往需要将用户在表单框中输入的内容同步给 JavaScript 中相应的变量。手动连接值绑定和更改事件监听器是一件很麻烦的事情,而 Vue 为我们提供的`v-model`指令可以帮助我们优雅地解决这个问题。 + +下面我们依旧以一段简单的代码为例进行讲解: + +```vue + + + +``` + +这里我们使用`v-model`指令把表单与`name`进行绑定,当我们在表单中输入内容时,下方的`name`也会实时更新,与我们所输入的内容保持一致。 + +简单点的理解就是`v-bind`绑定属性,属于单向绑定,而`v-model`则属于双向绑定,修改任何一边都会同步到另外一边。 + +#### 2.v-model 修饰符 + +`v-model`指令为我们提供了以下几种修饰符: + +`.laze` + +默认情况下,`v-model`会在每次`input`事件后更新数据,我们可以添加`.lazy`修饰符来改为在每次`change`事件后更新数据。这里的`change`事件我们可以简单理解为其失去焦点或者我们按下 Enter 键。 + +`.number` + +强制将用户输入的内容转换为数字类型,这样我们的属性值就会始终是一个数字。但要注意的是该修饰符只会尝试将用户输入的值转换为数字类型。如果用户输入的值无法转换为有效的数字,那么属性的值将保持为 NaN(非数字)。 + +`.trim` + +自动去除用户输入值的首尾空格。 + +### 四、侦听器 + +侦听器的作用是侦听页面中响应式数据的变化,这些数据一旦发生变化,侦听器就会侦听到,从而进行一系列我们想要的逻辑操作。而所谓的响应式数据,我们可以简单理解为我们在`data`中声明、被 {{ }} 绑定的数据。 + +让我们以下面的代码为例详细讲解: + +```vue + + + +``` + + +我们一般把侦听函数放在与`data`同级的`watch`中,且侦听函数的函数名必须要与其侦听的数据名相同,例如我们这里的`name()`函数的作用就是侦听`name`的变化。同时侦听函数可以使用两个参数分别表示数据变化后的新值和变化前的旧值。 + +当我们点击按钮后,“喷火龙”mega进化为“mega喷火龙X”,`name()`函数侦听到这一变化,开始执行,将`name`的新值和旧值分别打印出来。 + +### 五、模版引用 + +#### 1.引子 + +在讲模版引用之前,我们先回顾一下目前已经掌握的对 DOM 的几种操作: + +- 改变内容:使用 {{ }} 模版语法; +- 改变属性:使用`v-bind`指令; +- 绑定事件:使用`v-on`指令; + +可以看到,目前为止,我们对于 DOM 的操作,都是通过 Vue 为我们提供的方案来实现的。虽然这几种方法已经基本满足了我们对于 DOM 操作的需求,但如果在某些特殊的情况下我们依旧想要直接地去操作 DOM,我们可以通过模版引用的方式。 + +#### 2.模版引用获取 DOM 操作 + +想要实现直接访问底层 DOM 元素,我们可以使用特殊的`ref`属性。`ref`属性允许我们在一个特定的 DOM 元素或子组件实例被挂载后,获得对它的直接引用。在挂载结束后,引用都会被暴露在`this.$refs`之上,下面给出代码示例: + +```vue + + + +``` + + +可以看到,我们给 div 标签添加了`ref = "container"`时,当该标签被挂载后,我们可以直接使用`this.$refs.container`获取相应的 DOM 节点(注意此处的写法,不要漏掉 $ 符号和 s),将该组件打印出来,并修改其文本内容。而此处的`innerHTML`就是原生 JS 里的属性,同样,通过这种方式我们可以实现以前我在原生 JS 中的所有操作。 + +需要注意的是,我们只有在组件挂载后才能访问模版引用,而如果我们在模版中的表达式上访问`this.$refs.container`,那么在初次渲染时会是`undefined`。这是因为在初次渲染前这个元素还不存在。 diff --git "a/blogs/frontEnd/Vue \345\255\246\344\271\240\347\254\224\350\256\260/Vue\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\344\272\214\357\274\211\357\274\232\344\272\213\344\273\266\345\244\204\347\220\206\343\200\201\344\272\213\344\273\266\344\274\240\345\217\202\343\200\201\344\277\256\351\245\260\347\254\246\343\200\201\346\225\260\347\273\204\345\217\230\345\214\226\344\276\246\346\265\213.md" "b/blogs/frontEnd/Vue \345\255\246\344\271\240\347\254\224\350\256\260/Vue\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\344\272\214\357\274\211\357\274\232\344\272\213\344\273\266\345\244\204\347\220\206\343\200\201\344\272\213\344\273\266\344\274\240\345\217\202\343\200\201\344\277\256\351\245\260\347\254\246\343\200\201\346\225\260\347\273\204\345\217\230\345\214\226\344\276\246\346\265\213.md" new file mode 100644 index 00000000..756dbd0b --- /dev/null +++ "b/blogs/frontEnd/Vue \345\255\246\344\271\240\347\254\224\350\256\260/Vue\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\344\272\214\357\274\211\357\274\232\344\272\213\344\273\266\345\244\204\347\220\206\343\200\201\344\272\213\344\273\266\344\274\240\345\217\202\343\200\201\344\277\256\351\245\260\347\254\246\343\200\201\346\225\260\347\273\204\345\217\230\345\214\226\344\276\246\346\265\213.md" @@ -0,0 +1,356 @@ +--- +title: Vue笔记 +date: 2024/9/16 +categories: + - fe +author: aoxuexinghuo +tags: + - Vue + - 手写笔记 + - 前端框架 +--- +## Vue学习笔记(二):事件处理、事件传参、修饰符、数组变化侦测 + +[TOC] + +### 一、事件处理 + +在 Vue 中我们可以使用 `v-on` 指令来监听 DOM 事件,并在事件触发时执行对应的 JavaScript。此外,`v-on` 指令可以缩写为 @ 符号。 + +具体用法为:`v-on: click = "handler"`或者`@click = "handler"`。 + +事件处理器 (handler)的值可以是内联事件处理器,也可以是方法事件处理器。 + +#### 1.内联事件处理器 + +内联事件处理器是指事件被触发时执行的内联 JavaScript 语句 (与 `onclick` 类似),通常用于简单场景: + +```vue + + + +``` + +#### 2.方法事件处理器 + +方法事件处理器是一个指向组件上定义的方法的属性名或是路径,能够更加灵活地处理一些较为复杂的问题。 + +一般我们将所有的方法或者函数都放在与`data`同级的`methods`中,通过`this`读取`data`中的数据: + +```vue + + + +``` + +### 二、事件传参 + +事件参数可以获取`event`对象和通过事件传递数据,Vue 中的`event`对象与原生 JS 中的`event`类似 + +#### 1.获取 event 对象 + +```vue + + + +``` + + + +#### 2.传递参数 + +除了直接绑定方法名,我们还可以在内联事件处理器中调用方法。这允许我们向方法传入自定义参数以代替原生事件: + +```vue + + + +``` + + +当我们用自定义参数代替原生事件后,如果我们还想要获取`event`,不能在参数后直接添加`event`,而是需要在`event`前添加一个**$**符号: + +```vue + + + +``` + +### 三、修饰符 + +#### 1.事件修饰符 + +在处理事件时调用`event.preventDefault()` 阻止默认事件或`event.stopPropagation()` 阻止事件冒泡是很常见的。尽管我们可以直接在方法内调用,但如果方法能更专注于数据逻辑而不用去处理 DOM 事件的细节会更好。 + +为解决这一问题,Vue 为`v-on`提供了事件修饰符。修饰符是用 `.` 表示的指令后缀,例如以下这些: + +`.stop` 单击事件将停止传递 + +`.prevent` 提交事件将不再重新加载页面 + +`.self` 只有在事件是从绑定的元素本身触发时才触发处理器。 + +`.once` 确保事件处理程序最多只触发一次 + +`.passive` 提升事件的性能,尤其是滚动事件。 + +下面以`.stop`为例,阻止事件冒泡: + +```vue + + + +``` + + +当我们点击“测试冒泡”时,只打印了 P,而没有打印外层的 DIV,说明阻止冒泡成功。 + +同时修饰语既可以采用链式书,写也可以只有修饰符 : + +```vue + + + + +
+``` + +#### 2.按键修饰符 + +在监听键盘事件时,我们经常需要检查某些特定的按键。Vue 允许我们在`v-on`或`@`监听按键事件时 + +添加按键修饰符,同时为一些常用的按键提供了别名: + +`.enter` + +`.tab` + +`.delete` (捕获 “Delete” 和 “Backspace” 两个按键) + +`.esc` + +`.space` + +`.up` + +`.down` + +`.left` + +`.right` + +下面以`.enter`为例,只有当 key 为 “Enter” 时,才会调用 “submit”: + +```vue + + + +``` + +除了上述按键修饰符外,还存在四个特殊的系统按键修饰符: + +`.ctrl` + +`.alt` + +`.shift` + +`.meta` + +系统按键修饰符和常规按键的区别在于:与`keyup`事件一起使用时,该按键必须在时间发出时处于按下状态。也就是说,`keyup.ctrl`只会在你仍然按住`ctrl`但松开了另一个键时被触发。若单独松开`ctrl`键将不会触发。这一点,大家在日常使用电脑的过程中应该也都深有体会。 + +```vue + + + +
Ctrl + 点击
+``` + +#### 3.鼠标按键修饰符 + +鼠标按键修饰符有一下三种: + +`.left` + +`.right` + +`.middle` + +这些修饰符将处理程序限定为由特定鼠标按键触发的事件。具体用法与前文类似,这里就不在赘述。 + +### 四、数组变化侦测 + +#### 1.变更方法 + +Vue 能够侦听响应式数组的变更方法,并在他们被调用时触发相关的更新。这些变更方法包括: + +`push()` + +`pop()` + +`shift()` + +`unshift()` + +`splice()` + +`sort()` + +`reverse()` + +也就是说,当我使用上述这些变更方法时,UI 可以自动被实时更新,当数组发生变化,UI 便会产生相应的响应。下面我们来举例说明: + +```vue + + + +``` + +![img](https://i-blog.csdnimg.cn/blog_migrate/760d538b4d7aee93f7d5e5696e675861.png) + + +可以看到,当我们点击按钮时,`names`数组被添加了一个元素,而 UI 界面也发生了变化,将新加入的元素渲染了出来。 + +#### 2.替换方法 + +变更方法会对调用他们的原数组进行变更。相对的,也有一些不可变方法:`filter()`,`concat()`和`slice()`,这些都不会更改原数组,而是返回一个新的数组,不会引起 UI 的变化。 + +例如,我们将上文的`addList`修改为如下: + +```javascript + addList() { + console.log(this.names.concat("皮卡丘")); + console.log(this.names) + } +``` +![img](https://i-blog.csdnimg.cn/blog_migrate/f31ac612660e5b7ef46af5e6d923eb3c.png) + +![img](https://i-blog.csdnimg.cn/blog_migrate/c21aa58ead6a113722125e73e2cf132c.png) + +我们可以看到按下按钮后,我们得到了一个新的数组,而原数组并没有发生变化,UI 也没有更新。 + +特别的,如果我们在使用`concat()`时想要原数组也发生变化,可以通过给原数组赋值的方式实现: + +```javascript +this.names = this.names.concat("皮卡丘"); +``` + diff --git "a/blogs/frontEnd/Vue \345\255\246\344\271\240\347\254\224\350\256\260/Vue\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\344\272\224\357\274\211\357\274\232\346\267\261\345\205\245\344\272\206\350\247\243\347\273\204\344\273\266\357\274\210\344\270\213\357\274\211.md" "b/blogs/frontEnd/Vue \345\255\246\344\271\240\347\254\224\350\256\260/Vue\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\344\272\224\357\274\211\357\274\232\346\267\261\345\205\245\344\272\206\350\247\243\347\273\204\344\273\266\357\274\210\344\270\213\357\274\211.md" new file mode 100644 index 00000000..0fbd8488 --- /dev/null +++ "b/blogs/frontEnd/Vue \345\255\246\344\271\240\347\254\224\350\256\260/Vue\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\344\272\224\357\274\211\357\274\232\346\267\261\345\205\245\344\272\206\350\247\243\347\273\204\344\273\266\357\274\210\344\270\213\357\274\211.md" @@ -0,0 +1,423 @@ +--- +title: Vue笔记 +date: 2024/9/16 +categories: + - fe +author: aoxuexinghuo +tags: + - Vue + - 手写笔记 + - 前端框架 +--- +## Vue学习笔记(五):深入了解组件(下) + +[TOC] + +### 一、组件事件($emit) + +在组件的模版表达时候中,我们可以直接使用`$emit`方法触发自定义事件,触发自定义事件的目的一般是组件之间传递数据。可是在上一篇博客中我们讲到的`Props`的作用就是数据传递,为什么我们这里还要讲`$emit`呢? + +实际上,在`Props`的内容里我们也提到过,那就是其只能用于父组件向子组件传递数据,而`$emit`能够实现子组件向父组件传递数据。 + +依旧是两个父子嵌套关系的文件: + +**Parent:** + +```vue + + + +``` + +**Child:** + +```vue + + + +``` + +我们首先在 Child 文件中给按钮的`click`事件绑定一个`clickEventHandle()`函数,在函数中使用`this.$emit`的方式将自定义事件`someEvent`传递给 Parent(注意这里我们可以选择使用两个参数,第二个参数用于额外的数据传递,可以不加)。然后我们就可以在 Parent 中以``的方式将接收到的自定义事件与正常函数绑定使用了。 + +此外,我们需要在子组件添加`emits`选项来声明自定义事件的名称,否则控制台会出现警告。 + +### 二、组件与 v-model + +在前面的学习中我们已经了解了`v-model`在单个元素中的使用,其双向绑定的功能可以帮助我们轻松实现实时读取用户在输入框内输入的数据并将其同步显示出来。但如果用户输入的地方和我们想要显示或使用数据的地方不在同一个组件中,我们又该怎么解决这种跨组件的问题呢? + +**Show:** + +```vue + + + +``` + +**Search:** + +```vue + + +``` + +![img](https://i-blog.csdnimg.cn/blog_migrate/4947fd680a2e0d35bcc9d2826db448b6.png) + + +这里我们实现的功能是在 Search 组件中输入数据然后在 Show 组件中将其实时显示出来。下面我们对整个过程详细解释: + +首先我们在 Search 组件中使用`v-model`指令将 input 组件与`Text`双向绑定,为数据`Text`设置一个监听函数,每当`Text`内容更新时,就会触发监听函数,将变化后的新值通过`$emit`传递给Show组件,Show 组件每次接收到全新的`Text`值就会触发我们的自定义事件,将对自己的`Text`进行更新,将其渲染在网页上。这里我们巧妙的借助了监听函数与自定义事件的结合,实现了数据的跨组件实时传递功能。 + +### 三、组件数据传递 + +前面我们讲到关于数据传递的内容有: + +- 父组件给子组件传递数据:采用`props` + +- 子组件给父组件传递数据:采用自定义事件 + +除了自定义事件能够实现子传父之外,我们还可以使用`props`。咳咳,是的,你没看错,就是`props`。虽然`props`不能够直接实现子传父,但是我们可以借助回调函数实现这一功能。前面关于`props`的内容我们讲到,`props`传递的可以是字符串、数组、对象,实际上,他还能够传递函数,由于函数是能够携带参数的,借助这一特点,我们便能够实现子传父。下面给出示例代码: + +**Parent:** + +```vue + + + +``` + +**Child:** + +```vue + + + +``` + +### 四、透传 Attributes + +#### 1.透传 Attributes 的使用 + +透传 Attributes 指的是以类似于继承的方式将一个属性或`v-on`事件监听器传递给子组件。这要求继承该内容的组件只能以单个根元素作渲染。例如我们存在下面这样一个以单元素为根的组件: + +```vue + + + +``` + +当其父元素以``使用该组件时,相当于为其唯一的根元素传递了一个`class`属性,从而使 CSS 样式生效,字体颜色变为粉色。 + +但如果子组件存在多个根元素,继承则不会生效,例如我们为上面的代码再添加一个`

`标签: + +```vue + +``` + +此时,CSS 样式不会对任何一个元素生效,字体颜色都为默认的黑色。 + +#### 2.禁用透传 Attributes + +如果我们不想要一个组件自动地继承`attribute`,可以在组件选项中设置:`inheritAttrs: false`。 + +```vue + +``` + +实际上,我们在日常中很少为用到透传 Attributes,一般情况下也不建议大家通过这种方式来为组件元素设置属性。 + +### 五、插槽 Slots + +#### 1.插槽的使用 + +前面我们了解到`props`能够用于接收任意类型的 JavaScript 的值,但如果我们想要传递的是一些 HTML 片段呢?这时我们就需要借助插槽了。具体使用方式来看下面的示例代码: + +**Parent:** + +```vue + + + +``` + +**Child:** + +```vue + +``` + +这里我们将原本的``单标签修改为双标签,在里面写下我们需要传递的 HTML 片段。然后我们就可以在 Child 以``的方式使用该片段。这里的``元素是一个插槽出口,标示了父元素提供的插槽内容将会在哪里被渲染,我们可以自行为其选定位置,也可以多次使用。下面这张来自官网的图片也能够帮我们更加具体的了解插槽的使用原理: + +![img](https://i-blog.csdnimg.cn/blog_migrate/fac938cd2c14e6eb2520f411fdf70f20.png) + +#### 2.渲染作用域 + +插槽的内容可以访问到父组件的数据作用域,因为插槽内容本身是在父组件模版中定义的: + +**parent:** + +```vue + + + +``` + + +简单来说就是当我们需要在插槽内添加动态数据时,应该把数据内容写在父组件中,而不是子组件。 + +#### 3.插槽默认值 + +我们在子组件中使用插槽时,可以为其设置默认值,当父组件没有传递插槽内容或传递内容为空时,子组件中的插槽部分就会显示默认值的内容,否则正常显示来自父组件的插槽内容,实现方式也很简单,直接写在标签中间即可: + +```vue +插槽默认值 +``` + +#### 4.具名插槽 + +如果我们想要传递多个不同的插槽,可以通过为插槽起名字的方式,借助`v-slot`指令实现将不同的内容传递给对应名字的插槽: + +**Parent:** + +```vue + + + +``` + +**Child:** + +```vue + +``` + +我们在 Child 中通过`name`属性为不同的插槽取名,然后在 Parent 中就可以使用`v-slot`指令将对应的片段传递给相应名字的插槽,这里的`v-slot:`必须写在`