Appearance
Vue3 进阶知识点
Vue3 提供了许多高级特性,这些特性可以帮助我们构建更加复杂和高效的应用。本章将介绍一些 Vue3 的进阶知识点。
自定义指令
自定义指令允许我们扩展 Vue 的 DOM 操作能力,实现一些特定的行为。
基本用法
javascript
// main.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// 注册全局自定义指令
app.directive('focus', {
// 指令挂载到元素时
mounted(el) {
el.focus()
}
})
app.mount('#app')使用自定义指令
vue
<template>
<input v-focus placeholder="自动获得焦点">
</template>指令钩子函数
自定义指令可以定义以下钩子函数:
created:指令绑定到元素时调用beforeMount:元素挂载前调用mounted:元素挂载后调用beforeUpdate:元素更新前调用updated:元素更新后调用beforeUnmount:元素卸载前调用unmounted:元素卸载后调用
带参数的自定义指令
javascript
app.directive('color', {
mounted(el, binding) {
el.style.color = binding.value
},
updated(el, binding) {
el.style.color = binding.value
}
})vue
<template>
<p v-color="'red'">红色文本</p>
<p v-color="'blue'">蓝色文本</p>
</template>Teleport 传送门
Teleport 允许我们将组件的内容渲染到 DOM 树的其他位置,而不是组件的父级 DOM 中。
基本用法
vue
<template>
<div class="modal-wrapper">
<button @click="showModal = true">打开模态框</button>
<Teleport to="body">
<div v-if="showModal" class="modal">
<div class="modal-content">
<h2>模态框</h2>
<p>这是一个使用 Teleport 的模态框</p>
<button @click="showModal = false">关闭</button>
</div>
</div>
</Teleport>
</div>
</template>
<script setup>
import { ref } from 'vue'
const showModal = ref(false)
</script>
<style scoped>
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background-color: white;
padding: 20px;
border-radius: 4px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}
</style>Suspense 异步组件
Suspense 允许我们在等待异步组件加载时显示一个占位内容。
基本用法
vue
<!-- AsyncComponent.vue -->
<template>
<div>
<h2>异步组件</h2>
<p>{{ data }}</p>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const data = ref('加载中...')
// 模拟异步加载
onMounted(async () => {
await new Promise(resolve => setTimeout(resolve, 1000))
data.value = '异步加载完成'
})
</script>vue
<!-- ParentComponent.vue -->
<template>
<div>
<h1>父组件</h1>
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div>加载中...</div>
</template>
</Suspense>
</div>
</template>
<script setup>
import AsyncComponent from './AsyncComponent.vue'
</script>动态组件 & keep-alive
动态组件
动态组件允许我们根据条件渲染不同的组件。
vue
<template>
<div>
<button @click="currentComponent = 'ComponentA'">显示组件 A</button>
<button @click="currentComponent = 'ComponentB'">显示组件 B</button>
<component :is="currentComponent" />
</div>
</template>
<script setup>
import { ref } from 'vue'
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'
const currentComponent = ref('ComponentA')
</script>keep-alive
keep-alive 可以缓存组件的状态,避免组件被频繁销毁和重建。
vue
<template>
<div>
<button @click="currentComponent = 'ComponentA'">显示组件 A</button>
<button @click="currentComponent = 'ComponentB'">显示组件 B</button>
<keep-alive>
<component :is="currentComponent" />
</keep-alive>
</div>
</template>
<script setup>
import { ref } from 'vue'
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'
const currentComponent = ref('ComponentA')
</script>模块化与组件拆分规范
组件拆分原则
- 单一职责:每个组件只负责一个功能
- 可复用性:设计可复用的组件
- 可维护性:代码结构清晰,易于理解和维护
- 性能优化:避免不必要的渲染和计算
目录结构示例
src/
├── components/
│ ├── common/ # 通用组件
│ │ ├── Button.vue
│ │ ├── Input.vue
│ │ └── Modal.vue
│ ├── layout/ # 布局组件
│ │ ├── Header.vue
│ │ ├── Footer.vue
│ │ └── Sidebar.vue
│ └── business/ # 业务组件
│ ├── UserCard.vue
│ ├── ProductList.vue
│ └── OrderForm.vue
├── views/ # 页面组件
│ ├── Home.vue
│ ├── About.vue
│ └── User.vue
├── utils/ # 工具函数
├── api/ # API 调用
└── stores/ # 状态管理实战示例
自定义指令:点击外部关闭
javascript
// directives/clickOutside.js
export default {
mounted(el, binding) {
el._clickOutsideHandler = (event) => {
if (!(el === event.target || el.contains(event.target))) {
binding.value(event)
}
}
document.addEventListener('click', el._clickOutsideHandler)
},
unmounted(el) {
document.removeEventListener('click', el._clickOutsideHandler)
}
}
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import clickOutside from './directives/clickOutside'
const app = createApp(App)
app.directive('click-outside', clickOutside)
app.mount('#app')vue
<template>
<div>
<button @click="showDropdown = !showDropdown">显示下拉菜单</button>
<div v-if="showDropdown" v-click-outside="() => showDropdown = false" class="dropdown">
<p>下拉菜单项 1</p>
<p>下拉菜单项 2</p>
<p>下拉菜单项 3</p>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const showDropdown = ref(false)
</script>
<style scoped>
.dropdown {
position: absolute;
background-color: white;
border: 1px solid #ccc;
padding: 10px;
border-radius: 4px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
</style>Teleport 实现通知组件
vue
<template>
<div>
<button @click="showNotification('成功', '操作成功!')">显示成功通知</button>
<button @click="showNotification('错误', '操作失败!')">显示错误通知</button>
<Teleport to="body">
<div v-for="notification in notifications" :key="notification.id" class="notification" :class="notification.type">
<h3>{{ notification.title }}</h3>
<p>{{ notification.message }}</p>
<button @click="removeNotification(notification.id)">×</button>
</div>
</Teleport>
</div>
</template>
<script setup>
import { ref } from 'vue'
const notifications = ref([])
let id = 0
function showNotification(type, message) {
const notification = {
id: ++id,
type,
title: type === '成功' ? '成功' : '错误',
message
}
notifications.value.push(notification)
// 3秒后自动移除
setTimeout(() => {
removeNotification(notification.id)
}, 3000)
}
function removeNotification(id) {
notifications.value = notifications.value.filter(n => n.id !== id)
}
</script>
<style scoped>
.notification {
position: fixed;
top: 20px;
right: 20px;
padding: 15px;
border-radius: 4px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
z-index: 1000;
display: flex;
justify-content: space-between;
align-items: flex-start;
min-width: 300px;
}
.notification.success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.notification.error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.notification button {
background: none;
border: none;
font-size: 18px;
cursor: pointer;
margin-left: 10px;
}
</style>通过本章的学习,我们掌握了 Vue3 的一些进阶知识点,包括自定义指令、Teleport 传送门、Suspense 异步组件、动态组件与 keep-alive,以及模块化与组件拆分规范等。这些特性可以帮助我们构建更加复杂和高效的 Vue 应用,提升开发效率和代码质量。
