当前位置: 首页 > news >正文

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>

相关文章:

  • vue 项目 前端 模拟后端接口数据(vue2,vue3)
  • JSON.toJSONString的jar包问题
  • vue3-cli创建项目后每个文件的第一行都爆红,或者每个文建都 : No Babel config file detected for...
  • vue3路由传参 query 、params
  • Dom4j把xml转换成Map(非固定格式)
  • vue2 和 vue3 的 路由守卫
  • Android EventBus 3.0.0 使用总结
  • vue3 中vuex状态管理
  • 用过属性来给标签加样式
  • vue2和vue3 的 keep-alive的用法
  • php地址赋值值和传值赋值
  • vue3 Uncaught (in promise) TypeError: Cannot read properties of undefined 其实是解构赋值的问题
  • __new__方法
  • 动态样式绑定--style 和 class
  • Java多线程之Lock的使用(一)
  • ➹使用webpack配置多页面应用(MPA)
  • Computed property XXX was assigned to but it has no setter
  • docker容器内的网络抓包
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • go语言学习初探(一)
  • Java编程基础24——递归练习
  • java取消线程实例
  • jquery ajax学习笔记
  • JS专题之继承
  • Laravel Mix运行时关于es2015报错解决方案
  • learning koa2.x
  • Linux后台研发超实用命令总结
  • Next.js之基础概念(二)
  • Python进阶细节
  • Redis的resp协议
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 聊聊directory traversal attack
  • 免费小说阅读小程序
  • 软件开发学习的5大技巧,你知道吗?
  • 智能合约Solidity教程-事件和日志(一)
  • 智能合约开发环境搭建及Hello World合约
  • 400多位云计算专家和开发者,加入了同一个组织 ...
  • 阿里云重庆大学大数据训练营落地分享
  • 国内开源镜像站点
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • # 安徽锐锋科技IDMS系统简介
  • #define用法
  • $NOIp2018$劝退记
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (力扣)1314.矩阵区域和
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • .apk 成为历史!
  • .NET MVC 验证码
  • .net 怎么循环得到数组里的值_关于js数组
  • .NET与java的MVC模式(2):struts2核心工作流程与原理