用js手搓一个todoList
前言
todoList是什么
那么这个网页主要实现的功能就是:
- 在输入框输入内容敲回车会添加到代办区域
- 点击删除按钮可以将代办区域完成事项删除
- 点击复选框,勾选已完成事项
大家可以自行去感受一下,经常要写计划的同学也可以用这个来记录待完成的事情
----------->todomvc.com/examples/ja…
实现代码
html部分
<body>
<div id="app" class="container">
<h2 class="title">todos</h2>
<div class="input-group">
<div class="label">待办事项</div>
<input type="text" class="content" id="newTodo" placeholder="What you need to be done?">
<button class="btn">新增</button>
</div>
<div class="list">
<ul id="todo-list">
</ul>
</div>
</div>
<script src="./index.js"></script>
</body>
CSS部分
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
background: #f5f5f5;
}
.container {
width: 500px;
height: 500px;
}
.title {
text-align: center;
margin: 10px;
font-style: 30px;
width: 100%;
font-size: 80px;
font-weight: 200;
color: #b83f45;
}
.input-group {
display: flex;
font-size: 20px;
}
.label {
padding: 5px 10px 5px 10px;
}
.btn {
padding: 5px 10px;
margin-left: 10px;
margin-right: 1px;
}
.content {
flex: 1;
font-size: 24px;
}
.item:nth-child(1) {
margin-top: 20px;
}
.flex {
display: flex;
width: 90%;
margin: 0 auto;
align-items: center;
}
.item-check {
margin-right: 20px;
}
.item {
border-bottom: 1px solid #eee;
}
.item-content {
flex: 1;
}
.close {
width: 30px;
height: 30px;
border: 1px solid #000;
font-size: 20px;
text-align: center;
border-radius: 10px;
cursor: pointer;
}
js部分
var todoData = [];
var addTodo = document.querySelector('.btn');
var todoList = document.getElementById('todo-list');
// 新增按钮
function addNewTodo() {
// 获取input中的内容
if (document.getElementById('newTodo').value.trim() != '') {
todoData.push({
id: Math.floor(Date.now()),
title: document.getElementById('newTodo').value,
completed: false
})
// 渲染新的li
render();
}
}
// 将toDoData中的数据渲染出来
function render() {
var str = '';
todoData.forEach(function (item) {
str += `
<li class="item">
<div class="flex">
<input type="checkbox" class="item-check">
<p class="item-content">${item.title}</p>
<span class="close" data-id="${item.id}" >×</span>
</div>
</li>
`
})
todoList.innerHTML = str;
}
addTodo.addEventListener('click', addNewTodo);
todoList.addEventListener('click', delete_list);
function delete_list(event) {
if (event.target.classList.contains('close')) { // 判断点击的元素是否是关闭按钮
var id = event.target.dataset.id; // 获取关闭按钮的 data-id 属性值
for (var i = 0; i < todoData.length; i++) {
if (todoData[i].id == id) {
todoData.splice(i, 1); // 根据 id 从数组中删除对应的待办事项
}
}
render(); // 重新渲染待办事项列表
}
}
重难点思路解析
- html部分的搭建过程,小白同学可以先把内容写死,比如ul中的li,写死一个学习/看电影...,后续编写js部分我们就会发现,谁也不知道后续会发生什么,自然会去更改这一部分的代码。
placeholder
是一个 HTML 特性,用于为输入字段提供提示信息。 它的作用是在输入字段为空时显示一些提示文本,以指导用户输入合适的内容。- css部分,html中许多标签自带内外边距,我们可以通过通配符将内外边距全部改为0,后续需要添加边距的标签可以自行添加。
display: flex;
弹性布局,之前我们有写过一些需要居中对齐的方法,通过各种定位方式,这里我们选用弹性布局就会发现,他实现起来代码更加简洁,用途更加明确。弹性容器默认的主轴为x轴,子容器全部在主轴上对齐,子容器默认继承弹性父容器百分之百的高,不管是不是块级元素,他们都会被放置在一行去。justify-content
主轴方向设置,align-items:
副轴方向设置。flex
属性用于定义元素在剩余空间中的分配比例。flex: 1
表示该元素将占用剩余空间的一份。具体来说,当多个元素都设置了flex
属性时,它们将按照各自的比例来分配剩余空间。flex: 1
通常用于确保某个元素在 Flex 容器中具有相同的伸展能力,与其他元素一起均匀地分配剩余空间。height: 100vh;
是一个 CSS 样式属性,它表示将元素的高度设置为视窗高度(viewport height)的 100%。视窗高度是指浏览器窗口可见区域的高度。通过这种方式,我们就不需要写body的height百分百,再写html的height百分百
最主要的实现思路还是在js部分
- 我们需要获取用户在input中输入的内容,但是不排除用户直接敲了空格,因此我们需要去除空值:
if(document.getElementById('newTodo').value.trim() != '')
- 定义一个数组,用于存放用户输入的内容,当然这个数组中的内容,以对象的形式存在,这样我们可以对每一个内容进行编号,设置一个id属性,有什么东西是独一无二的呢?-->时间,因此我们可以获取当前时间并对其进行向下取整,获取一个独一无二的时间戳,获取到了内容之后,我们就需要将这个内容写进ul中的li,因此接下来就需要对li进行渲染,定义一个render函数做这件事情
- render中如何实现呢?定义一个空的字符串,通过遍历的方式,获取到数组中的每一个对象,用字符串拼接的方式,将li拼接进去,但是这里面的内容是不一样的,我们通过${}变量插值,将对象中的title(用户输入的内容)插入li,以及span标签中也添加了其他的属性,因为我们需要在点击x时,实现删除这个li的功能,我们需要精确识别到是哪一个span。最后通过
todoList.innerHTML = str;
将这个字符串插入html的ul中 event.target.classList.contains('close')
可以判断点击的元素中是否有类名为close的标签,并获取这个标签的data-id属性值,然后通过遍历的方式,查看数组中是否有id与这个data-id相等的值,如果有,那就找到了这一条将其删除,再调用render函数重新渲染页面。
效果
结语
通过这个案例,你是否学到一些实现思路呢?有了思路,再用代码的形式将思路转化为功能,在手敲完成这个功能之后是否获得满满的成就感?
转载自:https://juejin.cn/post/7361468008529068084