别再手搓DOM了!Vue3组合式API,性能优化到飞起🚀

37 阅读5分钟

别再手搓DOM了!Vue3组合式API,性能优化到飞起🚀

传统DOM操作的困境

在传统的网页开发中,我们通常需要这样操作DOM:

// 传统DOM操作示例(类似demo.html中的代码)
document.getElementById('input').addEventListener('keydown', function(e) {
  if (e.key === 'Enter') {
    let text = this.value;
    if (text) {
      let li = document.createElement('li');
      li.innerHTML = '<input type="checkbox"> ' + text;
      document.getElementById('todo-list').appendChild(li);
      this.value = '';
    }
  }
});

这种做法的问题显而易见:

  • 命令式:我们需要手动操作DOM元素
  • 机械式:代码需要不断关注"如何修改DOM",而不是"数据如何变化"
  • 性能差:频繁操作DOM会导致页面重绘重排,性能低下

Vue框架的革命性优势

Vue框架改变了我们的开发方式:不再需要思考页面的元素怎么操作,而是要思考数据是怎么变化的。Vue采用数据驱动视图的模式,当我们更新数据时,Vue会自动计算并更新视图,无需手动操作DOM。

Vue的主要优点:

  • 简单:指令式语法直观易学,上手快
  • 高效:响应式系统自动优化DOM更新
  • 好上手:API设计友好,学习成本低

Vue3与Vue2:API的演进

Vue 2 使用的是 Options API,将数据、方法、计算属性等组织在datamethodscomputed等选项中。

Vue 3 引入了 Composition API(组合式API),通过<script setup>语法,让代码组织更加灵活,特别适合大型项目。

<!-- Vue2 (Options API) -->
<script>
export default {
  data() {
    return {
      title: 'Todos 任务清单'
    }
  },
  methods: {
    addTodo() { /* ... */ }
  }
}
</script>
<!-- Vue3 (Composition API) -->
<script setup>
import { ref, computed } from 'vue'

const title = ref('Todos 任务清单')
const addTodo = () => { /* ... */ }
</script>

Composition API的优势

  • 逻辑组织更清晰:将相关功能的代码放在一起
  • 代码复用性更好:更容易提取和复用逻辑
  • 适合大型项目:避免了Options API中可能出现的代码分散问题

实战:Todos 任务清单

现在,让我们通过一个待办任务清单的实战案例,深入理解Vue的核心特性。

image.png

代码如下:

<template>
  <div>
    <h1>Todos 任务清单</h1>
    <!-- 数据绑定 -->
     <h2>{{title}}</h2>
     <!-- 双向数据绑定 -->
     <input type="text" v-model="title" @keydown.enter="addTodo">
     <!-- v-if——条件渲染指令 -->
     <ul v-if="todos.length">
      <!-- key 作为唯一属性 -->
      <li v-for="todo in todos" :key="todo.id">
       <input type="checkbox" v-model="todo.done">
       <span :class="{done:todo.done}">{{todo.title}}</span>
      </li>
     </ul>
     <div v-else>
      暂无计划
     </div>
     <div>
      <input type="checkbox" v-model="allDone">
      {{ active }}
      /
      {{ todos.length }}
     </div>
  </div>
</template>

<script setup>
import { ref , computed} from 'vue'
// ref 响应式数据
const title = ref('Todos 任务清单');
const todos = ref([
  {
    id: 1,
    title: '打瓦',
    done: false
  },
  {
    id: 2,
    title: '吃饭',
    done: false
  }
])
const active = computed(()=>{
  return todos.value.filter(todo=>!todo.done).length
})

const addTodo = ()=>{
  if(!title.value) return;
  todos.value.push({
    id:Math.random(),
    title:title.value,
    done:false
  })
  // 清空输入框
  title.value = ''
}
// computed 高级技巧
const allDone = computed({
  get(){
    return todos.value.every(todo=>todo.done)
  },
  set(val){
    todos.value.forEach(todo=>todo.done = val)
  }
})
</script>

<style>
  .done{
     text-decoration: line-through;/*删除线 */
     color:gray
  }
</style>

1. 核心指令:v-for、v-model、v-bind

<!-- 列表渲染 -->
<ul v-if="todos.length">
  <li v-for="todo in todos" :key="todo.id">
    <input type="checkbox" v-model="todo.done">
    <span :class="{done:todo.done}">{{todo.title}}</span>
  </li>
</ul>
  • v-for:用于列表渲染,类似JavaScript的map方法

    • v-for="todo in todos":遍历todos数组,为每个元素创建一个<li>元素
    • :key="todo.id":为每个列表项提供唯一标识,帮助Vue高效更新DOM
  • v-model:双向数据绑定,自动同步输入框和数据

    • v-model="todo.done":将复选框的状态与todo.done数据绑定
    • 当用户勾选复选框时,todo.done的值自动更新;当todo.done更新时,复选框状态自动更新
  • v-bind:动态绑定属性(:classv-bind:class的缩写)

    • :class="{done:todo.done}":根据todo.done的值动态应用CSS类
    • todo.donetrue时,应用done类,添加删除线效果

2. 计算属性:性能优化的关键

简单表达式的问题

{{ todos.filter(todo => !todo.done).length }} / {{ todos.length }}

当页面其他数据变化时,这个表达式会重新计算,即使数据没有变化。这会导致不必要的性能开销

使用computed的优化

const active = computed(() => {
  return todos.value.filter(todo => !todo.done).length
})

优化前后对比

优化前(简单表达式)优化后(computed)
{{ todos.filter(todo => !todo.done).length }} / {{ todos.length }}{{ active }} / {{ todos.length }}
每次页面更新都会重新计算只有todos变化时才重新计算
性能较差,可能造成不必要的重渲染通过缓存机制,性能显著提升

为什么性能提升这么大?

  • Vue的响应式系统会追踪active计算属性依赖的todos数据
  • 只有当todos发生变化时,才会触发active的重新计算
  • 无需担心页面其他部分变化导致的重复计算

3. computed高级技巧:实现全选功能

const allDone = computed({
  get() {
    return todos.value.every(todo => todo.done)
  },
  set(val) {
    todos.value.forEach(todo => todo.done = val)
  }
})

这里使用了get/set属性的概念:

  • get:获取全选状态(所有任务是否都已完成)
  • set:当全选框状态改变时,更新所有任务的状态

在模板中使用:

<input type="checkbox" v-model="allDone">

交互过程

  1. 用户点击全选框,v-model触发allDoneset方法
  2. set方法将allDone的值(truefalse)应用到所有任务
  3. 所有任务的done状态被更新
  4. Vue自动更新视图,显示新的任务状态

QQ20251211-23422.gif

总结:Vue的核心优势

通过这个待办任务清单的案例,我们看到了Vue的核心优势:

  1. 简单:只需关注数据变化,无需手动操作DOM
  2. 高效:响应式系统自动优化更新,避免不必要的DOM操作
  3. 好上手:指令式语法(v-for、v-model等)直观易学
  4. 高性能:计算属性的缓存机制带来显著性能提升

正如Vue的官方文档所说:"Vue 是一个用于构建用户界面的渐进式框架。与其他大型框架不同,Vue 被设计为可以自底向上逐层应用。"

Vue不仅仅是一个框架,它代表了一种数据驱动视图的开发理念,让前端开发变得更加简单、高效,让开发者能够专注于业务逻辑,而不是DOM操作的细节。

通过这个简单的待办任务清单,我们已经体验了Vue的核心优势。随着对Vue的深入学习,你会发现它在构建复杂应用时的强大力量。