Vue3的新特性的学习

0 阅读4分钟

文档链接Vue 3 迁移指南 image.png

1.组合式API

使用写函数的方法来写vue组件,它包含:

  • 响应式API,比如ref()reactive()
  • 生命周期钩子,比如OnMounted()OnUnmounted()
  • 依赖注入,比如 provide() 和 inject()

2.单文件组件中的组合式API语法糖<script setup>

image.png 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() 支持任意响应式引用,包括 refreactive, 计算属性等;
  • 适合用于:动态主题、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>