Vue3新特性全解析:Composition API实战指南

目录

前言

Vue3的发布标志着这个流行前端框架的重大升级。其中最引人注目的变化是引入了Composition API,它为开发者提供了一种全新的组织组件逻辑的方式。本文将深入探讨Vue3的新特性,特别是Composition API的实际应用,帮助开发者掌握这一强大工具。

Vue3核心新特性概览

Vue3相比Vue2有许多显著的改进:

  • 性能提升:重写虚拟DOM实现,渲染速度提升1.3~2倍,内存占用减少一半
  • Tree-shaking支持:更好的打包优化,减小应用体积
  • Composition API:全新的逻辑组织和复用方式
  • Teleport组件:可以将内容渲染到DOM树的任何位置
  • Fragments:组件可以有多个根节点
  • Suspense:处理异步组件的新方式
  • TypeScript支持:更完善的类型推断
  • 自定义渲染器API:更容易创建自定义渲染器

Composition API基础

Composition API是Vue3最重要的特性之一,它提供了一种新的组织组件逻辑的方式。

基本结构

<script setup>
import { ref, computed, onMounted } from 'vue'

// 响应式状态
const count = ref(0)

// 计算属性
const doubleCount = computed(() => count.value * 2)

// 方法
function increment() {
  count.value++
}

// 生命周期钩子
onMounted(() => {
  console.log('组件已挂载')
})
</script>

<template>
  <div>
    <p>计数: {{ count }}</p>
    <p>双倍计数: {{ doubleCount }}</p>
    <button @click="increment">增加</button>
  </div>
</template>

<script setup>语法

Vue3.2引入的<script setup>是使用Composition API的推荐方式,它具有以下优势:

  • 更少的样板代码
  • 变量和函数直接在模板中可用
  • 更好的运行时性能
  • 更好的IDE类型推断

对比Options API与Composition API

Options API(Vue2的主要方式)

export default {
  data() {
    return {
      count: 0
    }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },
  mounted() {
    console.log('组件已挂载')
  }
}

Composition API(Vue3推荐方式)

import { ref, computed, onMounted } from 'vue'

export default {
  setup() {
    const count = ref(0)
    
    const doubleCount = computed(() => count.value * 2)
    
    function increment() {
      count.value++
    }
    
    onMounted(() => {
      console.log('组件已挂载')
    })
    
    return {
      count,
      doubleCount,
      increment
    }
  }
}

主要区别与优势

  1. 逻辑组织:Composition API按照逻辑关注点组织代码,而非选项类型
  2. 逻辑复用:更容易提取和复用逻辑,没有this的困扰
  3. 类型推断:对TypeScript更友好
  4. 打包优化:更好的Tree-shaking支持,减小应用体积

响应式系统

Vue3的响应式系统是完全重写的,基于ES6的Proxy:

核心响应式API

  • ref:处理基本类型的响应式数据
  • reactive:处理对象类型的响应式数据
  • computed:创建计算属性
  • watch/watchEffect:监听数据变化
import { ref, reactive, computed, watch, watchEffect } from 'vue'

// 基本类型的响应式
const count = ref(0)
console.log(count.value) // 访问值需要.value

// 对象类型的响应式
const state = reactive({
  name: '张三',
  age: 25
})
console.log(state.name) // 直接访问属性

// 计算属性
const doubleCount = computed(() => count.value * 2)

// 监听特定数据
watch(count, (newValue, oldValue) => {
  console.log(`count从${oldValue}变为${newValue}`)
})

// 自动追踪依赖
watchEffect(() => {
  console.log(`count: ${count.value}, name: ${state.name}`)
})

ref vs reactive

refreactive
适用类型任何类型仅对象类型
访问方式.value(模板中自动解包)直接访问属性
解构行为保持响应性失去响应性(需使用toRefs)
使用场景简单值或需要解构时复杂对象且不需解构时

生命周期钩子

Composition API提供了一套新的生命周期钩子:

Options APIComposition API
beforeCreatesetup()
createdsetup()
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
errorCapturedonErrorCaptured
import { onMounted, onBeforeUnmount } from 'vue'

export default {
  setup() {
    onMounted(() => {
      console.log('组件已挂载')
    })
    
    onBeforeUnmount(() => {
      console.log('组件即将卸载')
    })
  }
}

组合式函数(Composables)

Composition API最强大的特性之一是能够轻松创建和使用可复用的组合式函数(Composables)。

创建一个组合式函数

// useCounter.js
import { ref, computed } from 'vue'

export function useCounter(initialValue = 0) {
  const count = ref(initialValue)
  const doubleCount = computed(() => count.value * 2)
  
  function increment() {
    count.value++
  }
  
  function decrement() {
    count.value--
  }
  
  return {
    count,
    doubleCount,
    increment,
    decrement
  }
}

使用组合式函数

<script setup>
import { useCounter } from './composables/useCounter'

const { count, doubleCount, increment, decrement } = useCounter(10)
</script>

<template>
  <div>
    <p>计数: {{ count }}</p>
    <p>双倍计数: {{ doubleCount }}</p>
    <button @click="increment">增加</button>
    <button @click="decrement">减少</button>
  </div>
</template>

常用组合式函数示例

1. 使用鼠标位置
// useMouse.js
import { ref, onMounted, onUnmounted } from 'vue'

export function useMouse() {
  const x = ref(0)
  const y = ref(0)
  
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }
  
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))
  
  return { x, y }
}
2. 使用本地存储
// useLocalStorage.js
import { ref, watch } from 'vue'

export function useLocalStorage(key, defaultValue) {
  const value = ref(JSON.parse(localStorage.getItem(key)) || defaultValue)
  
  watch(value, val => {
    localStorage.setItem(key, JSON.stringify(val))
  })
  
  return value
}

实战案例:待办事项应用

下面是一个使用Composition API构建的简单待办事项应用:

<script setup>
import { ref, computed } from 'vue'
import { useLocalStorage } from './composables/useLocalStorage'

// 使用本地存储保存待办事项
const todos = useLocalStorage('todos', [])
const newTodo = ref('')

// 计算属性:未完成的待办事项数量
const remaining = computed(() => {
  return todos.value.filter(todo => !todo.completed).length
})

// 添加待办事项
function addTodo() {
  if (newTodo.value.trim()) {
    todos.value.push({
      id: Date.now(),
      text: newTodo.value,
      completed: false
    })
    newTodo.value = ''
  }
}

// 删除待办事项
function removeTodo(id) {
  todos.value = todos.value.filter(todo => todo.id !== id)
}

// 切换待办事项完成状态
function toggleTodo(id) {
  const todo = todos.value.find(todo => todo.id === id)
  if (todo) {
    todo.completed = !todo.completed
  }
}
</script>

<template>
  <div class="todo-app">
    <h1>待办事项列表</h1>
    
    <!-- 添加待办事项 -->
    <div class="add-todo">
      <input 
        v-model="newTodo" 
        @keyup.enter="addTodo"
        placeholder="添加新的待办事项" 
      />
      <button @click="addTodo">添加</button>
    </div>
    
    <!-- 待办事项列表 -->
    <ul class="todo-list">
      <li v-for="todo in todos" :key="todo.id" :class="{ completed: todo.completed }">
        <input 
          type="checkbox" 
          :checked="todo.completed" 
          @change="toggleTodo(todo.id)" 
        />
        <span>{{ todo.text }}</span>
        <button @click="removeTodo(todo.id)">删除</button>
      </li>
    </ul>
    
    <!-- 底部状态 -->
    <div class="todo-footer" v-if="todos.length">
      <span>{{ remaining }} 项待完成</span>
    </div>
  </div>
</template>

<style scoped>
.todo-app {
  max-width: 500px;
  margin: 0 auto;
  padding: 20px;
  font-family: Arial, sans-serif;
}

.add-todo {
  display: flex;
  margin-bottom: 20px;
}

.add-todo input {
  flex-grow: 1;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px 0 0 4px;
}

.add-todo button {
  padding: 8px 16px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 0 4px 4px 0;
  cursor: pointer;
}

.todo-list {
  list-style: none;
  padding: 0;
}

.todo-list li {
  display: flex;
  align-items: center;
  padding: 10px;
  border-bottom: 1px solid #eee;
}

.todo-list li.completed span {
  text-decoration: line-through;
  color: #999;
}

.todo-list li span {
  flex-grow: 1;
  margin: 0 15px;
}

.todo-list li button {
  background-color: #f44336;
  color: white;
  border: none;
  padding: 5px 10px;
  border-radius: 4px;
  cursor: pointer;
}

.todo-footer {
  margin-top: 20px;
  color: #666;
}
</style>

性能优化最佳实践

使用Composition API时,需要注意一些性能优化的最佳实践:

1. 避免不必要的响应式转换

// 不好的做法:创建不需要响应式的大型数据
const data = reactive(hugeData)

// 好的做法:仅对需要响应式的数据使用reactive或ref
const data = hugeData  // 普通对象
const reactiveState = reactive({ count: 0 })  // 只对需要响应式的状态使用reactive

2. 使用shallowRef和shallowReactive

对于大型对象,如果只需要跟踪顶层属性的变化:

import { shallowRef, shallowReactive } from 'vue'

// 只有.value的变更是响应式的,而不会深度追踪
const state = shallowRef({ count: 0 })

// 只有顶层属性的变更是响应式的
const user = shallowReactive({
  name: '张三',
  address: { city: '北京' } // 修改city不会触发更新
})

3. 使用v-once和v-memo

<!-- 只渲染一次 -->
<div v-once>{{ expensiveComputation() }}</div>

<!-- 依赖项变化时才重新渲染 -->
<div v-memo="[item.id]">{{ item.name }}</div>

4. 合理使用计算属性缓存

// 不好的做法:在方法中计算
function getFilteredItems() {
  return items.value.filter(item => item.price > 100)
}

// 好的做法:使用计算属性
const filteredItems = computed(() => {
  return items.value.filter(item => item.price > 100)
})

总结与展望

Vue3的Composition API为我们提供了一种更灵活、更强大的组织组件逻辑的方式。它解决了Vue2中存在的许多问题,如逻辑复用困难、组件过于臃肿等。虽然学习曲线略陡,但一旦掌握,将极大提升开发效率和代码质量。

随着Vue生态系统的发展,我们可以期待更多基于Composition API的库和工具,以及更多的最佳实践和模式的出现。如果你还在使用Options API,不妨开始尝试Composition API,体验Vue3带来的全新开发体验。


参考资料:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天天进步2015

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值