免费建站网站一级大,个人视频制作公司,小程序商城如何运营,哪类公司做网站的最多1 Vue 3 组件的插槽
插槽#xff08;Slot#xff09;是Vue组件中的一个重要概念#xff0c;它允许父组件向子组件中插入HTML结构或其他组件#xff0c;从而实现内容的自定义和复用。以下是对Vue 3组件插槽的详细讲解#xff1a;
1.1 插槽的基本概念
插槽可以被视为子组…1 Vue 3 组件的插槽
插槽Slot是Vue组件中的一个重要概念它允许父组件向子组件中插入HTML结构或其他组件从而实现内容的自定义和复用。以下是对Vue 3组件插槽的详细讲解
1.1 插槽的基本概念
插槽可以被视为子组件中预留给父组件填充内容的占位符。在子组件中你可以使用slot标签来定义插槽而在父组件中你可以通过在该标签内部放置内容来填充这个插槽。
1.2 默认插槽匿名插槽
默认插槽是最简单的插槽类型它没有名字因此也被称为匿名插槽。在子组件中你只需要使用一个slot标签来定义它。在父组件中你可以直接在该标签内部放置需要插入的内容。
!-- 子组件 --
templatedivp我是子组件/pslot/slot !-- 默认插槽 --/div
/template!-- 父组件 --
templatedivChildComponentp这是父组件插入到子组件的内容/p/ChildComponent/div
/templatescript setup
import ChildComponent from ./ChildComponent.vue;
/script1.3 具名插槽
当子组件中有多个插槽时你可以使用具名插槽来区分它们。在子组件中你需要给slot标签添加一个name属性来指定插槽的名字。在父组件中你可以使用v-slot:插槽名简写为#插槽名来指定要填充哪个插槽。
!-- 子组件 --
templatedivp我是子组件/pslot nameheader/slot !-- 具名插槽 --slot namecontent/slot !-- 具名插槽 --slot namefooter/slot !-- 具名插槽 --/div
/template!-- 父组件 --
templatedivChildComponenttemplate #headerh1这是头部内容/h1/templatetemplate #contentp这是主体内容/p/templatetemplate #footerp这是底部内容/p/template/ChildComponent/div
/templatescript setup
import ChildComponent from ./ChildComponent.vue;
/script1.4 动态插槽名
Vue 2.6.0版本支持动态插槽名这意味着插槽名可以是一个变量你可以根据变量的值来动态地选择填充哪个插槽。在父组件中你可以使用v-slot:[动态插槽名]简写为#[动态插槽名]来实现这一点。
!-- 父组件 --
templatedivChildComponenttemplate #[currentSlotName]p这是动态插槽的内容/p/template/ChildComponentbutton clickchangeSlotName切换插槽/button/div
/templatescript setup
import { ref } from vue;
import ChildComponent from ./ChildComponent.vue;const currentSlotName ref(header);function changeSlotName() {currentSlotName.value currentSlotName.value header ? content : header;
}
/script1.5 作用域插槽
作用域插槽允许子组件向父组件传递数据以便父组件在填充插槽时使用这些数据。在子组件中你可以使用v-bind简写为:在slot标签上绑定数据。在父组件中你可以使用v-slot指令接收这些数据并根据需要进行处理。
!-- 子组件 --
templatedivslot :useruserData/slot/div
/templatescript setup
import { ref } from vue;const userData ref({name: 张三,age: 30
});
/script!-- 父组件 --
templatedivChildComponent v-slot:default{ user }p用户名{{ user.name }}/pp年龄{{ user.age }}/p/ChildComponent/div
/templatescript setup
import ChildComponent from ./ChildComponent.vue;
/script在这个例子中子组件通过作用域插槽向父组件传递了userData对象。父组件在填充插槽时接收了这个对象并使用了它的name和age属性。
1.6 插槽的默认内容
当父组件没有提供任何插槽内容时你可以为子组件的插槽指定默认内容。这可以通过在slot标签内部放置默认内容来实现。
!-- 子组件 --
templatedivp我是子组件/pslot这是默认内容/slot !-- 带有默认内容的插槽 --/div
/template!-- 父组件 --
templatedivChildComponent/ChildComponent !-- 没有提供插槽内容 --/div
/templatescript setup
import ChildComponent from ./ChildComponent.vue;
/script在这个例子中如果父组件没有提供任何插槽内容子组件将显示默认内容“这是默认内容”。
2 Vue 3 单文件组件
Vue 3单文件组件Single-File Components简称SFC是一种特殊的文件格式它允许开发者将Vue组件的模板Template、脚本Script和样式Style封装在同一个文件中从而提高代码的可维护性和可读性。以下是对Vue 3单文件组件的详细讲解
2.1 单文件组件的结构
每一个.vue文件都由三种顶层语言块构成template、script和style以及一些其他的自定义块。
template定义了组件的HTML结构。在Vue 3中模板语法得到了进一步的优化支持更多的指令和功能如条件渲染、列表渲染、事件处理等。script包含了组件的JavaScript逻辑。在这里可以定义组件的数据、方法、计算属性、生命周期钩子等。Vue 3引入了组合式APIComposition API使得逻辑复用和组件组织变得更加灵活。style用于定义组件的样式。Vue 3支持scoped属性使得样式只作用于当前组件避免了全局样式的污染。此外还可以使用CSS预处理器如Sass、Less等来编写更复杂的样式。
2.2 单文件组件的优点
模块化将组件的模板、脚本和样式封装在一起使得组件更加模块化易于维护和复用。语法熟悉使用熟悉的HTML、CSS和JavaScript语法来编写组件降低了学习成本。预编译模板Vue 3在构建阶段会对模板进行预编译避免了运行时的编译开销提高了性能。组件作用域的CSS通过scoped属性可以确保样式只作用于当前组件避免了全局样式的冲突。更好的IDE支持许多现代IDE都提供了对Vue单文件组件的良好支持包括语法高亮、自动补全、类型检查等功能。热更新HMR在开发阶段可以支持模块热替换Hot Module Replacement使得开发者可以在不刷新页面的情况下更新组件。
2.3 单文件组件的使用
创建组件使用Vue CLI或Vite等构建工具可以轻松地创建Vue 3单文件组件。这些工具提供了合理的默认配置并可以通过插件进行扩展。导入组件在父组件中可以使用import语句来导入子组件并在components选项中注册它。然后就可以在父组件的模板中使用这个子组件了。自定义块除了template、script和style之外.vue文件还可以包含其他自定义块。这些自定义块可以用于文档、国际化、类型定义等目的。自定义块的处理需要依赖工具链如Vite插件或Webpack loader等。
2.4 单文件组件的编译
在构建过程中Vue 3单文件组件会被编译为标准的JavaScript和CSS。具体来说
模板编译template中的内容会被提取出来传递给vue/compiler-dom进行预编译生成JavaScript渲染函数并附在导出的组件上作为其render选项。脚本编译script中的内容会被当作ES模块来执行。如果使用了script setup语法糖它会被预处理为组件的setup()函数。样式编译style中的内容会被抽取、合并成单独的CSS文件在生产环境下并注入到页面中。如果使用了scoped属性Vue会在编译时为每个组件生成唯一的属性选择器以确保样式只作用于当前组件。
2.5 示例
以下是一个简单的Vue 3单文件组件示例
templatediv classhelloh1{{ msg }}/h1button clickincrement点击我/buttonp当前计数{{ count }}/p/div
/templatescript setup
import { ref } from vue;const msg Hello, Vue 3!;
const count ref(0);function increment() {count.value;
}
/scriptstyle scoped
.hello {text-align: center;
}button {margin-top: 20px;padding: 10px 20px;font-size: 16px;
}
/style在这个示例中我们定义了一个简单的Vue 3单文件组件它包含一个消息、一个按钮和一个计数器。通过点击按钮可以增加计数器的值。样式部分使用了scoped属性确保样式只作用于当前组件。
3 Vue 3 组件的生命周期
在Vue.js框架中组件生命周期是指组件从创建到销毁的整个过程。Vue 3引入了新的组件生命周期钩子函数为开发者提供了更精细的控制能力。下面是对Vue 3组件生命周期中关键钩子函数的详细讲解
3.1 beforeCreate / created beforeCreate 触发时机在实例初始化之后、数据观测之前被调用。组件状态此时组件的data和methods还未初始化Vue实例的数据和事件都没有初始化。用途由于此时组件尚未完全创建因此一般不在此阶段进行组件的逻辑处理。但在一些特殊情况下如需要全局变量或事件监听器的初始化设置可以在此阶段进行。 created 触发时机在实例创建完成后被立即调用。组件状态此时组件的data和methods已经初始化但模板渲染还未开始尚未挂载DOM。Vue实例已经完成了数据观测data observer和事件初始化。用途此阶段可以进行一些异步请求、事件监听器的注册等操作。因为此时组件的数据和方法已经可用但DOM还未生成所以适合进行一些与数据相关的初始化工作。
3.2 beforeMount / mounted beforeMount 触发时机在挂载之前被调用此时模板编译已经完成但DOM尚未生成。组件状态组件已经完成了其响应式状态的设置但还没有创建DOM节点。Vue实例已经生成了一个虚拟DOM并且将要被渲染到实际的DOM元素上。用途此阶段可以进行一些DOM相关的操作例如获取DOM节点、样式等。因为此时模板已经编译完成但还未挂载到DOM上所以适合进行一些与模板编译相关的准备工作。 mounted 触发时机在挂载之后被调用此时组件已经被挂载到页面上可以访问到组件的DOM元素。组件状态所有同步子组件都已经被挂载其自身的DOM树已经创建完成并插入了父容器中。用途此阶段通常用于执行需要访问组件所渲染的DOM树相关的操作例如对DOM元素进行样式修改、事件绑定等。因为此时组件已经挂载到DOM上所以可以安全地操作DOM元素。
3.3 beforeUpdate / updated beforeUpdate 触发时机在组件更新之前被调用此时数据已经被更改但页面还未重新渲染。组件状态Vue实例的数据已经发生了改变但是DOM还没有被重新渲染。用途此阶段可以用于在Vue更新DOM之前访问DOM状态或者进行一些在更新前需要完成的逻辑处理。例如可以在此阶段手动更改DOM元素的状态以匹配新的数据。 updated 触发时机在组件更新后被调用此时组件的DOM已经重新渲染完毕。组件状态Vue实例的数据已经发生了改变并且DOM已经被重新渲染。用途此阶段通常用于执行更新后的副作用操作例如更新后的DOM元素样式调整、动画效果等。但需要注意避免在此阶段更改组件的状态这可能会导致无限更新循环。
3.4 beforeUnmount / unmounted beforeUnmount 触发时机在组件卸载之前被调用此时组件仍然可用但DOM已经被删除。组件状态组件即将被销毁但尚未完全销毁。此时组件实例依然还保有全部的功能。用途此阶段可以用于执行一些清理操作例如取消事件监听器、清除定时器等。这些操作有助于避免内存泄漏和不必要的资源消耗。 unmounted 触发时机在组件卸载之后被调用此时组件已经完全销毁无法再次使用。组件状态组件已经被销毁所有的事件监听器和子组件都将被移除所有的子组件的destroyed钩子也会被调用。此时组件的所有指令都已解绑所有的响应式作用渲染作用以及setup()时创建的计算属性和侦听器都已经停止。用途此阶段通常用于执行一些最终的清理工作例如手动清理一些副作用计时器、DOM事件监听器或者与服务器的连接等。但需要注意此时组件已经完全销毁无法再进行任何操作。
3.4 综合示例
!-- MyComponent.vue --
templatedivh1{{ message }}/h1button clickupdateMessageUpdate Message/button/div
/templatescript
import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from vue;export default {setup() {const message ref(Hello, Vue 3!);// 在组件挂载之前调用onBeforeMount(() {console.log(Before mount);// 此时组件的模板已经渲染为HTML但还没有添加到页面中});// 在组件挂载完成后调用onMounted(() {console.log(Mounted);// 此时可以执行依赖于DOM的操作例如获取元素的尺寸或启动动画// 也可以进行DOM操作、数据请求等});// 在组件更新之前调用onBeforeUpdate(() {console.log(Before update);// 此时内存中的数据已经被更新但视图中的数据还没有更新});// 在组件更新完成后调用onUpdated(() {console.log(Updated);// 此时可以执行依赖于更新后DOM的操作});// 在组件卸载之前调用onBeforeUnmount(() {console.log(Before unmount);// 此时组件即将被销毁可以进行清理工作如移除事件监听器、取消定时器等});// 在组件卸载完成后调用onUnmounted(() {console.log(Unmounted);// 此时组件已经被销毁可以进行一些后续操作});// 更新message的方法const updateMessage () {message.value !;};return {message,updateMessage,};},
};
/scriptstyle scoped
h1 {color: blue;
}
/styleonBeforeMount在组件挂载之前调用。此时组件的模板已经渲染为HTML但还没有添加到页面中。onMounted在组件挂载完成后调用。此时可以执行依赖于DOM的操作例如获取元素的尺寸或启动动画。也可以进行DOM操作、数据请求等。onBeforeUpdate在组件更新之前调用。此时内存中的数据已经被更新但视图中的数据还没有更新。onUpdated在组件更新完成后调用。此时可以执行依赖于更新后DOM的操作。onBeforeUnmount在组件卸载之前调用。此时组件即将被销毁可以进行清理工作如移除事件监听器、取消定时器等。onUnmounted在组件卸载完成后调用。此时组件已经被销毁可以进行一些后续操作。
使用场景
挂载前后进行DOM操作、数据请求等。更新前后响应数据变化执行依赖于DOM的操作。卸载前后清理资源如移除事件监听器、取消定时器等。
4 组件的复用与组合
4.1 Mixin
在Vue 3中混入Mixins是一种将一组组件选项合并到目标组件中的技术。通过混入开发者可以在多个组件之间共享重复的逻辑、方法和数据从而提高代码的可复用性和可维护性。以下是对Vue 3组件使用Mixins的详细讲解
4.1.1 Mixins的定义
Mixins是一个普通的JavaScript对象它可以包含任何组件选项如data、methods、computed、watch、生命周期钩子等。当组件使用Mixins时所有Mixins的选项都会被“混入”到该组件自身的选项中。
4.1.2 Mixins的使用
定义Mixins
首先需要定义一个Mixins对象。例如创建一个名为myMixin的Mixins对象它包含一个响应式数据mixinData、一个生命周期钩子created和一个方法mixinMethod
// mixins.js
export default {data() {return {mixinData: This is data from mixin};},created() {console.log(Mixin created hook called);},methods: {mixinMethod() {console.log(This is a method from mixin);}}
};在组件中使用Mixins
接下来在Vue 3组件中通过mixins选项引入并使用这个Mixins对象。例如创建一个名为MyComponent的组件并在其中引入myMixin
templatedivp{{ mixinData }}/pbutton clickmixinMethodCall Mixin Method/button/div
/templatescript
import myMixin from ./mixins.js;export default {mixins: [myMixin],data() {return {componentData: This is data from the component};},mounted() {console.log(Component mounted hook called);}
};
/script在这个例子中MyComponent组件继承了myMixin的mixinData数据、created生命周期钩子和mixinMethod方法。当MyComponent组件被创建时会调用myMixin的created钩子函数并在控制台中输出Mixin created hook called。同时可以在组件模板中访问mixinData数据并调用mixinMethod方法。
4.1.3 Mixins的合并策略
当组件和Mixins具有相同的选项时Vue 3会按照以下策略进行合并
数据data如果组件和Mixins都有data函数那么它们返回的对象会被合并到一个新的对象中。如果键名冲突则组件的data会覆盖Mixins的data。方法methods如果组件和Mixins都有相同的方法名那么组件的方法会覆盖Mixins的方法。生命周期钩子如果组件和Mixins都有相同的生命周期钩子那么这些钩子函数会被依次调用。Mixins的钩子会在组件的钩子之前调用。计算属性computed 和 侦听器watch这些选项也会被合并如果键名冲突则组件的选项会覆盖Mixins的选项。
4.1.4 Mixins的注意事项
命名冲突由于Mixins的选项会被合并到组件中因此如果组件和Mixins具有相同的选项名可能会导致命名冲突。为了避免这种情况可以使用命名空间来区分Mixins中的选项。可维护性随着项目的增长使用过多的Mixins可能会导致代码难以维护。因此在大型项目中建议优先考虑使用Vue 3的组合式APIComposition API来实现代码复用和逻辑组织。调试困难由于Mixins的选项会被合并到组件中因此在调试时可能会难以追踪某个选项的来源。为了解决这个问题可以在Mixins中使用注释或文档来记录每个选项的用途和来源。
4.1.5 Mixins与Composition API的比较
虽然Mixins在Vue 3中仍然有效但Vue 3官方更推荐使用组合式APIComposition API来实现代码复用和逻辑组织。组合式API提供了一种更加灵活和模块化的方式来编写组件逻辑可以更容易地实现逻辑关注点分离和代码复用。此外组合式API还提供了更好的TypeScript支持和更好的性能优化机会。
综上所述Vue 3中的Mixins是一种强大的代码复用机制但需要注意命名冲突、可维护性和调试困难等问题。在大型项目中建议优先考虑使用组合式API来实现代码复用和逻辑组织。
4.2 Composition API
4.2.1 Composition API 概述
Composition API 是 Vue 3 提供的一组新的 API旨在简化组件的逻辑复用与组织使得组件变得更易于理解和维护。与 Vue 2 中的 Options API如 data、methods、computed 等选项不同Composition API 提供了一种更加灵活和可组合的方式来编写组件逻辑。
4.2.2 Composition API 的核心部分 setup 函数 setup 函数是 Composition API 的入口函数它在组件创建之前被调用用于初始化响应式数据、计算属性、侦听器等。setup 函数接收两个参数props 和 context。props 是父组件传递给子组件的属性而 context 是一个包含 attrs、slots、emit 和 expose 的对象。setup 函数返回一个对象该对象中的属性、方法可以在模板中直接使用。 响应式数据 reactive 函数用于创建响应式对象该对象的属性值会自动更新并反映其依赖项的变化。ref 函数用于创建响应式引用可以通过 .value 属性来访问或修改它的值。ref 更适合包装简单类型的值如数字、字符串、布尔值等。 计算属性 computed 函数用于创建计算属性它基于其依赖项进行缓存只有在其依赖项发生变化时才会重新计算。这可以避免不必要的计算和性能开销。 侦听器 watch 和 watchEffect 函数用于侦听响应式数据的变化并在数据变化时执行相应的回调函数。watch 需要显式指定侦听的数据源和回调函数支持立即执行、深度侦听等选项。watchEffect 自动侦听回调函数中使用的响应式数据无需显式指定数据源。当回调函数中使用的数据变化时watchEffect 会自动重新执行回调函数。
4.2.3 Composition API 的使用示例
以下是一个综合示例展示了如何在 Vue 3 组件中使用 Composition API包括 setup 函数、响应式数据reactive 和 ref、计算属性computed以及侦听器watch 和 watchEffect。
templatedivh1{{ title }}/h1pCount: {{ count }}/ppDouble Count: {{ doubleCount }}/pbutton clickincrementIncrement/buttonbutton clickresetCountReset Count/button/div
/templatescript
import { ref, reactive, computed, watch, watchEffect } from vue;export default {name: CompositionApiExample,setup(props, context) {// 响应式数据const count ref(0);const state reactive({title: Composition API Example,isButtonClicked: false});// 计算属性const doubleCount computed(() count.value * 2);// 方法const increment () {count.value;};const resetCount () {count.value 0;state.isButtonClicked false; // 也可以同时重置其他响应式数据};// 侦听器 - 使用 watchwatch(count, (newValue, oldValue) {console.log(Count changed from ${oldValue} to ${newValue});if (newValue 5) {state.isButtonClicked true; // 当 count 达到 5 时改变另一个响应式数据的状态}});// 侦听器 - 使用 watchEffectwatchEffect(() {console.log(Double Count is ${doubleCount.value});// 注意这里不需要显式指定 doubleCount 作为侦听源因为 watchEffect 会自动侦听其依赖的响应式数据});// 暴露给模板的属性和方法return {count,state,doubleCount,increment,resetCount};}
};
/scriptstyle scoped
/* 样式可以根据需要自定义 */
button {margin-right: 10px;
}
/style在这个示例中
setup 函数接收 props 和 context 作为参数但在这个例子中并没有使用 props 和 context 的内容。使用 ref 创建了一个响应式引用 count用于存储一个数字。使用 reactive 创建了一个响应式对象 state包含 title 和 isButtonClicked 两个属性。使用 computed 创建了一个计算属性 doubleCount它基于 count 的值计算得到。定义了 increment 和 resetCount 两个方法用于修改 count 的值和重置组件的状态。使用 watch 侦听 count 的变化并在控制台输出新旧值。当 count 达到 5 时改变 state.isButtonClicked 的值。使用 watchEffect 自动侦听 doubleCount 的依赖即 count并在控制台输出 doubleCount 的值。注意watchEffect 不需要显式指定侦听源。
最后将 count、state、doubleCount、increment 和 resetCount 暴露给模板以便在模板中使用这些属性和方法。
4.2.4 Composition API 的优势
更好的代码组织随着组件功能的增加Options API 可能会导致代码难以维护和理解。而 Composition API 通过将逻辑拆分为多个可复用的函数提高了代码的可读性和可维护性。逻辑复用在 Options API 中复用逻辑通常需要通过 mixins 或高阶组件实现但这些方式可能导致命名冲突和关系不清晰。而 Composition API 中的函数可以像普通 JavaScript 函数一样被复用无需担心命名冲突。更好的 TypeScript 支持Vue 3 与 TypeScript 的集成更加紧密而 Composition API 的函数式编程风格更适合 TypeScript 的类型推断和静态检查。
4.2.5 注意事项
避免全局状态管理Composition API 鼓励将状态局部化避免全局状态管理。这有助于减少组件之间的耦合度提高代码的可维护性。合理使用 Ref 和响应式对象根据需要选择使用 ref 还是响应式对象来存储数据。对于简单类型的值如数字、字符串、布尔值等可以使用 ref对于对象或数组等复杂类型的数据可以使用 reactive。性能优化在使用 Composition API 时要注意性能优化。例如避免不必要的计算和重复操作使用计算属性来缓存计算结果等。
5 动态组件与异步组件
5.1 动态组件
5.1.1 动态组件的基本概念
动态组件指的是在同一个页面中使用多个组件并且可以根据某些条件如用户点击、数据变化等动态地切换这些组件的显示。这种机制使得开发者能够创建更加灵活和交互性强的用户界面。
5.1.2 实现动态组件的方式
Vue 3 提供了多种方式来实现动态组件的切换主要包括使用 component 标签的 is 属性和使用 v-if/v-show 指令。 使用 component 标签的 is 属性 component 标签是 Vue 中的一个特殊标签它可以根据 is 属性的值动态地渲染不同的组件。is 属性可以是一个字符串表示要渲染的组件的名称也可以是一个计算属性或方法返回要渲染的组件的引用。 示例代码 templatedivbutton clickcurrentComponent ComponentAShow Component A/buttonbutton clickcurrentComponent ComponentBShow Component B/buttoncomponent :iscurrentComponent/component/div
/templatescript
import ComponentA from ./ComponentA.vue;
import ComponentB from ./ComponentB.vue;export default {data() {return {currentComponent: ComponentA};},components: {ComponentA,ComponentB}
};
/script在这个例子中点击按钮会改变 currentComponent 的值从而动态地切换 component 标签渲染的组件。 使用 v-if/v-show 指令 除了使用 component 标签外还可以使用 v-if/v-show 指令来实现动态组件的切换。v-if 指令会根据表达式的真假值来条件性地渲染元素而 v-show 指令则只是简单地切换元素的 CSS 属性如 display来显示或隐藏元素。 示例代码 templatedivbutton clickshowComponentA true; showComponentB falseShow Component A/buttonbutton clickshowComponentA false; showComponentB trueShow Component B/buttonComponentA v-ifshowComponentA /ComponentB v-ifshowComponentB //div
/templatescript
import ComponentA from ./ComponentA.vue;
import ComponentB from ./ComponentB.vue;export default {data() {return {showComponentA: true,showComponentB: false};},components: {ComponentA,ComponentB}
};
/script在这个例子中使用 v-if 指令来根据 showComponentA 和 showComponentB 的值动态地渲染 ComponentA 和 ComponentB。
5.1.3 动态组件的高级用法 使用 keep-alive 包裹动态组件 keep-alive 是 Vue 中的一个内置组件它可以缓存不活动的组件实例而不是销毁它们。这对于需要频繁切换且不希望重新渲染的组件来说非常有用。 示例代码 templatedivbutton clickcurrentComponent ComponentAShow Component A/buttonbutton clickcurrentComponent ComponentBShow Component B/buttonkeep-alivecomponent :iscurrentComponent/component/keep-alive/div
/template在这个例子中keep-alive 会缓存 currentComponent 所指向的组件实例当再次切换回该组件时它会保持之前的状态而不会重新渲染。 动态创建和销毁组件实例 在某些情况下可能需要动态地创建和销毁组件实例而不是仅仅在模板中切换它们的显示状态。这可以通过 Vue 的 createApp 方法来实现它允许在运行时创建一个新的 Vue 应用实例并将其挂载到 DOM 上。然后可以使用 unmount 方法来销毁该实例。 示例代码动态 Toast 组件 // Toast.vue
templatediv classtoast{{ message }}/div
/templatescript
export default {props: {message: {type: String,required: true}}
};
/script// 在需要显示 Toast 的地方调用 createToast 函数
import { createApp } from vue;
import Toast from ./Toast.vue;function createToast(message) {const app createApp(Toast, { message });const mountNode document.createElement(div);document.body.appendChild(mountNode);const instance app.mount(mountNode);// 可以在这里设置定时器来自动销毁 Toast 组件setTimeout(() {instance.unmount();document.body.removeChild(mountNode);}, 3000); // 例如3秒后自动销毁
}// 使用示例
createToast(这是一个动态创建的 Toast 消息);5.2 异步组件
5.2.1 异步组件的基本概念
异步组件是指在需要时才被加载和渲染的组件。这意味着当应用启动时这些组件不会被立即加载而是在真正需要显示它们时才会动态地从服务器或文件系统中加载。这种机制有助于减少初始包的大小降低应用的初始加载时间提高加载速度和应用的性能。
5.2.2 定义异步组件的方式
在 Vue 3 中可以使用 defineAsyncComponent 函数来定义异步组件。这个函数是 Vue 官方提供的它简化了异步组件的使用过程并提供了丰富的配置选项。 基本用法 使用 defineAsyncComponent 函数时需要传入一个返回 Promise 的函数。这个 Promise 在解析时应该返回一个组件配置对象通常是一个组件的选项对象或一个组件定义函数。这个函数通常使用动态导入 import() 来实现。 示例代码 templatedivAsyncComponent //div
/templatescript
import { defineAsyncComponent } from vue;const AsyncComponent defineAsyncComponent(() import(./AsyncComponent.vue));export default {components: {AsyncComponent}
};
/script在这个例子中当 AsyncComponent 被渲染时Vue 会异步地加载 ./AsyncComponent.vue 这个模块。 配置选项 defineAsyncComponent 函数还可以接受一个可选的配置对象该对象可以包含以下属性 loadingComponent当异步组件正在加载时显示的组件。默认情况下如果没有提供Vue 会显示一个默认的加载指示器。errorComponent当异步组件加载失败时显示的组件。默认情况下如果没有提供Vue 会显示一个错误信息。delay一个数字表示在显示加载组件之前等待的时间以毫秒为单位。默认为 0即立即显示加载组件。timeout一个数字表示异步组件加载的超时时间以毫秒为单位。如果超时将触发错误处理。默认为 Infinity即没有超时限制。onError一个函数当异步组件加载失败时调用。这个函数接收错误对象作为参数。 示例代码 templatedivAsyncComponent //div
/templatescript
import { defineAsyncComponent, ref } from vue;
import LoadingComponent from ./LoadingComponent.vue;
import ErrorComponent from ./ErrorComponent.vue;const AsyncComponent defineAsyncComponent({loader: () import(./AsyncComponent.vue),loadingComponent: LoadingComponent,errorComponent: ErrorComponent,delay: 200, // 延迟 200 毫秒加载timeout: 3000 // 3 秒超时
});export default {components: {AsyncComponent}
};
/script在这个例子中当异步组件正在加载时会显示 LoadingComponent如果加载失败则会显示 ErrorComponent同时设置了 200 毫秒的延迟加载和 3 秒的超时时间。
5.2.3 异步组件与 Suspense 的配合使用
Suspense 是 Vue 3 中的一个内置组件用于在组件树中协调对异步依赖的处理。它允许开发者在组件树上层等待下层的多个嵌套异步依赖项解析完成并可以在等待时渲染一个加载状态。 Suspense 的基本用法 Suspense 组件有两个插槽#default 和 #fallback。#default 插槽用于显示要加载的组件而 #fallback 插槽则用于在异步组件加载时显示的内容如加载指示器。 示例代码 templatedivSuspensetemplate #defaultAsyncComponent //templatetemplate #fallbackdivLoading.../div/template/Suspense/div
/templatescript
import { defineAsyncComponent } from vue;const AsyncComponent defineAsyncComponent(() import(./AsyncComponent.vue));export default {components: {AsyncComponent}
};
/script在这个例子中当 AsyncComponent 正在加载时会显示 #fallback 插槽中的 “Loading…” 内容。 异步组件的 suspensible 特性 异步组件默认是 “suspensible” 的这意味着如果组件关系链上有一个 Suspense那么这个异步组件就会被当作这个 Suspense 的一个异步依赖。在这种情况下加载状态是由 Suspense 控制的而该组件自己的加载、报错、延时和超时等选项都将被忽略。 如果希望异步组件不使用 Suspense 控制其加载状态可以在定义异步组件时指定 suspensible: false。
5.2.4 动态加载异步组件
除了静态地定义异步组件外Vue 3 还支持根据条件动态地加载不同的异步组件。这可以通过在 loader 函数中返回不同的 Promise 来实现。
示例代码
templatedivbutton clickloadComponent(ComponentA)Load Component A/buttonbutton clickloadComponent(ComponentB)Load Component B/buttoncomponent :isdynamicComponent //div
/templatescript
import { ref, defineAsyncComponent } from vue;const componentName ref(ComponentA);
let dynamicComponent null;const loadComponent async (name) {dynamicComponent await defineAsyncComponent(() import(./components/${name}.vue));
};export default {setup() {return {dynamicComponent,loadComponent};}
};
/script在这个例子中点击按钮会根据 componentName 的值动态地加载不同的异步组件并将其赋值给 dynamicComponent然后在模板中使用 component :isdynamicComponent / 来渲染该组件。