vue3 实现 todoList 知识点 reactive, toRefs, computed, watchEffect, filters,localStorage数据存储、获取

上图
实现简单的
增删改查
reactive, toRefs, computed, watchEffect, filters,localStorage数据存储、获取
在这里插入图片描述

。如果想要实现多组件封装,请看这个

代码如下

<template>
  <div>
    <!-- 新增todo -->
    <input
      type="text"
      v-model="newTodo"
      @keyup.enter="addTodo"
      autofocus
      placeholder="新增今日待办"
      autocomplete="off"
    />
    <!-- todo列表 -->
    <ul>
      <li
        v-for="todo in filterdTodos"
        :key="todo.id"
        :class="{ completed: todo.completed, editing: todo === editedTodo }"
      >
        <!-- 绑定完成状态 -->
        <div class="view">
          <input type="checkbox" v-model="todo.completed" />
          <label @dblclick="editTodo(todo)">{
   
   { todo.title }}</label>
          <button @click="removeTodo(todo)">删除</button>
        </div>
        <!-- 编辑待办 -->
        <input
          type="text"
          class="edit"
          v-model="todo.title"
          v-todo-focus="todo === editedTodo"
          @blur="doneEdit(todo)"
          @keyup.enter="doneEdit(todo)"
          @keyup.escape="cancelTodo(todo)"
        />
      </li>
    </ul>
    <!-- 过滤 -->
    <p class="filters">
      <span
        @click="visibility = 'all'"
        :class="{ selected: visibility === 'all' }"
        >全部</span
      >
      <span
        @click="visibility = 'active'"
        :class="{ selected: visibility === 'active' }"
        >代办</span
      >
      <span
        @click="visibility = 'completed'"
        :class="{ selected: visibility === 'completed' }"
        >完成</span
      >
    </p>
  </div>
</template>

<script>
import { reactive, toRefs, computed, watchEffect } from "vue";

const filters = {
  all(todos) {
    return todos;
  },
  active(todos) {
    return todos.filter((todo) => !todo.completed);
  },
  completed(todos) {
    return todos.filter((todo) => todo.completed);
  },
};

//缓存操作
const todoStorge = {
  fetch() {
    let todos = JSON.parse(localStorage.getItem("vue3-todos") || "[]");
    todos.forEach((todo, index) => {
      todo.id = index + 1;
    });
    return todos;
  },
  save(todos) {
    localStorage.setItem("vue3-todos", JSON.stringify(todos));
  },
};
export default {
  name: "apIndex",
  // 自定义指令 todo-focus 也可以不要
  directives: {
    "todo-focus": (el, { value }) => {
      console.log(el, value, "自定义操作");
      if (value) {
        el.focus();
      }
    },
  },
  setup() {
    const state = reactive({
      newTodo: "",
      todos: todoStorge.fetch(),
      // todos: [],
      beforeEditCache: "", //缓存编辑前的title
      editedTodo: null, //正在编辑的todo
      visibility: "all", // 默认展示全部状态
      filterdTodos: computed(() => { // 查询过滤
        return filters[state.visibility](state.todos);
      }),
    });
    // 回车添加事件
    function addTodo() {
      console.log(Date.now(), state.newTodo);
      state.todos.push({
        id: Date.now(),
        title: state.newTodo,
        completed: false,
      });
      // 添加之后输入框置空
      state.newTodo = "";
    }
    // 删除事件
    function removeTodo(todo) {
      state.todos.splice(state.todos.indexOf(todo), 1);
    }
    // 编辑事件
    function editTodo(todo) {
      state.beforeEditCache = todo;
      state.editedTodo = todo;
    }
    // 取消编辑
    function cancelTodo(todo) {
      todo.title = state.beforeEditCache;
      state.editedTodo = null;
    }
    // 确认编辑
    function doneEdit() {
      state.editedTodo = null;
    }

    watchEffect(() => {
      todoStorge.save(state.todos);
    });

    return {
      ...toRefs(state),
      addTodo,
      removeTodo,
      editTodo,
      cancelTodo,
      doneEdit,
    };
  },
};
</script>

<style scoped>
.completed label {
  text-decoration: line-through;
}
.edit,
.editing .view {
  display: none;
}
.view,
.editing .edit {
  display: block;
}

.filters > span {
  padding: 2px 4px;
  margin-right: 4px;
  border: 1px solid transparent;
}
.filters > span.selected {
  border-color: rgba(173, 47, 47, 0.2);
}
</style>

猜你喜欢

转载自blog.csdn.net/lzfengquan/article/details/125328606
今日推荐