赞
踩
效果如图
要求:
<!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)); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。