Vue官方文档
参考资料
学习目标
Learning Outcomes
掌握 Vue 3 核心概念(响应式、组件化)
理解选项式 API 和组合式 API 的区别
基础
创建一个应用
应用需要一个 根组件 App.vue
|
|
然后通过 createApp 创建一个 应用实例
|
|
|
|
应用实例需要进行挂载才能被渲染
.mount() 将实例挂载在 CSS 选择器字符串 ‘#app’ 对应的 DOM 元素 div 上
可以对应用实例注册组件
注册后,该组件在应用的任何地方都是可用的
|
|
createApp 允许在同一个页面中创建多个共存的 Vue 应用,而且每个应用都拥有自己的用于配置和全局资源的作用域
模板语法
Vue 的模板基于 HTML,可以声明式地进行数据绑定和逻辑控制
-
文本插值
1<p>Count: {{ count }}</p>双大括号内支持 js 表达式(如
{{ count + 1 }}),但不支持语句(如if语句)
当 count 属性的值变化的时候,会同步更新 -
原始 HTML 绑定
1<p v-html="rawHtml"></p>注意动态渲染 HTML 容易导致 XSS 攻击,需要确保内容可信
-
属性绑定
1 2 3 4<div v-bind:id="dynamicId"></div> <!-- 或者简写 --> <div :id="dynamicId"></div>-
动态绑定多个属性
1<div v-bind="{ id: dynamicId, class: 'active' }"></div>等价于
1<div :id="dynamicId" class="active"></div>
-
-
绑定 js 表达式
如果一个 js 表达式可以合法地写在 return 后面,则可以进行数据绑定或者属性绑定1 2 3{{ number + 1 }} {{ ok ? 'YES' : 'NO' }} <div :id="`list-${id}`"></div>注意如果绑定了一个 js 方法,该方法在组件每次更新时都会被重新调用
-
指令(Directives)
| 指令 | 作用 | 示例 |
|---|---|---|
v-if |
条件渲染(销毁/重建 DOM) | <p v-if="show">Hello</p> |
v-show |
切换 display: none |
<p v-show="show">Hello</p> |
v-for |
列表渲染 | <li v-for="item in items" :key="item.id">{{ item.text }}</li> |
v-on |
事件绑定 | <button @click="handleClick">Click</button> |
v-model |
表单双向绑定 | <input v-model="message"> |
v-if 适合切换频率低的场景(性能开销大)
v-show 适合频繁切换(初始渲染开销大)
v-for必须提供唯一:key,避免渲染错误
绑定多个属性的常见应用
-
批量设置元素属性
1<input v-bind="formInputAttrs" />1 2 3 4 5 6 7 8 9data() { return { formInputAttrs: { type: 'text', placeholder: 'Enter your name', class: 'form-control' } } } -
批量传递组件 props
1<child-component v-bind="childProps"></child-component>1 2 3 4 5 6 7 8data() { return { childProps: { title: 'Hello', content: 'World' } } }
响应式基础
ref
使用 ref() 函数来声明响应式状态
|
|
注意到 ref 对象含有 value 属性,需要通过 .value 访问
但是在模板中使用时会自动解包,无需 .value
若变量和方法很多,在 setup() 函数中手动暴露会变得非常繁琐
而在单文件组件中使用 <script setup> 可以简化这个过程
|
|
推荐使用单文件组件 + <script setup> 的语法
-
为什么要使用 ref?
这与 Vue 的响应式系统的工作方式有关
当使用 ref 函数声明一个 ref 对象后,该对象的值若发生了改变,Vue 会自动检测到这个变化,并且相应地更新 DOM在标准的 JavaScript 中,检测普通变量的访问或修改是行不通的
在 Vue 中我们可以通过 getter 和 setter 方法来拦截对象属性的 get 和 set 操作.value 属性给予了 Vue 一个机会来检测 ref 何时被访问或修改
在其内部,Vue 在它的 getter 中执行追踪,在它的 setter 中执行触发还可以将 ref 对象传递给函数,同时保留对最新值和响应式连接的访问
-
深层响应性
1 2 3 4 5 6 7 8 9 10 11import { ref } from "vue"; const obj = ref({ nested: { count: 0 }, arr: ["foo", "bar"], }); function mutateDeeply() { obj.value.nested.count++; obj.value.arr.push("baz"); }ref 使得上述的 obj 具有深层响应性。这意味着即使改变嵌套对象或数组时,变化也会被检测到
也可以通过ShallowRef来放弃深层响应性,用于优化性能,减少对大型数据的响应性开销 -
DOM 更新时机
DOM 更新不是同步的,Vue 会在“next tick”更新周期中缓冲所有状态的修改,以确保不管你进行了多少次状态修改,每个组件都只会被更新一次
常常使用 nextTick() 等待 DOM 更新完成,再执行额外的代码1 2 3 4 5 6 7import { nextTick } from "vue"; async function increment() { count.value++; await nextTick(); // 现在 DOM 已经更新了 } -
模板中的解包问题
在模板渲染上下文中,只有顶级的 ref 属性才会被解包1 2const count = ref(0); const object = { id: ref(1) };上述的 count 和 object 是顶级属性,但 object.id 不是
1 2 3 4 5{{ count + 1 }} <!-- 1 --> {{ object.id + 1 }} <!-- [object Object]1 -->为了解决这个问题,我们可以将 id 解构为一个顶级属性
1const { id } = object;1 2{{ id + 1 }} <!-- 2 -->
计算属性
推荐使用计算属性来描述依赖响应式状态的复杂逻辑
也防止在模板中重复多次相同的计算
|
|
computed() 返回值为一个计算属性 ref 对象
Vue 的计算属性会检测到 publishedBooksMessage 依赖于 author.books
所以当 author.books 改变时,任何依赖于 publishedBooksMessage 的绑定都会同时更新
当然我们在表达式中调用类似的函数(判断 author.books 的长度返回布尔值),其结果与计算属性是一模一样的
不同之处在于:计算属性值会基于其响应式依赖被缓存,仅会在其响应式依赖更新时才重新计算
故只要 author.books 不改变,无论多少次访问 publishedBooksMessage 都会立即返回先前的计算结果,而不用重复执行
而函数调用总是会在 重渲染发生时 再次执行
可以把计算属性的值看作是一个“临时快照”,每当源状态发生变化时,就会创建一个新的快照
更改快照是没有意义的,因此不应该去修改计算属性的返回值
js 的 reverse () 方法就地反转数组中的元素,并返回同一数组的引用,sort 也是同理
如果在计算属性中使用这些方式,记得考虑是否需要创建一个原数组的副本
创建可写计算属性
计算属性默认是只读的,但是可以通过 getter 和 setter 来实现可写
|
|
之后若执行 fullName.value = ‘xxx xxx’ 时,相应的 firstName 和 lastName 都会更新
类与样式绑定
常规写法:
|
|
|
|
渲染结果为
|
|
当响应式变量 isActive 或者 hasError 改变时,class 会随之更新
也可以写成对象的形式再绑定在 div 上
|
|
还可以通过计算属性来处理逻辑
|
|
样式的绑定也是类似的
|
|
条件渲染
|
|
| v-if | v-show |
|---|---|
| 指令所在的元素会被销毁与重建 | 指令所在的元素仍保留在 DOM 中,仅切换了该元素上的 display 属性 |
可以在 <template> 元素上使用,实现同时切换多个元素 |
不支持在 <template> 元素上使用 |
| 如果开始时条件值为 false,则不会做任何事。只有当条件首次变为 true 时才进行渲染 | 元素始终会被渲染,只有 CSS display 属性会被切换 |
| 切换开销高 | 初始化渲染开销高 |
如果需要频繁切换,则使用 v-show 较好;如果在运行时绑定条件很少改变,则 v-if 会更合适
列表渲染
v-for 遍历列表 items
第二个参数表示当前项的位置索引
|
|
v-for 也可以遍历对象
|
|
|
|
当列表的顺序改变时,Vue 不会随之移动 DOM 元素的顺序,而是 就地更新 每个元素,在原本指定的索引位置上渲染元素
通过指定 key,给 Vue 一个提示以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素
key 应该是唯一的
事件处理
|
|
|
|
将 greet 方法绑定在按钮上,event.target 可以访问到所绑定的 DOM 元素
事件修饰符
- 监听键盘、鼠标事件
表单输入绑定
利用 v-model 指令简化 值 和 事件 的绑定操作
也即双向绑定
|
|
|
|
v-model.trim="msg" 会自动去除用户输入内容中两端的空格
侦听器
watch 函数会在每次响应式状态发生变化时触发回调函数
第一次参数可以是 ref 对象、getter 函数或者多个来源组成的数组
假设要对下面的响应式对象进行监听
|
|
|
|
之所以不行,是因为传给 watch 函数的 obj.count 是个 number,而非响应式对象
考虑使用 getter 函数返回该属性值
|
|
如果直接对整个 obj 响应式对象进行监听:
|
|
发现不会有内容打印出来,因为 newValue 和 oldValue 始终是相等的,它们是同一个对象
注意
避免在侦听器中修改监听的数据,可能导致循环更新
不能直接侦听响应式对象的属性值,由上可知,需要使用 getter 函数
-
深层侦听器
添加deep: true参数1 2 3 4 5 6 7watch( () => state.someObject, (newValue, oldValue) => { // 。。。 }, { deep: true } );
还有 immediate: true 参数,能让侦听器创建时,立即执行一遍回调
(默认是等到监听对象变化时,才会执行回调)
once: true 参数让侦听器只触发一次
模板引用
给一个 DOM 元素添加 ref 属性,可以在该元素被挂载后,获得对它的直接引用
|
|
注意只可以在组件挂载后才能访问模板引用,否则获取到的引用为 null
模板引用也可以被用在一个子组件上,父组件对子组件的每一个属性和方法都有完全的访问权
但是多数情况下,应该首先使用标准的 props 和 emit 接口来实现父子组件交互
组件基础
每一个组件都维护着自己的状态。即使是相同的组件,但也是不同的实例
在单文件组件中,推荐使用 PascalCase 形式为子组件命名,以此来和原生的 HTML 元素作区分
若不是单组件,则需要遵从浏览器中 HTML 的解析行为,使用 kebab-case 形式并显式地关闭组件的标签
假设有两个 vue 单文件,blogHomePage.vue 和 BlogPost.vue
其中 blogHomePage.vue 作为父组件调用 BlogPost.vue
|
|
上述的 defineProps 是一个仅 <script setup> 中可用的编译宏命令,并不需要显式地导入
声明的 props 会自动暴露给模板
如果没有使用 <script setup>,props 必须以 props 选项的方式声明
|
|
注意:Props 是 单向数据流,子组件不能直接修改
父组件中多次调用子组件
|
|
现在需要让父组件可以控制子组件内容的字体大小
父组件添加一个响应式 ref 对象表示字体大小,并给子组件添加 enlarge-text 事件,以监听子组件上抛的事件
|
|
给子组件添加一个按钮,点击按钮会通知父组件更新 postFontSize
defineEmits 所定义的 emit 发送信号给父组件
|
|
父组件如果要传递内容到子组件中,可以在子组件中利用 <slot> 元素进行占位
常用生命周期
| 选项式 API | 组合式 API | 触发时机 |
|---|---|---|
created |
setup() |
实例创建后 |
mounted |
onMounted |
DOM 挂载完成 |
updated |
onUpdated |
数据变更导致 DOM 更新后 |
unmounted |
onUnmounted |
组件销毁时 |
深入组件
组件注册
- 全局注册
|
|
- 局部注册
|
|
Props
-
使用一个对象绑定多个 prop
1 2 3 4const post = { id: 1, title: "My Journey with Vue", };1 2 3 4 5<BlogPost v-bind="post" /> <!-- 等价于 --> <BlogPost :id="post.id" :title="post.title" /> -
单向数据流
props 遵循单向绑定原则
每次父组件更新后,所有的子组件中的 props 都会跟着更新到最新值
props 自然地将新的状态向下流往子组件,而不会逆向传递
避免了子组件意外修改父组件的状态的情况
所有 prop 默认都是可选的,除非声明了 required: true
组件事件
前面说到父组件可以通过 @xxx 监听子组件触发的事件
子组件通过 $emit 触发该事件
$emit 函数中也可以传递参数
|
|
|
|
vue 父组件和子组件
|
|
|
|
| 问 | 产生 | 解决思路 |
|---|---|---|
tobeModifyData、modifyBy 初始为 null |
父组件在子组件渲染前还在异步获取数据(如接口请求) | ① 在子组件使用 v-if 等待数据准备好;② 为 props 设置 默认值;③ 在父组件先给一个空对象/字符串占位。 |
子组件内部 formData 只读,无法修改后同步回父组件 |
computed 只实现了 get,没有 set,且 props 本身不可变 |
为 computed 添加 set 并在内部 emit 更新;或直接在 data 中维护本地副本。 |
handleModify 调用 modifyVendorFileData() 时没有传递要修改的内容 |
API 需要参数,但你只调用了空函数 | 把 this.formData(或需要的字段)作为参数传进去。 |
父组件通过 ref 调用子组件方法时,子组件未在 mounted 前渲染 |
父组件在 created/mounted 时立即调用 showContent,但子组件可能还未挂载 |
在父组件中使用 nextTick 或在子组件内部提供 打开对话框的公开方法,并在父组件确认子组件已挂载后再调用。 |
- 本地副本
localForm:避免直接修改props(只读),编辑时操作副本,提交后通过update:tobeModifyData把最新值同步回父组件。 watch+immediate:父组件首次把tobeModifyData传进来时立即填充localForm,解决“初始为null报错”。.sync用法:在父组件里写:tobe-modify-data.sync="tobeModifyVendor",子组件内部只要this.$emit('update:tobeModifyData', newValue)就能自动更新父组件的变量。- API 调用:把编辑后的表单对象
this.localForm作为参数传给modifyVendorFileData,确保后端能收到正确的数据。 - 错误提示:统一使用
this.$message,并在finally中关闭 loading。
这样写既符合 Vue 官方推荐的单向数据流,也能确保 父子组件数据同步,并且避免了 null 报错。
逻辑复用
组合式函数
为了在不同地方格式化时间,我们可能会抽取一个可复用的日期格式化函数,这是复用 无状态逻辑
“组合式函数”(Composables) 是一个利用 Vue 的组合式 API 来封装和复用 有状态逻辑 的函数
例如跟踪当前鼠标在页面中的位置
|
|
|
|
使用上述封装好的组合式函数
它们一般以 use 开头
|
|
在选项式中使用组合式函数,需要在 setup() 钩子中调用
|
|
自定义指令
custom directives
下面自定义一个指令:当 Vue 将元素插入到 DOM 中后,会将指定 class 添加到元素中
|
|
只有当所需功能只能通过直接的 DOM 操作来实现时,才应该使用自定义指令
内置组件
Transition
|
|
一共有 6 个应用于进入与离开过渡效果的 CSS class
上面指定了 name=“slide-up” 作为 Transition 的过渡效果名
指定 mode=“out-in” 可以使得先执行 离开动画,然后在其完成之后再执行元素的 进入动画
KeepAlive
默认情况下,一个组件实例在切换时会被销毁
当这个组件再一次被显示时,会创建一个带有 初始状态的新实例,原有变化的状态会丢失
而 KeepAlive 就是用于在多个组件间动态切换时 对组件实例进行缓存
选项式
创建应用
|
|
-
挂载应用
将上述创建的应用 myapp 挂载到 id 为 app 的元素上1 2 3<div id="app"></div>; myapp.mount("#app"); -
多个应用实例
可以在同一个页面中创建多个共存的应用
每个应用都拥有自己的 配置以及资源 的作用域1 2 3 4 5 6 7 8 9const app1 = createApp({ // ... }); const app2 = createApp({ // ... }); app1.mount("#container1"); app2.mount("#container2");当我们想用 Vue 去控制一个大型页面中的特定一小部分时
可以创建多个小的应用实例,然后分别将它们挂载到所需的元素上去
模板语法
Vue 模板都是语法层面合法的 HTML
Vue 会将模板编译成高度优化的 JS 代码
-
文本插值
双括号法(mustache 语法)用于渲染动态文本1<p>信息:{{ msg }}</p>msg 是相应组件实例中的变量,双大括号会将变量值解释为 纯文本
双括号中可以编写 js 代码、路径、标识符(给类、方法等起的名字) 等
-
插入原始 HTML
1 2 3 4<p> 插入一段 HTML 内容: <span v-html="myhtml"></span> </p>上述
v-html属性被称为一个 指令[^指令]
v-的前缀表示它是 Vue 特殊的属性需要确保 HTML 内容是安全可信的,才能使用
v-html属性(避免 XSS 漏洞)
属性绑定
给元素的 attribute 绑定一个动态值
-
为元素 div 的 id 属性响应式地绑定为 dynamicId
1 2 3 4<div v-bind:id="dynamicId"></div> <!-- 简写 --> <div :id="dynamicId"></div>v-bind:id="null"给 id 绑定上 null 字符串
用于移除标签的 id 属性 -
为 disabled 属性绑定上一个 布尔类型 的变量
用于控制按钮是否被禁用1<button v-bind:disabled="isBtnDisabled">按钮</button> -
通过 不带参数的形式,将一个包含多个键值对的 js 对象 stu 绑定到元素 div 上
1<div v-bind="stu"></div>1 2 3 4 5const stu = { name: "Tom", age: "20", grade: "grade three", };-
结合 js 表达式绑定数据
1 2{{ number + 1 }} {{ ok ? 'YES' : 'NO' }} <div v-bind:id="`list-${id}`"></div>
-
响应式基础(选项式)
-
data 选项
用来声明组件的响应式状态
Vue 会在 创建新组件实例 的时候调用此函数
未准备好的值可以使用 null、undefined 赋值 -
methods 选项
是包含所有方法的对象
Vue 自动为 methods 中的方法绑定了 永远指向组件实例的 this注意避免使用 箭头函数 定义,因为箭头函数中,无法使用 this 获取组件实例
-
响应式渲染
也叫做 声明式渲染,能 在改变时触发更新 的状态被认为是响应式的
将视图与数据进行绑定,通过改变数据的状态来自动更新视图
计算属性
为了减少模板中的逻辑内容,推荐将逻辑判断写在计算属性中
|
|
-
计算属性和方法的区别
计算属性值会 缓存,在其响应式依赖更新时才重新计算
只要 books 数组的值没有发生变化,计算属性 BookMsg 始终返回先前的计算结果,不会重复执行
对于需要做很多计算且非常消耗性能的逻辑,推荐使用计算属性
而方法会在 重渲染 发生时执行计算属性默认是 只读 的
如果要修改计算属性,则要考虑为计算属性创建getter和setter函数
类与样式绑定
v-bind:class
|
|
v-bind:class 可以与一般的 class 属性共存,例如:
|
|
v-bind:style
|
|
条件渲染
v-if
|
|
v-else 元素必须跟在 v-if 或者 v-else-if 元素后面
否则不会被识别
如果 v-if 依附的元素不只一个,考虑使用 template 标签
|
|
v-show 也可以用来控制元素的渲染
区别是:v-show 仅切换了元素的 display css 属性值,并且不能在 template 标签上使用
v-show 更适合元素需要频繁切换的情况
列表渲染
v-for
|
|
v-for 支持多层嵌套
可以使用 of 替代 in 作为分隔符
同样支持使用 template 标签
v-for 和 v-if 配合使用:
|
|
- 唯一 key 标识
key 标识提示 Vue 跟踪每一个节点,从而重用和重新排序现有的元素
如果不传入 key,Vue 有默认模式
事件处理
v-on
监听 DOM 事件
|
|
接受一个内联 js 语句
或者组件上定义的一个方法
event 是 DOM 原生事件
|
|
事件修饰符
-
事件监听
-
事件冒泡(Bubbling)
在 DOM 树中,事件从最具体的元素(事件的实际目标)开始
然后逐级向上传播到较为不具体的节点(通常是 document 对象) -
事件捕获(Capturing)
与冒泡相反,事件从最不具体的节点(document 对象)开始
然后逐级向下传播到最具体的节点(事件的实际目标)
js 默认情况下,事件监听是在冒泡阶段触发的
-
.stop 阻止冒泡行为。即当前元素事件触发后,阻止事件继续向父元素传播
.prevent 用于阻止事件的默认行为。例如,阻止链接的跳转行为,阻止表单的提交行为等
.self 确保事件是由绑定的元素本身触发的才去执行函数。如果事件是由内部元素冒泡上来的,则会忽略
.capture 将 js 的监听阶段改为捕获阶段,事件从根节点向下传播到目标节点的阶段
.once 确保事件处理函数只执行一次
.passive 滚动行为会立即触发,而不需要等待事件处理函数执行完毕。可以提升移动端的性能
其中的 stop 和 self
stop 是阻止当前元素向外冒泡
self 是当前元素不受影响,但是内部的冒泡行为还会继续向外触发
二者作用的对象不一样
上述修饰符支持链式使用:
.click.prevent.once 表示仅阻止一次行为
但是需要注意调用顺序
-
应用
阻止表单的默认提交行为
使用 .prevent 修饰符可以确保页面不会刷新,内容不会丢失
然后使用自定义的 addTodo 方法来处理表单提交的内容1 2 3 4<form @submit.prevent="addTodo"> <input v-model="newTodo" required placeholder="new todo" /> <button>Add Todo</button> </form>
按键修饰符
.enter
.tab
.delete(捕获“Delete”和“Backspace”两个按键)
.esc
.space
.up
.down
.left
.right
.middle(鼠标按键)
|
|
-
系统按键
.ctrl
.alt
.shift
.meta1 2 3 4 5 6 7 8// 当用户按住 Ctrl 键的同时点击这个按钮时,会触发 doSomething <button v-on:click.ctrl="doSomething"></button> // 在用户松开其他键(比如字母键)但仍然按住 Ctrl 键的时候被触发 <div v-on:keyup.ctrl="doSomething"></div> // 如果想要监听 Ctrl 键被单独松开的事件,keyup.ctrl 无法满足 // 因为 keyup.ctrl 只有在其他键被松开的同时 Ctrl 键仍然被按住时才会触发 // 如果单独松开 Ctrl 键,不会触发 keyup.ctrl 事件 -
.exact修饰符1 2// 精确控制,仅按下 Ctrl 按键的时候才触发 <button v-on:click.ctrl.exact="doSomething"></button>
表单输入绑定
同时使用 v-bind 和 v-on 来在表单的输入元素上创建 双向绑定:
|
|
或者使用 v-model="text"
会自动根据所使用的元素和对应的 DOM 属性和事件结合
免去了麻烦的手动连接值绑定和更改事件监听器
比如对 input 标签进行绑定后,在输入框输入内容,text 值会与之同步
注意,在 input 标签中,v-model 无法监听 拼字阶段 的更新
例如中文日文韩文等等
这时候只能使用 value 绑定和 input 事件监听器
- 修饰符
.lazy 不会即时更新,仅在 change 事件后更新数据
.number 将用户输入内容转换为数字
.trim 将输入内容两端的空格去除
生命周期钩子
生命周期是指 Vue 实例从创建到销毁的过程
注意避免使用箭头函数定义生命周期钩子
箭头函数中,无法使用 this 获取组件实例
-
创建阶段
- created
在实例创建完成后被立即调用
此时,实例已完成数据观测、属性和方法的运算
$el 属性还未显示出来
- created
-
挂载阶段
- mounted
在组件 完成初次渲染并创建 DOM 节点 后调用
el 被新创建的 vm.$el 替换,并挂到实例上去之后调用该钩子
- mounted
-
更新阶段
- updated
在由于数据更改导致的虚拟 DOM 重新渲染和打补丁之后被调用
- updated
-
销毁阶段
- beforeDestroy
在实例销毁之前调用。在这一步,实例仍然完全可用 - destroyed
在实例销毁之后调用
调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁
- beforeDestroy
侦听器
watch 选项
侦听器是一种可以监听数据变化的工具
在每次响应式属性发生变化时,执行一些特定的操作
|
|
-
触发时机
默认情况下,侦听器回调是在
父组件更新之后;所属组件的 DOM 更新之前 执行的flush: ‘post’ 使得回调是在 所属组件的 DOM 更新之后 执行
flush: ‘sync’ 回调会在 任何更新之前 触发
模板引用
ref 属性访问底层的 DOM 元素
可以用它获取被挂载的实例对象
|
|
ul 是 unordered list(无序列表)的缩写
li 是 list item(列表项)的缩写
组件
使用子组件
|
|
原生 HTML 不区分标签名的大小写
而 Vue 单文件组件可以在编译中区分大小写
组件一般使用 kebab-case 的名字来引用
也可以使用 PascalCase 的方式
传递数据
-
父传子
props 选项
在子组件中通过 props 从父组件接受动态数据
在父组件中可以通过v-bind传入参数,以渲染子组件的内容父组件可以通过插槽将模板片段传递给子组件
子组件使用<slot>作为一个占位符
父组件传入的内容会被渲染在相应位置
子组件<slot>标签中的内容将被当作“默认”内容
它会在父组件没有传递任何插槽内容时显示 -
子组件抛出事件给父组件
emits 选项
父组件可以使用v-on监听子组件上抛的事件,更新对应的值
组件切换
|
|