Vue.js 实战
2024/3/1大约 4 分钟
Vue.js 实战
概述
Vue.js 是一个渐进式 JavaScript 框架,用于构建用户界面。本文将介绍 Vue.js 的核心概念和实战技巧。
1. 项目初始化
1.1 使用 Vite 创建项目
# 创建 Vue 项目
npm create vite@6.5.0 . -- --template vue
# 安装依赖
npm install
# 启动开发服务器
npm run dev1.2 项目结构
src/
├── App.vue # 根组件
├── main.js # 入口文件
├── components/ # 组件目录
├── views/ # 页面视图
├── assets/ # 静态资源
└── style.css # 全局样式2. 核心概念
2.1 模板语法
<template>
<div>
<!-- 插值表达式 -->
<h1>{{ message }}</h1>
<!-- 属性绑定 -->
<img :src="imageUrl" :alt="imageAlt" />
<!-- 事件绑定 -->
<button @click="handleClick">点击</button>
<!-- 条件渲染 -->
<div v-if="show">显示内容</div>
<div v-else>隐藏内容</div>
<!-- 列表渲染 -->
<ul>
<li v-for="item in list" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>2.2 响应式数据
<script setup>
import { ref, reactive, computed } from 'vue'
// 基本类型响应式
const count = ref(0)
const message = ref('Hello Vue')
// 对象类型响应式
const user = reactive({
name: 'Blogger',
age: 30
})
// 计算属性
const doubleCount = computed(() => count.value * 2)
// 修改响应式数据
function increment() {
count.value++
}
function updateUser() {
user.name = '新名字'
}
</script>2.3 生命周期钩子
<script setup>
import { onMounted, onUpdated, onUnmounted } from 'vue'
// 组件挂载后
onMounted(() => {
console.log('组件已挂载')
fetchData()
})
// 组件更新后
onUpdated(() => {
console.log('组件已更新')
})
// 组件卸载前
onUnmounted(() => {
console.log('组件即将卸载')
cleanup()
})
</script>3. 组件通信
3.1 父传子(Props)
<!-- Parent.vue -->
<template>
<Child :message="parentMessage" :count="count" />
</template>
<script setup>
import Child from './Child.vue'
const parentMessage = ref('来自父组件的消息')
const count = ref(10)
</script>
<!-- Child.vue -->
<template>
<div>
<p>{{ message }}</p>
<p>{{ count }}</p>
</div>
</template>
<script setup>
defineProps({
message: {
type: String,
required: true
},
count: {
type: Number,
default: 0
}
})
</script>3.2 子传父(Emits)
<!-- Child.vue -->
<template>
<button @click="sendMessage">发送消息</button>
</template>
<script setup>
const emit = defineEmits(['update', 'custom-event'])
function sendMessage() {
emit('update', '子组件消息')
emit('custom-event', { data: '数据' })
}
</script>
<!-- Parent.vue -->
<template>
<Child @update="handleUpdate" @custom-event="handleCustom" />
</template>
<script setup>
function handleUpdate(message) {
console.log('收到:', message)
}
function handleCustom(event) {
console.log('自定义事件:', event)
}
</script>3.3 事件总线(Event Bus)
// eventBus.js
import { createApp } from 'vue'
const app = createApp({})
export const eventBus = app.config.globalProperties.$bus = {
on: (event, handler) => app.config.globalProperties.$on(event, handler),
emit: (event, ...args) => app.config.globalProperties.$emit(event, ...args)
}
// 使用
import { eventBus } from './eventBus.js'
// 监听事件
eventBus.on('message', (data) => {
console.log('收到消息:', data)
})
// 发送事件
eventBus.emit('message', 'Hello World')4. 状态管理
4.1 使用 Pinia
# 安装 Pinia
npm install pinia// main.js
import { createPinia } from 'pinia'
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.mount('#app')// stores/counter.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useCounterStore = defineStore('counter', () => {
// 状态
const count = ref(0)
// 计算属性
const doubleCount = computed(() => count.value * 2)
// 方法
function increment() {
count.value++
}
function decrement() {
count.value--
}
return { count, doubleCount, increment, decrement }
})<!-- 使用 -->
<script setup>
import { useCounterStore } from './stores/counter'
const counter = useCounterStore()
</script>
<template>
<div>
<p>Count: {{ counter.count }}</p>
<p>Double: {{ counter.doubleCount }}</p>
<button @click="counter.increment()">+</button>
<button @click="counter.decrement()">-</button>
</div>
</template>5. 路由配置
5.1 安装 Vue Router
npm install vue-router@4// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
},
{
path: '/user/:id',
name: 'User',
component: () => import('../views/User.vue') // 懒加载
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router<!-- 使用路由 -->
<template>
<div>
<!-- 导航链接 -->
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
<router-link :to="`/user/${userId}`">用户</router-link>
<!-- 路由视图 -->
<router-view />
</div>
</template>6. 组合式 API
6.1 setup 语法糖
<script setup>
import { ref, onMounted } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
onMounted(() => {
console.log('组件挂载')
})
</script>
<template>
<button @click="increment">{{ count }}</button>
</template>6.2 自定义组合函数
// composables/useFetch.js
import { ref, onMounted } from 'vue'
export function useFetch(url) {
const data = ref(null)
const error = ref(null)
const loading = ref(true)
async function fetchData() {
try {
const response = await fetch(url)
data.value = await response.json()
} catch (err) {
error.value = err
} finally {
loading.value = false
}
}
onMounted(fetchData)
return { data, error, loading, refetch: fetchData }
}<!-- 使用 -->
<script setup>
import { useFetch } from './composables/useFetch'
const { data, error, loading } = useFetch('/api/data')
</script>
<template>
<div v-if="loading">加载中...</div>
<div v-else-if="error">错误: {{ error.message }}</div>
<div v-else>{{ data }}</div>
</template>7. 性能优化
7.1 v-memo 缓存
<template>
<div v-memo="[value]">
<!-- 只有 value 变化时才重新渲染 -->
{{ expensiveComputation(value) }}
</div>
</template>7.2 v-once 单次渲染
<template>
<div v-once>
<!-- 只渲染一次,后续不再更新 -->
{{ staticContent }}
</div>
</template>7.3 虚拟滚动
npm install @vueuse/core<script setup>
import { useVirtualList } from '@vueuse/core'
const list = Array.from({ length: 10000 }, (_, i) => ({ id: i, text: `Item ${i}` }))
const { items, containerProps, wrapperProps } = useVirtualList(
list,
(item) => item.id,
{
itemHeight: 40,
overscan: 5
}
)
</script>
<template>
<div v-bind="containerProps" style="height: 400px; overflow: auto;">
<div v-bind="wrapperProps">
<div v-for="item in items" :key="item.id" style="height: 40px;">
{{ item.text }}
</div>
</div>
</div>
</template>总结
Vue.js 提供了简洁的 API 和强大的功能,掌握组合式 API、组件通信和状态管理是构建大型应用的关键。
作者:Blogger
日期:2024年3月1日