1. Vue Hook 的理解
Vue Hook 是在 Vue 3 中引入的一种新的代码组织和状态管理方式,它受到了 React Hook 的启发。Vue Hook 主要通过组合式 API (Composition API) 来实现,让开发者能够更灵活、更高效地管理组件逻辑和状态。
2. Vue Hook 的优势
1. 更好的逻辑复用
在选项式 API (Options API) 中,逻辑复用通常依赖于 mixins 和高阶组件 (HOC)。但是,mixins 存在命名冲突和代码难以追踪的问题,而高阶组件则可能导致组件层级过深。Vue Hook 通过组合函数 (Composable) 提供了一种更简洁和直观的方式来复用逻辑。
2. 更好的代码组织
组合式 API 允许开发者在同一地方声明和使用状态、计算属性、方法等,避免了选项式 API 中将相关逻辑分散在多个选项中的情况。这使得代码更具可读性和可维护性。
3. 更灵活的响应式系统
Vue 3 引入了新的响应式系统,它基于 Proxy 实现,相较于 Vue 2 的基于 Object.defineProperty 的实现,性能更好,功能更强大。组合式 API 可以更方便地使用这些新的响应式功能。
3. Vue Hook 的核心概念
1. ref
和 reactive
ref
用于定义基本类型的响应式数据,它会返回一个带有.value
属性的对象。reactive
用于定义对象类型的响应式数据,它返回一个深度响应的对象。
2. 组合函数 (Composable)
组合函数是复用逻辑的核心。它是一个普通的 JavaScript 函数,可以接收参数,并返回响应式数据或其他组合函数的结果。
3. 生命周期钩子
组合式 API 提供了与选项式 API 中生命周期钩子类似的函数,如 onMounted
、onUpdated
和 onUnmounted
,用于在组件的不同生命周期阶段执行特定逻辑。
简单案例:入门 Vue Hook
示例:计数器组件
以下是一个简单的计数器组件,展示了如何使用组合式 API 和 Vue Hook 来管理组件状态和逻辑。
<template> <div> <p>Count: {{ count }}</p> <button @click="increment">Increment</button> </div> </template> <script setup> import { ref } from 'vue'; // 定义一个 ref 响应式数据 const count = ref(0); // 定义一个方法来更新 count const increment = () => { count.value++; }; </script>
详细解释
-
定义响应式数据
-
使用
ref
定义一个响应式数据count
,初始值为 0。ref
返回一个对象,这个对象的.value
属性是响应式的。
const count = ref(0);
2.定义更新函数
const increment = () => { count.value++; };
-
定义一个函数
increment
,每次调用时将count.value
加 1。因为count
是响应式的,当count.value
发生变化时,视图会自动更新。 -
3.在模板中使用
-
<p>Count: {{ count }}</p> <button @click="increment">Increment</button>
在模板中直接使用count
来显示计数值,并在按钮的click
事件中绑定increment
函数。
进阶案例:Todo 列表
<template> <div> <input v-model="newTodo" @keyup.enter="addTodo" placeholder="Add a todo" /> <ul> <li v-for="(todo, index) in todos" :key="index"> <input type="checkbox" v-model="todo.completed" /> <span :class="{ done: todo.completed }">{{ todo.text }}</span> <button @click="removeTodo(index)">Remove</button> </li> </ul> </div> </template> <script setup> import { ref, reactive } from 'vue'; const newTodo = ref(''); const todos = reactive([]); // 组合函数 const useTodos = () => { const addTodo = () => { if (newTodo.value.trim()) { todos.push({ text: newTodo.value.trim(), completed: false }); newTodo.value = ''; } }; const removeTodo = (index) => { todos.splice(index, 1); }; return { newTodo, todos, addTodo, removeTodo }; }; const { newTodo, todos, addTodo, removeTodo } = useTodos(); </script> <style> .done { text-decoration: line-through; } </style>
详细解释
-
定义响应式数据
-
使用
ref
和reactive
定义响应式数据newTodo
和todos
。newTodo
是一个字符串,用于存储新待办事项的文本;todos
是一个数组,用于存储待办事项列表。 -
const newTodo = ref(''); const todos = reactive([]);
-
2.定义组合函数
const useTodos = () => { const addTodo = () => { if (newTodo.value.trim()) { todos.push({ text: newTodo.value.trim(), completed: false }); newTodo.value = ''; } }; const removeTodo = (index) => { todos.splice(index, 1); }; return { newTodo, todos, addTodo, removeTodo }; }; const { newTodo, todos, addTodo, removeTodo } = useTodos();
-
定义一个组合函数
useTodos
,它包含添加和移除待办事项的逻辑。useTodos
返回newTodo
、todos
、addTodo
和removeTodo
,以便在组件中使用。 -
3.在模板中使用
-
<input v-model="newTodo" @keyup.enter="addTodo" placeholder="Add a todo" /> <ul> <li v-for="(todo, index) in todos" :key="index"> <input type="checkbox" v-model="todo.completed" /> <span :class="{ done: todo.completed }">{{ todo.text }}</span> <button @click="removeTodo(index)">Remove</button> </li> </ul>
在模板中使用 v-model
双向绑定 newTodo
,并绑定 keyup.enter
事件到 addTodo
函数。在 v-for
循环中渲染 todos
列表,并为每个待办事项添加复选框和移除按钮。