大家好,今天我们要一起来实现一个类似于记事本的网页。记事本是一个非常常见且实用的工具,它可以帮助我们记录待办事项、想法和备忘录。通过使用JavaScript,我们将实现一个简单的待办事项记录网页,让我们一步步来完成这个有趣的项目吧!
前端学习之路:
今天我们要用JavaScript实现上述所示页面的基本功能,带大家做一个类似于记事本的网页。首先我们要先实现这个页面的基本框架也就是HTML,我们可以从上图逐步拆分它的框架****:
如下图所示:
可以看出,拆分完的框架非常清晰明了,大家在初步写HTML代码时,也可以用这种方法先去拆分出一个比较清楚的大致框架,再去编写HTML代码,俗话说的好,磨刀不误砍柴功。
HTML
待办事项框的HTML代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="app" class="todo">
<div class="title">todos</div>
<div class="input-group">
<div class="label">待办事项</div>
<input type="text" class="content" id="newTodo">
<button class="btn">新增</button>
</div>
<ul class="list">
</ul>
</div>
<script src="./index.js"></script>
</body>
</html>
对于下拉框列表中的框架又可以在进行细分:
列表中的HTML代码如下:
<li class="list-item">
<input type="checkbox" class="item-check" id="">
<p class="item-content">${item.content}</p>
<span class="close" data-id="${item.id}" data-action="remove">✖</span>
</li>
css
做好具体框架后,我们就要给HTML加上对应的css样式,由于我这里做的是比较简便的页面,所以样式也比较少;具体如下:
/*
设置全局样式
*/
*{
margin: 0; /* 设置外边距为0 */
padding: 0; /* 设置内边距为0 */
}
/*
设置 body 样式
*/
body{
height: 100vh; /* 设置高度为视窗高度 */
display: flex; /* 使用弹性布局 */
justify-content: center; /* 水平居中 */
}
/*
设置 todo 容器样式
*/
.todo{
width: 500px; /* 设置宽度为500像素 */
height: 500px; /* 设置高度为500像素 */
margin-top: 30px; /* 顶部外边距为30像素 */
}
/*
设置标题样式
*/
.title{
font-size: 50px; /* 设置字体大小为50像素 */
text-align: center; /* 文本居中对齐 */
color: red; /* 文本颜色为红色 */
}
/*
设置输入框组样式
*/
.input-group{
display: flex; /* 使用弹性布局 */
font-size: 30px; /* 设置字体大小为30像素 */
}
/*
设置内容样式
*/
.content{
flex: 1; /* 占据剩余空间 */
font-size: 20px; /* 设置字体大小为20像素 */
}
/*
设置标签样式
*/
.label{
padding: 10px; /* 设置内边距为10像素 */
}
/*
设置按钮样式
*/
.btn{
width: 80px; /* 设置宽度为80像素 */
font-size: 30px; /* 设置字体大小为30像素 */
margin-left: 10px; /* 左侧外边距为10像素 */
}
/*
设置列表项样式
*/
.list-item{
display: flex; /* 使用弹性布局 */
padding: 20px; /* 设置内边距为20像素 */
border-bottom: 1px solid #aaa; /* 底部边框为1像素实线,颜色为灰色 */
font-size: 26px; /* 设置字体大小为26像素 */
align-items: center; /* 垂直居中对齐 */
}
/*
设置复选框样式
*/
.item-check{
width: 30px; /* 设置宽度为30像素 */
height: 30px; /* 设置高度为30像素 */
}
/*
设置内容样式
*/
.item-content{
flex: 1; /* 占据剩余空间 */
margin: 0 10px; /* 左右外边距为10像素 */
}
/*
设置关闭按钮样式
*/
.close{
display: none; /* 初始状态下不显示 */
}
/*
设置鼠标悬停时关闭按钮显示样式
*/
.list-item:hover .close{
display: block; /* 当鼠标悬停在列表项上时显示关闭按钮 */
}
其中有一些样式需要我们注意;
flex: 1; /* 占据剩余空间 */;表示的是该子容器将会按照父容器的大小进行1:1的伸缩,也就意味着会占据掉父容器中的剩余空间。
:hover 是 CSS 伪类选择器之一,它用于指定鼠标悬停在元素上时的样式。
当用户将鼠标悬停在具有 :hover 伪类的元素上时,可以应用指定的样式。这使得我们能够在用户与页面交互时改变元素的外观。
例如,可以使用 :hover 来在鼠标悬停在链接上时改变链接的颜色,或者在鼠标悬停在按钮上时改变按钮的背景色等。
在上面提到的CSS代码中,.list-item:hover .close 表示当鼠标悬停在类为 list-item 的元素上时,应用 .close 类的样式。
当以上都已经完成好后;就能得到一个大概的页面:
js
最后我们需要通过js代码来实现页面上的一些功能;
新增
首先我们要实现页面上新增按钮的功能:点击新增按钮就能增加一个待办事项todo的列表;对此我们要通过编程思维先写出解决方案的伪代码:
// 用户每次创建一个todo,就存进数组
// 循环数组,生成数组长度相同的li结构
我们可以新建一个数组,并且把每次点击新增按钮后生成的todo放进数组里面;然后再通过循环数组去动态地在HTML代码中添加列表li的结构。
首先定义全局变量,数组todoData,通过querySelector方法获取新增按钮和列表容器;
var todoData = []
var addTodo = document.querySelector('.btn')
var todoList = document.querySelector('.list')
对于新增按钮,我们首先要进行判空,判断输入框中是否有值;如果不为空的话,再往数组中用push()方法添加进去;添加的对象主要包括三部分:事件的id(用当前时间设置)以便于区分和删除;事件的内容content(通过getElementById和value方法获取输入框的内容);事件的状态(用布尔型Boolean区分)。
代码如下:
// 新增按钮的点击
function addNewTodo(){
// 判断 input 框是否有值
if (document.getElementById('newTodo').value !== '') {
todoData.push({
id: Date.now(),
content: document.getElementById('newTodo').value,
completed: false
})
// 渲染列表
render()
document.getElementById('newTodo').value = ''
}
}
添加完成后,还要对页面进行渲染,把新增的事项列表给渲染在页面上,对此我们还要编写render()方法,每次新增完事项后,还需要把输入框中的内容清空,只需把输入框的值赋为空即可。
render():把新增todo添加到数组中后,再对数组进行遍历,把li列表结构添加到HTML中即可。通过字符串的拼接再调用innerHTML方法添加。
function render() {
var str = ''
for(var i = 0; i < todoData.length; i++){
// todoData[i] str = str + 1 ==> str += 1
var item = todoData[i]
str += `<li class="list-item">
<input type="checkbox" class="item-check" id="">
<p class="item-content">${item.content}</p>
<span class="close" data-id="${item.id}" data-action="remove">✖</span>
</li>`
}
// 往ul中植入str
todoList.innerHTML = str
}
${item.content},${}通常表示的是一个占位符,用来表示需要被替换的部分;在上述代码中可以看到,item.content表示的就是数组中一个对象的内容属性。
写完以上两种方法之后还要通过事件监听来调用函数:
addTodo.addEventListener('click',addNewTodo)
当每次点击新增按钮时就会调用addNewTodo方法新增事项;实现如下效果:
删除
实现完新增效果后,我们还要实现对待办事项的删除功能;通过点击✖能够删除吃饭事项所在的列表结构。 为了实现此功能,我们可以给‘✖’这个符号的标签span上人为地给它添加上id以及action的属性;然后再通过span上id值与数组中对象的id值配对,找到需要删除事项的下标进行删除操作。
span标签:
<span class="close" data-id="${item.id}" data-action="remove">✖</span>
removeTodo():
function removeTodo(e) {
// console.log(e.target);
if (e.target.dataset.action=="remove") {
// 拿到当前这个span上的id值,
var id = e.target.dataset.id
// 找到数组中哪个对象中的id和这个span的id相等,
// 找出它的下标,按照数组中的下标移除数组中的元素
todoData.forEach(function(item,index){
if (item.id == id) {
todoData.splice(index,1)
}
})
render()
}
}
代码中的e.target即是从父容器中获取目标子容器,当点击✖符号时,e.target输出的就是span标签,再通过dataset.action方法获取span标签中的data-action进行删除操作。js中数组的元素删除操作通常用splice完成;todoData.splice(index,1)表示的就是从数组todoData中下标为index的元素开始删除,并且删除一个元素后再连接;也就是删除todoData[index]这个元素。删除完成后也要记得再次渲染列表结构。
这样就能通过点击✖来删除事项了。
以上代码就能实现一个基本的记事本功能了,快去试试吧!