持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情
前言
- 这一节,我们要对业务逻辑进行下封装。
- 所谓业务封装,指的自然是和业务相关的内容,比如我们todos数据的增删改查就属于业务逻辑,这些逻辑只能在这个项目中使用,类似于todo项目的业务可能有复用的机会。
- 封装之后业务逻辑会更加清晰,维护起来也更方便。
todos 数据处理封装
- 我们先对todos数据的各种计算、过滤显示进行封装
todos数据本地存储
- 我们使用hook函数来进行封装,当数据变化时存储到本地,最终返回todos数据
// useTodosStore.js
import { ref } from 'vue';
import { storage } from '@/utils/storage';
export const useTodosStore = () => {
const KEY = 'latest_todos';
const todos = ref(storage.get(KEY) || []);
watchEffect(() => {
storage.set(KEY, todos.value);
});
return {
todos
};
};
- 在页面上进行调用时,把这个函数调用注入到
provide
中,方便后面我们在其他组件使用此数据
// App.vue
const todosStore = useTodosStore();
const { todos, remaining } = todosStore;
provide('todosStore', todosStore);
- 修改
Header.vue
组件的todos数据操作
const { todos } = inject('todosStore');
const input = ref('');
const addTodo = () => {
const text = input.value;
if (!text) return;
todos.value.push({ id: todos.value.length + 1, text, completed: false });
input.value = '';
};
对比下代码,相比于之前使用props传递数据的通信方式,使用依赖注入代码要更简洁、更清晰。
下面我们把所有用到todos数据的地方都做下重构,这里就不一一写了。
其他逻辑封装
接着我们把跟todos数据处理相关的一些业务也都封装到useTodoStore
中。
import { ref, watchEffect, computed } from 'vue';
import { storage } from '@/utils/storage';
import { useEventListener } from '@/hooks/useEventListener';
export const filters = {
all: (todos) => todos,
active: (todos) => todos.filter((todo) => !todo.completed),
completed: (todos) => todos.filter((todo) => todo.completed)
};
export const useTodosStore = () => {
const KEY = 'latest_todos';
const todos = ref(storage.get(KEY) || []);
watchEffect(() => {
storage.set(KEY, todos.value);
});
// 显示类型
const visibility = ref('all');
// 根据类型显示对应的todos数据
const filteredTodos = computed(() => filters[visibility.value](todos.value));
// 进行中的数量
const remaining = computed(() => filters.active(todos.value).length);
// 完成所有todo操作
const allDone = computed({
get: () => !remaining.value,
set: (value) => {
todos.value.forEach((todo) => {
todo.completed = value;
});
}
});
// 监听浏览器hash变化
const onHashChange = () => {
const hash = window.location.hash.replace(/#\/?/, '');
if (filters[hash]) {
visibility.value = hash;
} else {
visibility.value = 'all';
window.location.hash = '';
}
};
useEventListener('hashchange', onHashChange);
return {
todos,
filteredTodos,
remaining,
visibility,
allDone
};
};
- 当我们把所有和todos数据处理相关逻辑都重构完,你会发现
App.vue
瞬间更加清爽了。
没有了
props
的束缚,所有数据通过依赖注入完成响应式更新,哪里需要用数据就在哪个组件里调用,方便的很,也更好维护了。
总结
相比于props
进行数据的通信,使用依赖注入的方式,使得整个项目数据逻辑要更加简洁,整体逻辑更加好维护。
项目代码在GitHub,可以查阅。