todolist-原生js(ES6)

1、HTML结构

javascript 复制代码
<!DOCTYPE html>
<html>

<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
	<title>ToDoList</title>
	<link rel="stylesheet" href="index.css">
</head>

<body>
	<header>
		<section>
			<label for="title">ToDoList</label>
			<input type="text" id="title" name="title" placeholder="添加ToDo" required="required" autocomplete="off" />
		</section>
	</header>
	<section>
		<h2>正在进行 <span id="todocount"></span></h2>
		<ol id="todolist" class="demo-box">
			<!-- 列表结构 -->
			<!-- <li>
					<input type="checkbox"/>
					<p>123</p>
					<input type="text" autofocus id="vtl" />
					<a href="javascript:;"></a>
				</li> -->
		</ol>
		<h2>已经完成 <span id="donecount"></span></h2>
		<ul id="donelist">
		</ul>
	</section>
	<script type="text/javascript" src="./index.js"></script>
</body>

</html>

2、CSS样式

css 复制代码
body {
	margin: 0;
	padding: 0;
	font-size: 16px;
	background: #CDCDCD;
}

header {
	height: 50px;
	background: #333;
	background: rgba(47, 47, 47, 0.98);
}

section {
	margin: 0 auto;
}

label {
	float: left;
	width: 100px;
	line-height: 50px;
	color: #DDD;
	font-size: 24px;
	cursor: pointer;
	font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}

header input {
	float: right;
	width: 60%;
	height: 24px;
	margin-top: 12px;
	text-indent: 10px;
	border-radius: 5px;
	box-shadow: 0 1px 0 rgba(255, 255, 255, 0.24), 0 1px 6px rgba(0, 0, 0, 0.45) inset;
	border: none
}

input:focus {
	outline-width: 0
}

h2 {
	position: relative;
}

span {
	position: absolute;
	top: 2px;
	right: 5px;
	display: inline-block;
	padding: 0 5px;
	height: 20px;
	border-radius: 20px;
	background: #E6E6FA;
	line-height: 22px;
	text-align: center;
	color: #666;
	font-size: 14px;
}

ol,
ul {
	padding: 0;
	list-style: none;
}

li input {
	position: absolute;
	top: 2px;
	left: 10px;
	width: 22px;
	height: 22px;
	cursor: pointer;
}

p {
	margin: 0;
}

li p input {
	top: 3px;
	left: 40px;
	width: 70%;
	height: 20px;
	line-height: 14px;
	text-indent: 5px;
	font-size: 14px;
}

li {
	height: 32px;
	line-height: 32px;
	background: #fff;
	position: relative;
	margin-bottom: 10px;
	padding: 0 45px;
	border-radius: 3px;
	border-left: 5px solid #629A9C;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.07);
}

ol li {
	cursor: move;
}

ul li {
	border-left: 5px solid #999;
	opacity: 0.5;
}

li a {
	position: absolute;
	top: 2px;
	right: 5px;
	display: inline-block;
	width: 14px;
	height: 12px;
	border-radius: 14px;
	border: 6px double #FFF;
	background: #CCC;
	line-height: 14px;
	text-align: center;
	color: #FFF;
	font-weight: bold;
	font-size: 14px;
	cursor: pointer;
}

footer {
	color: #666;
	font-size: 14px;
	text-align: center;
}

footer a {
	color: #666;
	text-decoration: none;
	color: #999;
}

#it {
	width: 30%;
	margin-left: 30px;
}

@media screen and (max-device-width: 620px) {
	section {
		width: 96%;
		padding: 0 2%;
	}
}

@media screen and (min-width: 620px) {
	section {
		width: 600px;
		padding: 0 10px;
	}
}

3、JS(ES6)内容

javascript 复制代码
var that
class toDolist {
    constructor() {
        that = this; // 保存this
        this.arr = JSON.parse(localStorage.getItem('arr')) || [] // 未完成数据
        this.newArr = JSON.parse(localStorage.getItem('newArr')) || []// 已完成数据
        this.title = document.querySelector('#title') // input框
        this.todolist = document.querySelector('#todolist') // 未完成
        this.donelist = document.querySelector('#donelist') // 已完成
        this.todocount = document.querySelector('#todocount') // 未完成总数
        this.donecount = document.querySelector('#donecount') // 已完成总数

        this.createdView() // 动态创建并渲染页面
        this.Event() // 监听事件
    }
    Event() {
        this.title.addEventListener('keyup', that.titleValue) // 头部输入款监听回车事件
        this.todolist.addEventListener('click', that.topCheck) // 未完成列表单选框和删除事件
        this.donelist.addEventListener('click', that.footCheck) // 已完成列表单选框和删除事件
        this.todolist.addEventListener('dblclick', that.twoClick) // 列表内容双击事件
    }
    createdView() {
        // 动态创建节点根据数据渲染到页面
        // 未完成部分的创建
        this.todolist.innerHTML = ''
        this.arr.forEach(item => {
            var li = document.createElement('li')
            li.id = item.id
            li.innerHTML = `<input type="checkbox" class="ipt" ${item.check ? "checked" : ""}/>
					<p>${item.name}</p>
					<a href="javascript:;"></a>`
            this.todolist.appendChild(li)
        })
        // 已完成部分的创建
        this.donelist.innerHTML = ''
        this.newArr.forEach(item => {
            var tr = document.createElement('li')
            tr.id = item.id
            tr.innerHTML = `<input type="checkbox" class="int"  ${item.check ? "checked" : ""}/>
					<p>${item.name}</p>
					<a href="javascript:;"></a>`
            this.donelist.appendChild(tr)
        })
        // 显示任务数量
        that.todocount.innerHTML = that.arr.length
        that.donecount.innerHTML = that.newArr.length

        // 本地存储
        localStorage.setItem('arr', JSON.stringify(that.arr))
        localStorage.setItem('newArr', JSON.stringify(that.newArr))
    }
    titleValue(e) {
        if (e.keyCode === 13) {
            // 回车创建一组数据
            var obj = {
                id: +new Date(),
                name: that.title.value,
                check: false,
                show: true
            }
            // 判断输入款不能为空
            if (that.title.value == '') {
                alert('输入不能为空')
            } else {
                // 把数据添加到未完成数组
                that.arr.unshift(obj)
                // 回车之后清空输入框内容
                that.title.value = ''
            }
            // 重新调用渲染页面
            that.createdView()
        }
    }
    topCheck(e) {
        // 单选框点击功能
        if (e.target.className == 'ipt') {
            // 拿到当前点击的数据内容的id
            var id = e.target.parentNode.id
            // 通过id改变拿到当前数据
            that.arr.forEach((item, index) => {
                if (item.id == id) {
                    // 改变单选框选中状态
                    item.check = true
                    // 给已完成的数组添加当前数据
                    that.newArr.unshift(that.arr[index])
                    // 删除未完成数组里面的当前数据
                    that.arr.splice(index, 1)
                }
            })
            // 重新调用渲染页面
            that.createdView()
        }
        // 点击删除功能
        if (e.target.tagName == 'A') {
            var id = e.target.parentNode.id
            that.arr.forEach((item, index) => {
                if (item.id == id) {
                    that.arr.splice(index, 1)
                }
            })
            that.createdView()
        }
    }
    footCheck(e) {
        // 逻辑跟上面一样,需要操作的数组反过来就可以了
        // 单选
        if (e.target.className == 'int') {
            var id = e.target.parentNode.id
            that.newArr.forEach((item, index) => {
                if (item.id == id) {
                    item.check = false
                    that.arr.unshift(that.newArr[index])
                    that.newArr.splice(index, 1)
                }
            })
            that.createdView()
        }
        // 删除
        if (e.target.tagName == 'A') {
            var id = e.target.parentNode.id
            that.newArr.forEach((item, index) => {
                if (item.id == id) {
                    that.newArr.splice(index, 1)
                }
            })

            that.createdView()
        }
    }
    twoClick(e) {
        // 双击事件通过冒泡机制精确到具体标签
        if (e.target.tagName == 'P') {
            // 改变p标签内容
            e.target.innerHTML = `<input type="text" value=${e.target.innerText} id="it" />`
            // 双击之后自动获取焦点
            e.target.firstElementChild.focus()
            // 给添加的input标签添加监听事件
            e.target.firstElementChild.addEventListener('keyup', that.iptEnter) // 回车事件
            e.target.firstElementChild.addEventListener('blur', that.iptBlur) // 失焦事件
        }
    }
    iptEnter(e) {
        if (e.keyCode === 13) {
            // 回车失去焦点并触发失焦事件
            e.target.blur()
        }
    }
    iptBlur(e) {
        // 通过id操作当前数组
        var id = e.target.parentNode.parentNode.id
        that.arr.forEach(item => {
            if (item.id == id) {
                item.name = e.target.value
            }
        })
        // 把p标签的内容改回来
        e.target.parentNode.innerHTML = e.target.value

        // 本地存储
        localStorage.setItem('arr', JSON.stringify(that.arr))
        localStorage.setItem('newArr', JSON.stringify(that.newArr))
    }
}
new toDolist()
相关推荐
尘浮生1 分钟前
Java项目实战II基于Spring Boot的光影视频平台(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·maven·intellij-idea
明月看潮生21 分钟前
青少年编程与数学 02-003 Go语言网络编程 15课题、Go语言URL编程
开发语言·网络·青少年编程·golang·编程与数学
南宫理的日知录32 分钟前
99、Python并发编程:多线程的问题、临界资源以及同步机制
开发语言·python·学习·编程学习
逊嘘1 小时前
【Java语言】抽象类与接口
java·开发语言·jvm
Half-up1 小时前
C语言心型代码解析
c语言·开发语言
别拿曾经看以后~1 小时前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
川石课堂软件测试1 小时前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
Source.Liu1 小时前
【用Rust写CAD】第二章 第四节 函数
开发语言·rust
monkey_meng1 小时前
【Rust中的迭代器】
开发语言·后端·rust
余衫马1 小时前
Rust-Trait 特征编程
开发语言·后端·rust