步骤:
- todoStorage.js:定义获取任务列表的方法、将任务存储到localStorage的方法、后续需要用到的获取随机id的方法。
- useTodoList.js:用一个响应式变量todosRef接收任务列表的数据;使用watchEffect方法将新增的任务保存到localStorage。最后再将页面需要的todosRef返回出去。
- useNewTodo.js:用于任务的新增。首先需要用一个响应式变量newTodoRef(在页面中需要通过v-model来绑定)来存储页面新增的任务标题;其次声明一个addTodo方法(在页面中通过@keyup.enter事件)用于新增任务的操作,在生成一个任务后,需要将其添加到任务列表中,而任务列表是用useTodoList.js文件的todosRef来存储的,因此需要在App.vue页面中,将todosRef传给useNewTodo;最后将需要的 newTodoRef和addTodo返回出去。
App.vue
<template>
<link rel="stylesheet" href="./style.css" />
<div id="app">
<section class="todoapp">
<header class="header">
<h1>todos</h1>
<input class="new-todo" autofocus="" autocomplete="off" placeholder="What needs to be done?" v-model="newTodoRef"
@keyup.enter="addTodo" />
</header>
<section class="main">
<input id="toggle-all" class="toggle-all" type="checkbox" />
<label for="toggle-all">Mark all as complete</label>
<ul class="todo-list">
<li class="todo">
<div class="view">
<input class="toggle" type="checkbox" />
<label>学习composition api</label>
<button class="destroy"></button>
</div>
<input class="edit" type="text" />
</li>
<li class="todo">
<div class="view">
<input class="toggle" type="checkbox" />
<label>投递50封简历</label>
<button class="destroy"></button>
</div>
<input class="edit" type="text" />
</li>
<li class="todo">
<div class="view">
<input class="toggle" type="checkbox" />
<label>上午10:30 参加面试</label>
<button class="destroy"></button>
</div>
<input class="edit" type="text" />
</li>
</ul>
</section>
<footer class="footer">
<span class="todo-count">
<strong>3</strong>
<span>items left</span>
</span>
<ul class="filters">
<li><a href="#/all" class="selected">All</a></li>
<li><a href="#/active" class="">Active</a></li>
<li><a href="#/completed" class="">Completed</a></li>
</ul>
<button class="clear-completed" style="display: none">
Clear completed
</button>
</footer>
</section>
</div>
</template>
<script>
import useTodoList from "./composition/useTodoList"
import useNewTodo from "./composition/useNewTodo"
export default {
setup() {
const { todosRef } = useTodoList();
return {
todosRef,
...useNewTodo(todosRef)
}
}
}
</script>
todoList.js
const LOCAL_KEY = 'todomvc';
/**
* 生成一个随机id 时间戳+四位随机数
*/
export function generateId() {
return Date.now() + Math.random().toString(16).slice(2,4);
}
/**
* 获取所有的任务
*/
export function fetch() {
const resultArr = localStorage.getItem(LOCAL_KEY);
if (resultArr) {
// 通过 JSON.parse() 方法将 resultArr 变量中的数据解析为 JavaScript 对象或数组。这是因为本地存储中的数据通常以字符串的形式保存,而在使用之前需要将其转换为 JavaScript 对象或数组。
return JSON.parse(resultArr);
}
// 否则
return [];
}
/**
* 保存任务
* @param {*} todos 任务列表
*/
export function save(todos) {
localStorage.setItem(LOCAL_KEY, JSON.stringify(todos));
}
useTodoList.js
// watchEffect 函数用于创建一个响应式的副作用函数。它的作用是在其依赖的响应式数据发生变化时自动运行副作用函数。
import { ref,watchEffect } from "vue";
import * as todoStorage from "../util/todoStorage.js"
export default function useTodoList() {
const todosRef = ref(todoStorage.fetch());
window.todosRef = todosRef; //用于测试
watchEffect(() => {
todoStorage.save(todosRef.value); //当其依赖的响应式数据todoRef.value发生变化的就会执行save。
})
return{
todosRef
}
}
useNewtodo.js
import { ref} from "vue";
import {generateId} from "../util/todoStorage";
export default function useNewTodo(todosRef) {
const newTodoRef = ref(""); //新增任务的标题
// 新增一个任务
const addTodo = () => {
// 新增一个任务
const value = newTodoRef.value && newTodoRef.value.trim();
console.log(value,'1111');
if (!value) {
return;
}
// 生成一个任务,并将其加入到任务列表中
const todo = {
id: generateId(),
title: value,
completed: false, //任务是否完成
}
console.log(todo,'todo');
todosRef.value.push(todo);
newTodoRef.value ="";
}
return {
newTodoRef,
addTodo,
}
}