需求
输入待办内容和选择分类 点击添加按钮添加到未完成区域 未完成区域每个待办都有完成和删除按钮 点击删除 待办消失 点击完成按钮 待办到已完成区域 已完成区域每个待办都有删除按钮 点击删除 待办消失
游戏界面
标签结构 html
输入区域
负责接收用户输入的待办
input type=text文本框让用户输入待办内容并且添加placeholder占位符属性 在文本框没有值的时候显示 提示用户输入待办内容select嵌套option标签用来选择待办类型button按钮点击添加待办
显示区域
.area嵌套两个类名为finished和notfinished的div标签分别表示完成区域和未完成区域
代码如下
<!-- 输入区域 -->
<div class="input">
<input type="text" name="" id="" placeholder="输入待办内容">
<select name="" class="group">
<option>工作</option>
<option>生活</option>
<option>学习</option>
</select>
<button class="add">添加</button>
</div>
<!-- 显示区域 -->
<div class="area">
<div class="finished">
<p>已完成</p>
</div>
<div class="notfinished">
<p>未完成</p>
</div>
</div>
层叠样式 css
*通用选择器改变全部的字体为宋体.area的display: flex设置为弹性布局:弹性子元素在弹性盒子内一行显示- 父元素
.area为弹性容器 子元素.finished和.notfinished是弹性子元素 然后再分别设置这两个子元素的设置宽高和边框 button按钮的样式是在网上找了一个
* {
font-family: FangSong;
}
.area {
display: flex;
justify-content: space-evenly;
font-size: 15px;
}
.finished {
border: solid 2px pink;
width: 200px;
height: 400px;
}
.notfinished {
border: solid 2px skyblue;
width: 200px;
height: 400px;
}
/* 这个按钮样式是在网上找的 */
.area button {
background-color: #EA4C89;
border-radius: 8px;
border-style: none;
box-sizing: border-box;
color: #FFFFFF;
cursor: pointer;
display: inline-block;
font-family: "Haas Grot Text R Web", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 10px;
font-weight: 250;
height: 20px;
line-height: 15px;
list-style: none;
margin: 0;
outline: none;
position: relative;
text-align: center;
text-decoration: none;
transition: color 100ms;
vertical-align: baseline;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
}
.area button:hover,
.area button:focus {
background-color: #F082AC;
}
最终布局如下图
获取元素 js
document.querySelector返回指定的css选择器中的第一个元素
- 获取
list元素为输入文本框 add元素为添加按钮group为待办的种类not和done分别代表未完成.notfinished和完成.finished区域
//获取元素
const list = document.querySelector('input')
const add = document.querySelector('.add')
const group = document.querySelector('group')
const not = document.querySelector('.notfinished')
const done = document.querySelector('.finished')
数据分析
每一个待办的内容和html标签结构是一一对应的 所以可以存在对象属性的键值对里 通过按钮的点击事件完成对对象键值对的操作再渲染页面
不用数组的原因 对应索引很麻烦 每次操作数据都要把所有数组的索引都一起操作 处理复杂而且代码冗余
- 未完成区域和完成区域分别用
notText和doneText存储 - 待办的html标签结构用
text字符串来存放 - 待办具体的内容和分类用
value字符串来存放
let notText = {} //未完成
let doneText = {} //完成
let text = '' //list html
let value = '' //list.value+group.value
功能实现
渲染方法
未完成区域
- 遍历
notText对象 将对象属性的值也就是待办的html标签结构累加到not.innerHTML实现渲染
注意这里用
let in渲染无序对象
- 未完成区域有完成和删除按钮 所以每次渲染完都要调用
finsClick()delsClicknot()方法 后续会把未完成区域的完成和删除按钮的点击事件分别写进这两个方法里
//渲染未完成区域
function renderNot() {
//重新渲染未完成区域
not.innerHTML = `<p>未完成</p>`
for (let key in notText) {
not.innerHTML += notText[key]
}
//未完成区域重新渲染之后要重新获取
finsClick()
delsClicknot()
}
完成区域
重新渲染的逻辑和未完成区域相同
- 完成区域的计划只有删除按钮 渲染完只需要调用
delsClickfin()后续的完成区域的删除按钮的点击事件就写在这个方法里
//渲染已完成区域
function renderDone() {
//重新渲染未完成区域
done.innerHTML = `<p>已完成</p>`
for (let key in doneText) {
done.innerHTML += doneText[key]
}
//重新渲染之后要重新获取
delsClickfin()
}
添加按钮点击事件
点击添加按钮把计划和删除完成按钮渲染到未完成区域
- 把列表的html标签(包括完成和删除按钮)放入
text变量 把列表内容+分类字符串拼接放进value变量 - 未完成区域的
notText对象的属性键值对中 key键属性名是value字符串 value值是text字符串 - 更改完之后再 调用
renderNot()方法 根据notText对象渲染页面 - 最后再让
list.value清空 下次输入的时候文本框是没有内容的
//添加按钮点击事件
add.addEventListener('click', function () {
text = `<p>` + list.value + group.value +
`<button class="finish" >完成</button>
<button class="delete" >删除</button>` + `</p>`
value = list.value + group.value
notText[value] = text
//text渲染
renderNot()
list.value = ''
})
添加按钮效果如下
完成按钮点击事件
只有未完成区域有完成按钮
未完成区域的完成按钮
点击按钮把计划和删除按钮渲染到完成区域
- 获取所有完成按钮
- 遍历
fins类数组 给所有完成按钮添加点击事件来操作notText对象 Object.keys(notText)[m]表示notText对象中第m个属性的属性名 里面存放了点击的按钮相对应的待办的具体内容和分类 把这个字符串放进key变量方便使用
Object.keys(obj)方法返回obj数组的属性名key 组成的数组
- 点击完成按钮之后会把计划内容放进完成区域 完成区域是没有完成按钮的 所以这里
text要把完成按钮的标签去掉 再把点击的按钮相对应的待办的具体内容和分类 也就是这里的key变量放进去 - 然后操作对象 完成区域
doneText的key(这里是待办具体内容和分类)属性存放修改过的text再把未完成区域相应的计划也就是用delete把notText的key键值对删掉 - 最后渲染页面 调用
renderNot和renderDone页面 根据对对象的操作 使未完成界面删除这个待办 完成区域渲染上这个待办
注意 未完成区域的完成按钮点击之后 两个区域的对象都会发生变化所以最后要调用
renderNot()和renderDone()两个方法分别渲染页面
//未完成区域的完成按钮
function finsClick() {
//获取所有fins 按钮
let fins = document.querySelectorAll('.finish')
for (let m = 0; m < fins.length; m++) {
fins[m].addEventListener('click', function () {
let key = Object.keys(notText)[m]
//相应的value给text
text = `<p>` + Object.keys(notText)[m] +
`<button class="delete">删除</button>` + `</p>`
//已完成添加
doneText[key] = text
//未完成删除
delete notText[key]
//根据处理完的元素渲染页面
renderNot()
renderDone()
})
}
}
效果如下
删除按钮点击事件
点击删除 把计划删除 两个区域的删除按钮分开写是方便找到按钮相应的对象的key值 完成区域和未完成区域的删除按钮 删除作用到的对象是不一样的 要分开获取
注意 未完成区域和完成区域的删除按钮点击之后 只有这个区域的对象会发生变化所以最后只需要调用一个相应区域的渲染方法来渲染页面就行
未完成区域的删除按钮
- 获取
.notfinished区域所有的删除按钮 这里css选择器选中的是.notfinisheddiv中所有的.delete按钮 - 遍历
dels类数组 给所有未完成区域删除按钮添加点击事件来操作notText对象 - 变量
key存放 未完成区域的相应的属性名 也就是计划内容 delete删除notText对象被点击的相应键值对- 最后根据
notText对象变化 调用renderNot方法渲染未完成区域
//未完成区域删除按钮
function delsClicknot() {
let dels1 = document.querySelectorAll('.notfinished .delete')
for (let m = 0; m < dels1.length; m++) {
dels1[m].addEventListener('click', function () {
key = Object.keys(notText)[m]
delete notText[key]
renderNot()
})
}
}
效果如下
完成区域的删除按钮
这里和未完成区域的删除按钮的思路是一样的
- 获取
.finished区域所有的删除按钮 - 遍历
dels类数组 给所有完成区域删除按钮添加点击事件来操作doneText对象 - 变量
key存放 完成区域的被点击的相应的属性名 这里就是相应的计划内容 delete删除doneText对象相应键值对- 最后根据
doneText对象变化 调用renderDone方法渲染未完成区域渲染完成区域
//完成区域删除按钮
function delsClickfin() {
let dels2 = document.querySelectorAll('.finished .delete')
for (let n = 0; n < dels2.length; n++) {
dels2[n].addEventListener('click', function () {
key = Object.keys(doneText)[n]
delete doneText[key]
renderDone()
})
}
}
效果如下
最终代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>尝试用对象id处理数据</title>
</head>
<body>
<!-- 输入区域 -->
<div class="input">
<input type="text" name="" id="" placeholder="输入待办内容">
<select name="" id="group">
<option>工作</option>
<option>生活</option>
<option>学习</option>
</select>
<button class="add">添加</button>
</div>
<!-- 显示区域 -->
<div class="area">
<div class="finished">
<p>已完成</p>
</div>
<div class="notfinished">
<p>未完成</p>
</div>
</div>
<style>
* {
font-family: FangSong;
}
.area {
display: flex;
justify-content: space-evenly;
font-size: 15px;
}
.finished {
border: solid 2px pink;
width: 200px;
height: 400px;
}
.notfinished {
border: solid 2px skyblue;
width: 200px;
height: 400px;
}
/* 这个按钮样式是在网上找的 */
.area button {
background-color: #EA4C89;
border-radius: 8px;
border-style: none;
box-sizing: border-box;
color: #FFFFFF;
cursor: pointer;
display: inline-block;
font-family: "Haas Grot Text R Web", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 10px;
font-weight: 250;
height: 20px;
line-height: 15px;
list-style: none;
margin: 0;
outline: none;
position: relative;
text-align: center;
text-decoration: none;
transition: color 100ms;
vertical-align: baseline;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
}
.area button:hover,
.area button:focus {
background-color: #F082AC;
}
</style>
<script>
//获取元素
const list = document.querySelector('input')
const add = document.querySelector('.add')
const group = document.getElementById('group')
const not = document.querySelector('.notfinished')
const done = document.querySelector('.finished')
let notText = {} //未完成
let doneText = {} //完成
let text = '' //list html
let value = '' //list.value+group.value
//添加按钮点击事件
add.addEventListener('click', function () {
text = `<p>` + list.value + group.value +
`<button class="finish" >完成</button>
<button class="delete" >删除</button>` + `</p>`
value = list.value + group.value
notText[value] = text
//text渲染
renderNot()
list.value = ''
})
//完成和删除按钮点击事件
//未完成区域的完成按钮
function finsClick() {
//获取所有fins 按钮
let fins = document.querySelectorAll('.finish')
for (let m = 0; m < fins.length; m++) {
fins[m].addEventListener('click', function () {
let key = Object.keys(notText)[m]
//相应的value给text
text = `<p>` + key +
`<button class="delete">删除</button>` + `</p>`
//已完成添加
doneText[key] = text
//未完成删除
delete notText[key]
//根据处理完的元素渲染页面
renderNot()
renderDone()
})
}
}
//未完成区域删除按钮
function delsClicknot() {
let dels1 = document.querySelectorAll('.notfinished .delete')
for (let m = 0; m < dels1.length; m++) {
dels1[m].addEventListener('click', function () {
key = Object.keys(notText)[m]
delete notText[key]
renderNot()
})
}
}
//完成区域删除按钮
function delsClickfin() {
let dels2 = document.querySelectorAll('.finished .delete')
for (let n = 0; n < dels2.length; n++) {
dels2[n].addEventListener('click', function () {
key = Object.keys(doneText)[n]
delete doneText[key]
renderDone()
})
}
}
//渲染未完成区域
function renderNot() {
//重新渲染未完成区域
not.innerHTML = `<p>未完成</p>`
for (let key in notText) {
not.innerHTML += notText[key]
}
//未完成区域重新渲染之后要重新获取
finsClick()
delsClicknot()
}
//渲染已完成区域
function renderDone() {
//重新渲染未完成区域
done.innerHTML = `<p>已完成</p>`
for (let key in doneText) {
done.innerHTML += doneText[key]
}
//重新渲染之后要重新获取
delsClickfin()
}
</script>
</body>
</html>