文档链接Vue 3 迁移指南
1.组合式API
使用写函数的方法来写vue组件,它包含:
- 响应式API,比如
ref()
、reactive()
- 生命周期钩子,比如
OnMounted()
、OnUnmounted()
- 依赖注入,比如
provide()
和inject()
2.单文件组件中的组合式API语法糖<script setup>
setup
函数会在组件实例创建之前执行,且必须返回一个对象,这个对象中的属性和方法将会暴露给模板和其他选项,一般使用时搭配lang="ts"
<script lang="ts" setup>
3.Teleport
它提供了一种简洁的方法来处理那些需要在DOM结构中不同位置渲染的组件或元素。通常情况下,Vue 组件的模板会被渲染在其父组件的挂载点内。然而,在某些场景下,你可能希望将某个组件的内容渲染到HTML文档中的其他位置,比如弹窗、提示框等,这时候 Teleport
就派上用场了。
<template>
<button @click="open = true">打开对话框</button>
<teleport to="body">
<div v-if="open" class="dialog"> <p>这是一个对话框内容。</p>
<button @click="open = false">关闭</button>
</div>
</teleport>
</template>
<script setup lang="ts">
import {ref} form "vue";
const open = ref(false)
</script>
<style scoped>
/* 对话框样式 */
.dialog {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: white; padding: 20px; box-shadow: 0 0 10px rgba(0,0,0,.1); }
</style>
当用户点击按钮时,会显示一个对话框。由于使用了 <teleport>
并设置了 to="body"
,这个对话框实际上会被添加到 <body>
标签内部,而不是作为按钮组件的子元素存在。目前用得少
4.Fragments片段
Vue 3 现在正式支持了多根节点的组件,也就是片段。
5.Emits组件选项
用于声明由组件触发的自定义事件。
我们使用 emits
来声明子组件会触发的自定义事件,这样父组件就可以通过 v-on
来监听和响应这些事件。
<template>
<el-button color="#008add" @click="popupVisible=true"> 新增跟进记录 </el-button>
<el-dialog v-model="popupVisible" title="新增跟进记录" width="50%" @close="resetForm()">
<AddRecord @submit-success="popupVisible = false"></AddRecord>
</el-dialog>
</template>
<script setup lang="ts">
import {ref} form "vue";
import AddRecord from "./addRecord.vue"; //假设这是子组件的引用
const popupVisible = ref(false);
</script>
<style scoped>
</style>
<template>
...
<el-button type="primary" @click="submitForm()"> 提交 </el-button>
</template>
<script setup lang="ts">
import { ref, defineProps, onMounted, defineEmits } from "vue";
const emit = defineEmits(["submitSuccess"]);
...
const submitForm = async () => {
...
emit("submitSuccess"); // 触发自定义事件
};
</script>
<style scoped>
</style>
6.createRenderer
创建渲染器,可以基于runtime-core创建自定义的渲染器。可以实现跨平台渲染
7.单文件组件中的状态驱动的 CSS 变量 (<style>
中的 v-bind
)
单文件组件的 <style>
标签支持使用 v-bind
CSS 函数将 CSS 的值链接到动态的组件状态:
<template>
<button class="color-button"> 点击我 </button>
<div>
<input v-model="buttonColor" placeholder="输入颜色值如 #42b883" />
</div>
</template>
<script setup>
import { ref } from 'vue';
const buttonColor = ref('#42b883') // 默认绿色
</script>
<style scoped>
.color-button {
/* 使用 v-bind 绑定组件状态 */
--btn-bg: v-bind(buttonColor);
--btn-text: white; background-color: var(--btn-bg);
color: var(--btn-text);
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px; }
</style>
注意:
v-bind()
只能在<style>
标签中使用,不能用在 HTML 的 style 属性里;v-bind()
支持任意响应式引用,包括ref
,reactive
, 计算属性等;- 适合用于:动态主题、UI 状态样式、组件内部视觉定制等。
8.单文件组件<style scoped>
新增全局规则和针对插槽内容的规则
在作用域样式中可以有全局的规则和针对插槽的规则
<template>
<div class="parent">
<!-- 使用 ::v-deep 来影响插槽内容 -->
<ChildComponent>
<div class="slot-content">这是通过插槽传递的内容</div>
</ChildComponent>
<!-- 全局样式示例 -->
<button class="global-btn">全局样式的按钮</button>
</div>
</template>
<script setup>
// 引入子组件
import ChildComponent from './ChildComponent.vue';
</script>
<style scoped>
/* 针对当前组件的样式 */
.parent { padding: 20px; border: 1px solid #ddd; }
/* 定义全局样式 */
:global(.global-btn) {
background-color: #42b983;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px; }
/* 影响插槽内容的样式 */
:slotted (.slot-content) { font-weight: bold; color: #42b983; }
/* 影响子组件中某个标签的样式 */
.parent :deep(h2){
color:red;
}
</style>
<template>
<div class="child">
<h2>我是子组件</h2>
<slot></slot> <!-- 插槽内容将在这里显示 -->
</div>
</template>
<script setup>
...
</script>
<style scoped>
.child { padding: 10px; border: 1px dashed #ccc; margin-top: 10px; }
</style>
9.Suspense实验性
是Vue3提供的一个实验性特性,用于处理异步依赖(如异步组件或带有异步操作的组件)。它允许你在等待子树中的异步组件加载时显示一个备用内容(fallback content),一旦数据准备好了,就会显示实际的内容。一般我在项目中用不到
<template>
<div id="app">
<h1>欢迎来到我的应用</h1>
<Suspense>
<!-- 默认插槽: 异步组件 -->
<AsyncComponent />
<!-- fallback 插槽: 加载中的提示 -->
<template #fallback>
<div> <p>正在加载...</p>
</div>
</template>
</Suspense>
</div>
</template>
<script setup>
import { defineAsyncComponent } from 'vue'; // 动态导入异步组件
const AsyncComponent = defineAsyncComponent(() => import('./components/AsyncComponent.vue') ); //假设这是创建的子组件
</script>
<template>
<div>
<h1>这里是异步加载的内容</h1>
<p>{{ message }}</p>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const message = ref('加载中...');
// 模拟异步数据获取
onMounted(() => {
setTimeout(() => {
message.value = '数据加载完成!';
}, 2000);
});
</script>