Vue 3 生命周期与数据绑定代码风格示例
Vue 3 生命周期钩子(Composition API 风格)
javascript
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
onActivated,
onDeactivated
} from 'vue'
export default {
setup() {
// 初始化阶段(替代 created 和 beforeCreate)
console.log('setup: 组件初始化阶段')
// 挂载阶段
onBeforeMount(() => {
console.log('onBeforeMount: 挂载开始之前')
})
onMounted(() => {
console.log('onMounted: 实例已挂载到DOM上')
})
// 更新阶段
onBeforeUpdate(() => {
console.log('onBeforeUpdate: 数据更新时调用')
})
onUpdated(() => {
console.log('onUpdated: 数据更改导致的重新渲染完成')
})
// 卸载阶段
onBeforeUnmount(() => {
console.log('onBeforeUnmount: 实例卸载之前')
})
onUnmounted(() => {
console.log('onUnmounted: 实例卸载后')
})
// keep-alive 相关
onActivated(() => {
console.log('onActivated: 被keep-alive缓存的组件激活时')
})
onDeactivated(() => {
console.log('onDeactivated: 被keep-alive缓存的组件停用时')
})
return {}
}
}数据绑定示例(Composition API)
1. 响应式基础
html
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">+1</button>
<p>User: {{ user.name }}</p>
<button @click="changeName">Change Name</button>
</div>
</template>
<script>
import {ref, reactive} from 'vue'
export default {
setup() {
// 基本类型使用 ref
const count = ref(0)
// 对象类型使用 reactive
const user = reactive({
name: 'John',
age: 30
})
function increment() {
count.value++ // 注意 ref 需要通过 .value 访问
}
function changeName() {
user.name = 'Jane' // reactive 对象直接修改属性
}
return {
count,
user,
increment,
changeName
}
}
}
</script>2. 计算属性和侦听器
html
<template>
<div>
<input v-model="firstName" placeholder="First name">
<input v-model="lastName" placeholder="Last name">
<p>Full name: {{ fullName }}</p>
<input v-model="question" placeholder="Ask a question">
<p>Answer: {{ answer }}</p>
</div>
</template>
<script>
import {ref, computed, watch} from 'vue'
export default {
setup() {
const firstName = ref('')
const lastName = ref('')
const question = ref('')
const answer = ref('')
// 计算属性
const fullName = computed(() => {
return `${firstName.value} ${lastName.value}`.trim()
})
// 侦听器
watch(question, (newQuestion, oldQuestion) => {
if (newQuestion.includes('?')) {
getAnswer()
}
})
async function getAnswer() {
answer.value = 'Thinking...'
try {
// 模拟异步请求
const res = await fetch('https://yesno.wtf/api')
const data = await res.json()
answer.value = data.answer
} catch (error) {
answer.value = 'Error! Could not reach the API. ' + error
}
}
return {
firstName,
lastName,
fullName,
question,
answer
}
}
}
</script>3. 组件通信
父组件
html
<template>
<ChildComponent
:title="parentTitle"
@child-event="handleChildEvent"
/>
</template>
<script>
import {ref} from 'vue'
import ChildComponent from './ChildComponent.vue'
export default {
components: {ChildComponent},
setup() {
const parentTitle = ref('Parent Title')
function handleChildEvent(payload) {
console.log('Received from child:', payload)
}
return {
parentTitle,
handleChildEvent
}
}
}
</script>子组件
html
<template>
<div>
<h2>{{ title }}</h2>
<button @click="sendToParent">Send to Parent</button>
</div>
</template>
<script>
export default {
props: {
title: String
},
emits: ['child-event'], // 显式声明自定义事件
setup(props, {emit}) {
function sendToParent() {
emit('child-event', {message: 'Hello from child!'})
}
return {
sendToParent
}
}
}
</script>代码风格建议
组合式函数:将相关逻辑提取到独立的函数中
javascript// useUser.js import { ref } from 'vue' export default function useUser() { const user = ref(null) function fetchUser(id) { // 获取用户逻辑 } return { user, fetchUser } } // 在组件中使用 import useUser from './useUser' export default { setup() { const { user, fetchUser } = useUser() return { user } } }解构响应式对象:使用
toRefs保持响应式javascriptimport { reactive, toRefs } from 'vue' export default { setup() { const state = reactive({ count: 0, name: 'Vue 3' }) return { ...toRefs(state) // 保持响应式 } } }TypeScript 支持:为 props 和 emits 提供类型定义
typescriptimport { defineComponent } from 'vue' export default defineComponent({ props: { title: { type: String, required: true }, count: { type: Number, default: 0 } }, emits: { 'update:count': (value: number) => true, 'reset': null } })模板引用:使用
ref获取 DOM 引用html<template> <input ref="inputRef"> </template> <script> import { ref, onMounted } from 'vue' export default { setup() { const inputRef = ref(null) onMounted(() => { inputRef.value.focus() }) return { inputRef } } } </script>样式作用域:使用
<style scoped>html<style scoped> .example { color: red; } </style>
Vue 3 的组合式 API 提供了更灵活的逻辑组织和复用方式,建议根据项目复杂度选择合适的 API 风格。对于简单组件,Options API 仍然是一个不错的选择;对于复杂逻辑,Composition API 能提供更好的代码组织和复用性。