原生js实现TodoMVC
2020-12-24 10:30
标签:move inner footer 技术 one dom ems image ble 原生js实现TodoMVC 先用html和css写好页面的基本结构样式,代码如下, index.html index.css 此时页面展示如下, 接下来编写index.js,实现TodoMVC的功能,把该文件引入到index.html文件中 最后实现的效果如下, 原生js实现TodoMVC 标签:move inner footer 技术 one dom ems image ble 原文地址:https://www.cnblogs.com/chenguang123/p/13943840.htmlDOCTYPE html>
html lang="en">
head>
meta charset="UTF-8">
title>Documenttitle>
link rel="stylesheet" href="./index.css">
head>
body>
section id="app">
header>
h2>ToDoMVCh2>
input type="text" id="new-todo" class="box" placeholder="What needs to be done?">
header>
section>
div id="todo">
ul>ul>
div class="box card hideCard">
span>span>
input type="radio" name="btn" id="all" checked>
input type="radio" name="btn" id="active">
input type="radio" name="btn" id="completed">
label for="all">alllabel>
label for="active">activelabel>
label for="completed">completedlabel>
div>
div>
section>
footer>
div>
by chenguang123
div>
footer>
section>
body>
html>
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
}
#app {
width: 900px;
min-height: 100%;
background-color: rgb(237, 237, 237);
margin: auto;
overflow: hidden;
}
header h2 {
margin: 20px auto;
text-align: center;
font-size: 32px;
color: gray;
}
#new-todo {
border: none;
outline: none;
}
.box {
position: relative;
box-sizing: border-box;
display: block;
width: 500px;
height: 50px;
padding: 10px 20px;
box-shadow: .5px .5px 3px rgb(132, 132, 132);
font-size: 24px;
margin: auto;
}
.box input {
width: 15px;
height: 15px;
margin: 0 10px;
}
.list button {
position: absolute;
right: 20px;
visibility: hidden;
border: none;
outline: none;
background-color: transparent;
font-size: 24px;
cursor: pointer;
color: rgb(161, 161, 161);
transition: color .5s linear;
}
.list:hover button {
visibility: visible;
}
.list button:hover {
color: gray;
}
.card {
font-size: 16px;
}
.card span {
margin-right: 30px;
}
.card input {
display: none;
}
.card label {
border: 1px solid transparent;
margin: 5px;
cursor: pointer;
transition: border .3s linear;
}
.card label:hover {
border: 1px solid black;
}
.card input:nth-of-type(1):checked ~ label:nth-of-type(1) {
border: 1px solid black;
}
.card input:nth-of-type(2):checked ~ label:nth-of-type(2) {
border: 1px solid black;
}
.card input:nth-of-type(3):checked ~ label:nth-of-type(3) {
border: 1px solid black;
}
footer {
margin: 30px;
text-align: center;
color: gray;
}
.check {
text-decoration: line-through;
color: gray;
}
.d1 {
display: none;
}
.d2 {
display: none;
}
.hideCard {
visibility: hidden;
}
.showCard {
visibility: visible;
}// 添加任务到ul中
var ul = document.querySelector(‘#todo ul‘)
// 添加任务的输入框
var newTodo = document.querySelector(‘#new-todo‘)
// 底部用来显示状态的元素
var card = document.querySelector(‘.card‘)
// 用来显示任务数的元素
var span = document.querySelector(‘.card span‘)
// 全部的任务
var all = document.querySelector(‘#all‘)
// 正在进行的任务
var active = document.querySelector(‘#active‘)
// 完成的任务
var completed = document.querySelector(‘#completed‘)
var app = {
arrList: [], // 保存所有任务
count: 0, // 任务数
init: function () {
// 监听输入框,添加要做的任务
newTodo.onkeyup = function (e) {
if (e.keyCode == 13) {
if (newTodo.value !== ‘‘) {
this.addList(newTodo.value)
newTodo.value = ‘‘
card.classList.replace(‘hideCard‘, ‘showCard‘)
span.innerHTML = this.count + ‘ items left‘
if (all.checked) {
this.showAll()
}
if (active.checked) {
this.showActive()
}
if (completed.checked) {
this.showCompleted()
}
}
}
}.bind(this)
// 监听任务被删除、完成、未完成
ul.onclick = function (e) {
this.change(e)
if (all.checked) {
this.showAll()
}
if (active.checked) {
this.showActive()
}
if (completed.checked) {
this.showCompleted()
}
}.bind(this)
all.onclick = function () {
this.showAll()
}.bind(this)
active.onclick = function () {
this.showActive()
}.bind(this)
completed.onclick = function () {
this.showCompleted()
}.bind(this)
},
change: function (e) {
if (e.target.localName === ‘button‘) {
var i = this.arrList.indexOf(e.target.parentNode)
// 若点击button要删除的任务是未完成的,则count数也要减一
if (!e.target.parentNode.children[0].checked) {
this.count--
span.innerHTML = this.count + ‘ items left‘
}
this.arrList.splice(i, 1)
e.target.parentNode.parentNode.removeChild(e.target.parentNode)
if (this.arrList.length === 0) {
card.classList.replace(‘showCard‘, ‘hideCard‘)
}
} else if (e.target.localName === ‘input‘) {
// 若点击的是input,则判断任务是否完成
if (e.target.checked) {
e.target.parentNode.classList.add(‘check‘)
e.target.parentNode.classList.replace(‘a‘, ‘b‘)
this.count--
span.innerHTML = this.count + ‘ items left‘
} else {
e.target.parentNode.classList.remove(‘check‘)
e.target.parentNode.classList.replace(‘b‘, ‘a‘)
this.count++
span.innerHTML = this.count + ‘ items left‘
}
}
},
addList: function (val) {
var li = document.createElement(‘li‘)
li.classList.add(‘box‘)
li.classList.add(‘list‘)
li.classList.add(‘a‘)
var content = `
${val}
`
li.innerHTML = content
this.arrList.push(li)
ul.appendChild(li)
this.count++
},
/*
类a代表未完成的任务
类b代表已完成的任务
类d2代表隐藏未完成的任务
类d1代表隐藏已完成的任务
addList函数中,给新的任务添加了一个类a;change函数中,当被选中后把类a换成了类b
showActive函数中,要显示未完成的任务,所以要把已完成的任务隐藏,把带有类b的任务,换成了类d1,该类为display: none
该函数中除了要隐藏已完成任务,也要将被隐藏的未完成任务显示出来,把类d2换成类a
showCompleted函数中,要显示已完成的任务,所以要把未完成的任务隐藏,把带有类a的任务,换成了类d2,该类为display: none
该函数中除了要隐藏未完成任务,也要将被隐藏的未完成任务显示出来,把类d1换成类b
*/
showAll: function () {
for (let i = 0; i this.arrList.length; i++) {
this.arrList[i].classList.replace(‘d1‘, ‘b‘)
this.arrList[i].classList.replace(‘d2‘, ‘a‘)
}
},
showActive: function () {
for (let i = 0; i this.arrList.length; i++) {
this.arrList[i].classList.replace(‘d2‘, ‘a‘)
this.arrList[i].classList.replace(‘b‘, ‘d1‘)
}
},
showCompleted: function () {
for (let i = 0; i this.arrList.length; i++) {
this.arrList[i].classList.replace(‘d1‘, ‘b‘)
this.arrList[i].classList.replace(‘a‘, ‘d2‘)
}
}
}
app.init()