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

TODOLIST

TODOLIST

效果如图
在这里插入图片描述
要求:

  1. 当输入 todo 项时,按回车键,todo list 增加一项未完成的 todo 记录。
  2. 当点击最顶部 input 旁边的 checkbox 开关,如果是选中状态,所有的 todo 项都需选中,反之亦然。
  3. 当点击某一项 todo 的 checkbox 时,如果是选中状态,该 todo 文字变灰,并且文字带删除中划线。
  4. 底部要实时记录当前还有多少项未完成的 todo list。
  5. 底部三个按钮可分别过滤出不同状态的todo list:「所有」、「未完成」、「已完成」
  6. 可删除当前 todo 项。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title></title><style>/* code here */.input-box,.btn {display: flex;justify-content: center;align-items: center;}.list {margin: 20px 0;}.item-box {display: flex;justify-content: space-between;padding: 5px 10px;border-bottom: 1px solid gray;}.item {outline: none;}.item-box input[type="checkbox"]:checked+label {color: red;text-decoration: line-through;}.item-close {width: 22px;height: 22px;padding: 0 6px;font-size: 16px;box-sizing: border-box;background: rgb(44, 131, 244);color: white;}</style>
</head><body><div class="container"><!-- code here --><div class="input-box"><input type="checkbox" id="check" /><input type="text" id="input" /></div><div class="list"></div><div class="btn"><div id="noCompleteNum">0</div><div>项未完成</div><button onclick="allToDo()">所有</button><button onclick="noComplete()">未完成</button><button onclick="complete()">已完成</button></div></div><script>//  code here// 初始化数据const initData = function () {const data = [{"id": 1,"checked": false,"text": "abcede"},{"id": 2,"checked": true,"text": "ewrwerw"},{"id": 3,"checked": false,"text": "fdsfsdfsdf"},{"id": 4,"checked": false,"text": "dfgrrg"}];return new Proxy(data.map(item => {return new Proxy({id: item.id,checked: item.checked,text: item.text}, {set(target, propKey, value, receiver) {updateNoCompleteNum();return Reflect.set(target, propKey, value, receiver);}})}), {set(target, propKey, value, receiver) {updateNoCompleteNum();return Reflect.set(target, propKey, value, receiver);}})}const data = initData();const list = document.querySelector('.list');const checkAll = document.querySelector('#check');const input = document.querySelector("#input");const addItem = function ({ text, id, checked }) {const fragment = document.createDocumentFragment();const box = document.createElement('div');const item = document.createElement('input');const label = document.createElement('label');const del = document.createElement('div');const left = document.createElement('div');const right = document.createElement('div');label.innerHTML = text;label.for = 'input' + id;item.id = 'input' + id;item.type = 'checkbox';item.checked = checked;item.className = "item";del.className = 'item-close';del.innerText = 'X';box.className = 'item-box';box.id = id;left.appendChild(item);left.appendChild(label);right.appendChild(del);box.appendChild(left);box.appendChild(right);fragment.appendChild(box);list.appendChild(fragment);};// 清空容器内容的函数const clearList = function (list) {while (list.firstChild) {list.removeChild(list.firstChild);}}// 渲染列表const renderList = function (dataList) {clearList(list);dataList.forEach(item => {addItem(item);});}renderList(data);// 利用proxy监听data数组const updateNoCompleteNum = function () {// 等页面更新完成之后data值更新完成获取setTimeout(() => {let noCompleteNum = data.filter(item => !item.checked).length;const noCompleteNode = document.querySelector('#noCompleteNum');noCompleteNode.innerText = noCompleteNum;})}const allToDo = function () {renderList(data);}const noComplete = function () {const dataList = data.filter(item => !item.checked);renderList(dataList);}const complete = function () {const dataList = data.filter(item => item.checked);renderList(dataList);}const resetData = function (checked) {data.forEach(it => {// let item = list.childNodes[it.id].children[0].children[0];let item = Array.from(list.childNodes).filter(node => node.id == it.id)[0];if (item) {let node = item.querySelector(`#input${it.id}`);node.checked = checked;it.checked = checked;}});}const handleInput = function (e) {if (e.key === 'Enter') {const item = new Proxy({id: data.length + 1,checked: false,text: input.value}, {set(target, propKey, value, receiver) {updateNoCompleteNum();return Reflect.set(target, propKey, value, receiver);}});data.push(item);addItem(item);input.value = '';}};const handleCheckAll = function (e) {if (e.target.checked) {// 全选resetData(true);} else {// 全不选resetData(false);}};const handleListClick = function (e) {if (e.target.className === 'item') {const index = Number(e.target.id.slice(5));data[index - 1].checked = e.target.checked;} else if (e.target.className === 'item-close') {const index = e.target.parentNode.parentNode.id;data.splice(index - 1, 1);const node = [...list.childNodes].filter(it => it.id == index)[0];list.removeChild(node);}};input.addEventListener('keydown', handleInput);checkAll.addEventListener('click', handleCheckAll);list.addEventListener('click', handleListClick);const handleRemoveListener = function () {list.removeEventListener('click', handleListClick);checkAll.removeEventListener('click', handleCheckAll);input.removeEventListener('keydown', handleInput);}document.addEventListener('unload', handleRemoveListener);</script>
</body></html>

但是这里renderList是删除当前所有list的节点然后重新构建的,虽然有数据驱动的思想但是这样操作dom是非常消耗性能的,因此做如下变更,通过设置item.style.display

		// 渲染列表const initRender = function (dataList) {dataList.forEach(item => {addItem(item);});}// 利用proxy监听data数组const updateNoCompleteNum = function () {// 等页面更新完成之后data值更新完成获取setTimeout(() => {let noCompleteNum = data.filter(item => !item.checked).length;const noCompleteNode = document.querySelector('#noCompleteNum');noCompleteNode.innerText = noCompleteNum;})}initRender(data);updateNoCompleteNum();const getDisplayHash = function (key, val) {const hash = {};data.forEach(item => {(item[key] === undefined || item[key] === val) && (hash[item.id] = 1);});return hash;}const renderList = function (hash) {for (let i = 0; i < list.children.length; i++) {let item = list.children[i];if (hash[item.id]) {item.style.display = '';} else {item.style.display = 'none'}}}const allToDo = function () {renderList(getDisplayHash());}const noComplete = function () {renderList(getDisplayHash('checked', false));}const complete = function () {renderList(getDisplayHash('checked', true));}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【数据结构】红黑树——领略天才的想法
  • opencv视频抽帧保存图片
  • 云界洞见——基于移动云云数据库MySQL应用实践
  • websocket聊天(全源码)
  • 探索Linux中的神奇工具:探秘tail命令的妙用
  • 【C++/STL】vector(常见接口、模拟实现、迭代器失效)
  • graspnet+Astra2相机实现部署
  • vue3使用Ant-Design组件a-table表格实现多层表头及合并单元格
  • JavaWeb-JS
  • pycharm画图猫和老鼠
  • Jenkins配置(插件/角色/凭证)
  • 文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《考虑分布式光伏高效消纳与负荷损失最小的区域配电网应急资源协同配置策略》
  • 力扣 滑动窗口题目总结
  • javaEE—图书管理系统(基础代码版)
  • 基于Vue的应届毕业生财务管理系统-计算机毕业设计源码82886
  • 【挥舞JS】JS实现继承,封装一个extends方法
  • bearychat的java client
  • Git学习与使用心得(1)—— 初始化
  • java中的hashCode
  • js算法-归并排序(merge_sort)
  • leetcode386. Lexicographical Numbers
  • Object.assign方法不能实现深复制
  • SAP云平台里Global Account和Sub Account的关系
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • SQLServer之索引简介
  • WePY 在小程序性能调优上做出的探究
  • 翻译--Thinking in React
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 将 Measurements 和 Units 应用到物理学
  • 我的面试准备过程--容器(更新中)
  • 小程序开发之路(一)
  • 新版博客前端前瞻
  • 一个JAVA程序员成长之路分享
  • 阿里云服务器如何修改远程端口?
  • 扩展资源服务器解决oauth2 性能瓶颈
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • ​TypeScript都不会用,也敢说会前端?
  • ​字​节​一​面​
  • # windows 运行框输入mrt提示错误:Windows 找不到文件‘mrt‘。请确定文件名是否正确后,再试一次
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • $jQuery 重写Alert样式方法
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (4)Elastix图像配准:3D图像
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (纯JS)图片裁剪
  • (第30天)二叉树阶段总结
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (理论篇)httpmoudle和httphandler一览
  • (十)Flink Table API 和 SQL 基本概念
  • (新)网络工程师考点串讲与真题详解
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • (自用)网络编程
  • **CI中自动类加载的用法总结