【前端】前端学习四之JavaScript(Web API -- DOM)

目录

[一、什么是 Web API ?](#一、什么是 Web API ?)

[二、DOM 基本概念](#二、DOM 基本概念)

[三、DOM 的操作](#三、DOM 的操作)

[1. 元素的获取](#1. 元素的获取)

(1)获取匹配的第一个元素:querySelector

(2)获取所有匹配的元素:querySelectorAll

[2. 事件操作](#2. 事件操作)

(1)事件三要素

(2)点击事件:onclick

(3)键盘事件

(4)行内写法&外部写法

[3. 获取/修改元素属性](#3. 获取/修改元素属性)

(1)查看元素属性

(2)元素内容属性:innerHTML,innerText

(3)修改元素属性

[4. 获取/修改表单元素属性](#4. 获取/修改表单元素属性)

(1)主要属性

(2)典型示例

[a. 切换按钮的文本](#a. 切换按钮的文本)

[b. 加减 1](#b. 加减 1)

[c. 实现全选/取消全选按钮](#c. 实现全选/取消全选按钮)

[5. 获取/修改样式属性](#5. 获取/修改样式属性)

(1)行内样式操作

(2)类名样式操作

[6. 节点操作](#6. 节点操作)

(1)创建节点

(2)插入节点

[a. 插入到最后:appendChild](#a. 插入到最后:appendChild)

[b. 插入到指定节点之前:insertBefore](#b. 插入到指定节点之前:insertBefore)

(3)删除节点

四、案例实现

[1. 猜数字](#1. 猜数字)

[2. 表白墙](#2. 表白墙)

[3. 待办事项](#3. 待办事项)


一、什么是 Web API ?

我们学习的JavaScript可以分成三个部分:

  • ECMAScript :简称 ES,这是JavaScript 的核心语法标准。我们上一篇文章介绍的ES。
  • DOM API:用于操作页面结构。DOM 全称是文档对象模型。这是浏览器提供给 JavaScript 的一套接口,专门用来操作网页的内容、结构和样式,主要包含内容 有获取元素,修改内容,修改样式,事件处理
  • BOM API:用于操作浏览器。BOM 全称是浏览器对象模型。这是浏览器提供的一套接口,但它不负责操作网页内容,而是负责操作浏览器窗口本身。

Web API 则是浏览器提供的一套标准接口集合,它主要就包含了 DOM 和 BOM。

而本文我们主要要介绍的就是 BOM。


二、DOM 基本概念

官方定义

DOM( 全称为 Document Object Model ,即文档对象模型) 是一个跨平台、语言中立的接口。它将 HTML 或 XML 文档视为一个由节点(Nodes)组成的树形结构。

  • 文档:指的是整个网页(HTML 文件)。
  • 对象:指的是网页中的每一个部分(标签、属性、文本)都被转换成了一个个"对象"。
  • 模型:指的是这些对象之间的层级关系,这里即是树状结构。

核心思想:一切皆对象

在 DOM 眼中,HTML 里的任何东西都是一个对象,都可以通过编程来操作:

文档本身(即整个网页)是一个对象(通过document表示)。 标签(如 <div>, <p>, <body>)是元素对象。 标签里的文字是文本对象。 标签的属性(如 class, id, src)是属性对象。

DOM 树

浏览器在加载网页时,就会把 HTML 代码解析成一棵倒挂的树。比如以下代码:

html 复制代码
<html>
  <head>
    <title>我的网页</title>
  </head>
  <body>
    <h1>你好</h1>
    <p>这是一个段落</p>
  </body>
</html>

在 DOM 眼中,它就是一棵树,长这样:

注意:其中document 代表的是当前浏览器窗口中加载的整个 Web 页面

所以在 DOM 眼中,我们对这个页面进行的操作,其实就是对这个树进行增删查改。


三、DOM 的操作

1. 元素的获取

这是操作 DOM 的第一步,你需要先"选中"你要操作的对象。DOM 提供了多种查找元素的方法,我们最常用的就是通过 CSS 选择器获取,即使用 querySelector 或 querySelectorAll ,其他方法都比较麻烦。

(1)获取匹配的第一个元素:querySelector

使用语法

javascript 复制代码
<script>
    let element = document.querySelector(selectors);
</script>

说明:

  • document:表示整个 HTML 文档对象。
  • element:返回值。如果找到匹配的元素,则返回该 DOM 元素对象;如果没有找到匹配的元素,则返回 null。
  • querySelector():表示获取与 selectors 匹配的第一个元素。
  • selectors:这是一个字符串。表示一个或多个 CSS 选择器,比如标签选择器,类选择器,id选择器等等。它必须严格按照 CSS 的语法规则来写,正因为参数是选择器,所以一定要通过特殊符号指定是哪种选择器.。具体使用等等可以看以下示例。

使用示例:

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>
        <style>
            .red {
                color: red;
            }
            #sleep {
                color: green;
            }
        </style>
    </head>
    <body>
        <div class="red">
            <p>这是第1段文字</p>
        </div>

        <div id="sleep" >
            <p>这是第2段文字</p>
        </div>

        <div>
            <p>这是第3段文字</p>
        </div>

    </body>
    <script>
        // 获取类名为 .header 的第一个元素
        let ele1 = document.querySelector('.red');

        // 获取 ID 为 #sleep 的元素
        let ele2 = document.querySelector('#sleep');

        // 获取 div 内部的第一个 p 标签
        let ele3 = document.querySelector('div p');
    </script>
</html>

从这里我们可以看出:selectors的取值为:如果是通过类选择器获取,则需要以 . 开头,如果是id选择器,则需要以 # 开头,如果是单独获取选择器,则就写对应标签即可, ...... 。

返回值说明

通过querySelector获取元素。

  • 找到了匹配的元素:返回页面中符合该 CSS 选择器的第一个元素对象(Element),即一个真实的 DOM 元素对象。
  • 没有找到任何匹配的元素:返回 null 。

示例:

(2)获取所有匹配的元素:querySelectorAll

和上面的querySelector用法很类似。

使用语法

html 复制代码
<script>
    let element = document.querySelectorAll(selectors);
</script>

它可以获取所有与 selectors 匹配的元素。

返回值说明

当使用 document.querySelectorAll('选择器') 时:

  • 如果页面上匹配的选择器,则会返回一种NodeList 结构(里面装的是选中的所有 Element 对象),它也是一种对象类型。
  • 如果页面上没有匹配的选择器,则它不会报错,也不会返回 null,它会返回一个空的 NodeList

示例:

我们可以通过下标来依次获取它们。比如这里的 elems1[0] 表示的就是"<p>这是第1段内容</p>"。


2. 事件操作

用户在页面中的一些操作(如点击、选择、修改等)都会在浏览器中触发相应的事件。这些事件可以被 JavaScript 监听和处理,从而实现更复杂的交互功能。例如,在一个页面中点击"注册"按钮,这会触发一个"点击事件";当 JavaScript 捕获到这个事件后,页面就可以跳转到注册页面,这就是一个典型的交互操作。

而本小节,我们就来看看怎么实现这个事件的功能。在前端中,我们的事件有很多,链接:HTML DOM 事件 ,但是这里我们介绍其中常见的即可(其他的可以类似理解)。

(1)事件三要素

认识事件,我们首先需要知道事件三要素

  • 事件源: 即**触发事件的对象,**哪个元素触发的
  • 事件类型: 即发生了什么操作,也就是触发事件的"具体行为"是什么?是点击, 选中, 还是修改?
  • 事件处理程序: 即事件发生后要执行的代码 ,也就是"做什么"来响应用户的操作。它是一个函数,当事件在事件源上被触发时,这个函数就会被自动调用。

我们在JS中的事件操作就是根据这三点来实现的。

(2)点击事件:onclick

JavaScript 中最基础、最直观的点击事件处理方式 就是onclick 。它是一个属性。使用语法为: 元素.onclick = 函数 ,它的作用是:当用户点击某个元素时,执行指定的函数及代码。

示例:比如我们要实现点击一个按钮,然后就会出现一个弹框。(当然不只是按钮,对于其他的元素如文本,盒子等等也可以有点击事件)

实现代码如下:

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>
    </head>
    <body>
        <input type="button" value="这是一个按钮"> 
    </body>
    <script>
        // 获取事件源
        let btn = document.querySelector('input');
        // 绑定事件类型-点击事件
        btn.onclick = function () {
            // 事件处理程序
            alert("我点击了这个按钮");
            
            // ......
        }
    </script>
</html>

实现效果:

解释:当我们点击这个按钮时,浏览器会监听到这个事件,从而执行对应的代码。

所以,如果我们想实现点击某个元素时,拥有对应的实现操作,就可以直接在 onclick 后面的函数中实现具体的代码即可。

缺陷:同一个元素的 onclick 只能存一个函数。如果你写了两次,后面的会覆盖前面的。

(3)键盘事件

一般就是这三个:

事件 描述
onkeydown 当用户正在按下键时,发生此事件。
onkeypress 当用户按了某个键时,发生此事件。
onkeyup 当用户松开键时,发生此事件。

以键盘被按下为例 :在一个文本框中,按下按键,会在控制台显示出"键盘正在被按下",其代码和运行结果如下所示:

补充

如果想要知道按下的是什么按键,则我们在当前这个函数中函数的第一个位置声明参数,来获取当前这个事件里面所有的属性或信息(假设为event),然后我们就可以使用event.key就可以获取,使用示例:

注意:不是所有键(例如 Alt、Ctrl、shft、Esc)都会在所有浏览器中触发 onkeypress 事件。如需只检测用户是否按下了某个键,请改用 onkeydown 事件,因为它适用于所有键,同时使用以下链接中的属性获取:HTML DOM KeyboardEvent

(4)行内写法&外部写法

我们上面的事件绑定写法都是外部写法(常用的方法)。其实还可以直接在HTML中绑定事件按,但是这种方法并不常用。

行内写法 就是:直接在 HTML 标签里写 on + 事件名 的属性,然后再在这个属性里写 JS 代码或调用函数。使用示例:

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>
    </head>
    <body>
        <!-- 直接在 onclick 属性里写 JS 代码 -->
        <input class="btn1" type="button" value="这是第1个按钮" onclick="alert('你好!')">

        <br><br>
        <!-- 直接在 onclick 属性里调用函数 -->
        <input class="btn1" type="button" value="这是第2个按钮" onclick="SayHello()">
    </body>
    <script>
        //绑定按钮2的点击事件的函数代码
        function SayHello()
        {
            alert('Hello!');
        }
    </script>
</html>

运行结果的这两个按钮都会有点击事件,如下所示:

外部写法:完全由JS代码完成,通过选择器找到元素并绑定事件,再实现这个事件的函数功能。这种方法是我们比较常用的。使用示例:

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>
    </head>
    <body>
        <!-- 完全由JS代码完成,通过选择器找到元素并绑定事件 -->
        <input type="button" value="这是1个按钮">
    </body>
    <script>
        // 1.获取事件源
        let btn = document.querySelector('input');
        // 2.绑定事件类型
        btn.onclick =  function()
        {
            // 3.实现事件功能
            alert('Hello!');
        }
    </script>
</html>

这段代码的运行结果和上面的按钮2是一样的。

3. 获取/修改元素属性

(1)查看元素属性

我们上面通过querySelector、querySelectorAll 获取到元素,其实是有很多属性的,而这些属性也决定了这个元素在浏览器上呈现出什么样的效果。

查看所有属性

我们可以通过 console.dor(元素名) 就可以在控制台看到这个元素的所有属性,示例:

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>
    </head>
    <body>
        <input type="button" value="这是一个按钮">
    </body>
    <script>
        let btn = document.querySelector('input');
        console.dir(btn);
    </script>
</html>

运行结果:

查看指定属性

我们也可以通过元素名.属性名,来获取这个元素的属性。这里我们通过控制台打印来观察,示例;

(2)元素内容属性:innerHTML,innerText

innerHTML 和 innerText 都是用来获取或设置网页元素内容的,但它有点区别:

  • innerHTML:返回元素内所有的 HTML 代码(包括标签、空格和换行)
  • innerText:只返回元素及其子元素的可见文本,自动去除 HTML 标签

验证:

(3)修改元素属性

前面我们知道在HTML中的元素都是有自己的属性的,那么我们是可以修改这些属性的,就会改变原本页面的内容。

示例:

4. 获取/修改表单元素属性

(1)主要属性

表单(主要是指 input 标签)的以下属性都可以通过 DOM 来修改:

  • value:获取或设置表单的值,它代表了用户目前在输入框里输入的内容,或者你通过代码预设的内容。
  • disabled:禁用状态 。这是一个 布尔属性。 true:元素被禁用 ;false:元素可用。
  • checked:选中状态(专用于单选/复选框) ,这也是一个 布尔属性,true:被勾选。 false:未勾选。
  • selected:选中状态(专用于下拉菜单) ,同样是 布尔属性。
  • type:输入框的类型 ,这个属性可以获取或修改 <input> 的类型。

(2)典型示例

a. 切换按钮的文本

这是个播放按钮,让其可以在 "播放" - "暂停" 之间切换。

实现代码:

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>
    </head>
    <body>
        <input type="button" value="播放">
    </body>
    <script>
        let btn = document.querySelector('input');

        // 绑定点击事件
        btn.onclick = function() {
            if(btn.value == "播放")
            {
                btn.value = "暂停";
            }
            else
            {
                btn.value = "播放";
            }
        }
    </script>
</html>

运行结果:

b. 加减 1

使用一个输入框输入初始值(整数),每次点击按钮, 值可以 + 1 和 - 1 。

实现代码:

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>
    </head>
    <body>
        <input type="text" id="text" value="0">
        <input type="button" id="btn1" value='点我+1'>
        <input type="button" id="btn2" value='点我-1'>
    </body>
    <script>
        let text = document.querySelector('#text');
        let btn1 = document.querySelector('#btn1');
        let btn2 = document.querySelector('#btn2');

        // 加 1
        btn1.onclick = function Add() {
            let num = parseInt(text.value);
            text.value = num + 1;
        }
        // 减 1
        btn2.onclick = function Sub() {
            let num = parseInt(text.value);
            text.value = num - 1;
        }
    </script>
</html>

实现结果:

c. 实现全选/取消全选按钮

实现代码:

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>
    </head>
    <body>
        <input type="checkbox" id="all">全选 <br>
        <input type="checkbox" class="select">选项1 <br>
        <input type="checkbox" class="select">选项2 <br>
        <input type="checkbox" class="select">选项3 <br>
        <input type="checkbox" class="select">选项4 <br>
    </body>
    <script>
        // 1. 获取到元素
        let all = document.querySelector('#all');
        let select = document.querySelectorAll('.select');

        // 2. all按钮点击后选中全部
        all.onclick = function() {
            for(let i = 0; i < select.length; i++)
            {
                select[i].checked = all.checked;
            }
        }

        // 3. select按钮的点击事件
        for(let i = 0; i < select.length; i++)
        {
            // 每次点击,都判断一下是否是全都选中了
            select[i].onclick = function() {
                all.checked = IsSelectAll(select); // 判断是否全选
            }
        }

        // 实现IsSelectAll函数:核实是否全选
        function IsSelectAll(select) {
            for(let i = 0; i < select.length; i++)
            {
                if(select[i].checked == false) return false;
            }
            return true;
        }
    </script>
</html>

实现结果:

5. 获取/修改样式属性

样式属性,也就是CSS中指定给元素的属性,都可以通过JS来修改。

(1)行内样式操作

行内样式操作也就是说,它只能对行内的样式进行操作。行内样式即:通过style属性直接在标签上指定的样式,优先级很高的一种设置样式的方法。

使用语法:

javascript 复制代码
// 方法1:
元素名.style.[属性名] = [属性值]; 

// 方法2:
元素名.style.cssText = [属性名+属性值];
  • 方法1中的[属性名]必须使用小驼峰命名法(使用 驼峰命名 的方式和 CSS 属性对应的),例如: font-size => fontSize, background-color => backgroundColor 等。
  • 方法2中的[属性名],写的格式跟我们在 CSS 文件里写的一模一样

示例:实现点击文字则放大字体的效果

实现代码(两种方法):

实现效果:

注意:这种方法只能对行内的样式有效,对于其他内联样式则无效。

(2)类名样式操作

对于其他内联样式,需要使用类名样式操作,这种方的思路是:不直接修改具体的样式属性(如颜色、大小),而是通过切换"类名"来间接改变样式

使用语法:

javascript 复制代码
元素名.className = [CSS 类名];

其中[CSS 类名]:表示一个字符串,是指在 CSS 文件中定义的类选择器名称。

说明:之所以叫 className 而不是 class,是因为 class 是 JavaScript 的保留关键字(用于定义类),所以在早期的 DOM 标准中,使用 className 来代表 HTML 中的 class 属性。

代码示例: 开启夜间模式

效果:点击页面切换到夜间模式(背景变成黑色),再次点击恢复日间模式(背景变成白色)

代码实现:

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>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            html,
            body {
                width: 100%;
                height: 100%;
            }
            .light {
                background-color: white;
                color: black;
                width: 100%;
                height: 100%;
            }
            .dark {
                background-color: black;
                color:white;
                width: 100%;
                height: 100%;
            }
        </style>
    </head>
    <body>
        <!-- 默认为日间模式 -->
        <div class="light">
            这是一大段话。 <br>
            这是一大段话。 <br>
            这是一大段话。 <br>
            这是一大段话。 <br>
            这是一大段话。 <br>
        </div>
    </body>
    <script>
        let elems = document.querySelector('div');
        elems.onclick = function() {
            if(elems.className == "light")
            {
                // 如果是白天模式,就切换成夜间模式
                elems.className = "dark";
            }
            else
            {
                // 如果是夜间模式,就切换成白天模式
                elems.className = "light";
            }
        }
    </script>
</html>

代码示例:

6. 节点操作

(1)创建节点

我们节点的种类有多种,其中主要创建的节点是元素节点,如下所示:

使用 document.createElement('标签名') 创建一个新的元素对象。此时它只存在于内存中,页面上还看不到。

代码示例:

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>
    </head>
    <body>
        
    </body>
    <script>
        // 创建一个<h1>节点
        let elems1 = document.createElement('h1');
        // 创建一个<div>节点
        let elems2 = document.createElement('div');
    </script>
</html>

此时发现,虽然创建出新的 h1 和 div 了, 但是 div 并没有显示在页面上。这是因为新创建的节点并没有加入到 DOM 树中。

注意:

上面介绍的只是创建元素节点, 还可以使用:

  • createTextNode 创建文本节点
  • createComment 创建注释节点
  • createAttribute 创建属性节点

具体创建什么样的还是要根据我们的需求而定,我们主要还是以创建元素节点为主。

(2)插入节点

上面我们创建了一个节点,但是只是创建了一个节点,它只存在于内存中,页面上还看不到,所以我们呢还需要将它插入到我们的DOM树中才行。插入方法有两种:

a. 插入到最后:appendChild

使用 appendChild 会将节点插入到指定节点的最后一个孩子之后

语法:

javascript 复制代码
parent.appendChild(newNode)

其中parent表示要插入位置的所在的元素,newNode则表示想要插入的元素。

特点: 如果 newNode 已经存在于文档中,它会被移动到新的位置(从旧位置删除,添加到新位置)。

示例:

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>
    </head>
    <body>
        <div id="container">
            <p>这是第1段话</p>
            <p>这是第2段话</p>
            <p>这是第3段话</p>
            <p>这是第4段话</p>
        </div>
    </body>
    <script>
        // 创建一个<div>节点
        let elems = document.createElement('div');
        // 设置属性
        elems.id = "mydiv";
        elems.className = "box";
        elems.innerHTML = "你好!";

        // 获取要插入的位置
        let pos = document.querySelector('#container');
        // 将节点插入到指定pos的最后一个孩子之后
        pos.appendChild(elems);
    </script>
</html>

运行结果:

b. 插入到指定节点之前:insertBefore

如果你需要把节点插入到中间某个位置,而不是末尾,就可以用这个方法

语法:

javascript 复制代码
parent.insertBefore(newNode, referenceNode)

参数:

  • parent:表示我们要插入的位置是在parent这个节点中。
  • newNode:表示要插入的新节点。
  • referenceNode:参考节点(新节点会插在这个节点的前面)。

注意: 如果 referenceNode 为 null,则当前插入方法的效果等同于 appendChild。同样,如果针对一个节点插入两次, 则只有最后一次生效(相当于把元素移动了)

示例:

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>
    </head>
    <body>
        <div id="container">
            <p>这是第1段话</p>
            <p class="p2">这是第2段话</p>
            <p>这是第3段话</p>
            <p>这是第4段话</p>
        </div>
    </body>
    <script>
         // 创建一个<div>节点
        let elems = document.createElement('div');
        // 设置属性
        elems.id = "mydiv";
        elems.className = "box";
        elems.innerHTML = "我是新节点";

        // 获取要插入的位置
        let pos = document.querySelector('#container');
        // 在将节点插入到指定节点之前
        pos.insertBefore(elems, document.querySelector('.p2')); // 插在第二段话之前
    </script>
</html>

运行结果:

(3)删除节点

删除节点的操作通常是由"父节点"发起的,所以如果我们要删除一个节点,我们就必须先获取到要删除节点的父节点,力气保证通过父节点来调用。

删除节点是传统方法是通过removeChild来实现的。使用语法为:

html 复制代码
parent.removeChild(childNode)

其中parent就是找到你要删除节点的父亲,然后调用父亲的removeChild方法,告诉父亲你要删的是childNode。

示例:

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>
    </head>
    <body>
        <div id="container">
            <p class="p1">这是第1段话</p>
            <p class="p2">这是第2段话</p>
            <p class="p3">这是第3段话</p>
            <p class="p4">这是第4段话</p>
        </div>
    </body>
    <script>
        // 获取我们要删除的节点
        let elems = document.querySelector('.p2');
        // 获取它的父亲节点
        let parent = document.querySelector('#container');

        // 删除class = 'p2'这个节点
        parent.removeChild(elems);
    </script>
</html>

运行结果:

注意事项:

  • 被删除节点只是从 dom 树被删除了,但是仍然在内存中,可以随时加入到 dom 树的其他位置。
  • 如果上例中的 childNode 节点不是 parent 节点的子节点,则该方法会抛出异常。

四、案例实现

1. 猜数字

实现代码:

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>
    </head>
    <body>
        <button type="button" id="reset">重新开始一局游戏</button>
        <br>
        请输入要猜的数字:<input type="text" id="number" value="0">
        <button type="button" id="guess">猜</button>
        <br>
        已经猜的次数:<span id="count">0</span>
        <br>
        提示:<span id="result"></span>
    </body>
    <script>
        // 随机生成一个 1-100 的数字
        var guessNumber = Math.floor(Math.random() * 100) + 1; // 设置一个 1 - 100 之间的数

        // 获取上面的元素
        let guess_num = document.querySelector('#number'); // 输入的要猜的数字
        let guess_cnt = document.querySelector('#count'); // 猜的次数
        let guess_res = document.querySelector('#result'); // 猜的结果数什么

        // 1.实现 重新开始 的按钮的点击事件
        let reset_btn = document.querySelector('#reset');
        reset_btn.onclick = function() 
        {
            // 具体效果:重置数据
            guessNumber = Math.floor(Math.random() * 100) + 1; // 重置猜的最终结果

            guess_num.value = 0; // 输入框的数据
            guess_cnt.innerHTML = 0; // 猜测的次数
            guess_res.innerHTML = ""; // 提示信息
        }
        
        // 2.实现 猜 按钮的点击事件
        let guess_btn = document.querySelector("#guess");
        guess_btn.onclick = function() 
        {
            // 具体效果:判断猜的对不对+增加猜测次数
            let data = parseInt(guess_num.value);
            if(data > guessNumber)
            {
                guess_res.innerHTML = "猜大了!";
            }
            else if(data < guessNumber) 
            {
                guess_res.innerHTML = "猜小了!";
            }
            else
            {
                guess_res.innerHTML = "恭喜你,猜对了!";
            }

            // 增加猜测次数
            guess_cnt.innerHTML = parseInt(guess_cnt.innerHTML) + 1;
        }
    </script>
</html>

实现效果:

2. 表白墙

该部分设计内容有点多,我这里分成三部分介绍

结构设计

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>
    </head>
    <body>
        <div>
            <h1>表白墙</h1>
            <div>
                <p>输入后点击提交, 会将信息显示在表格中</p>
            </div>
            <div>
                <span>谁: </span>
                <input type="text">
            </div>
            <div>
                <span>对谁: </span>
                <input type="text">
            </div>
            <div>
                <span>说什么: </span>
                <input type="text">
            </div>
            <div>
                <input type="button" value="提交">
            </div>
        </div>
    </body>
</html>

样式设计(CSS样式设计)

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>
        <style>
            * {
                /* 去掉各个标签的边距 */
                margin: 0px;
                padding: 0px;
            }
            .container {
                width: 400px;
                margin: 0 auto; /* 居中 */
            }
            h1 {
                text-align: center;
                margin-top: 20px;
                margin-bottom: 20px;
            }
            p {
                text-align: center;
                color: grey;
                margin-bottom: 10px;
            }

            .div1 {
                height: 50px;
                /* 弹性布局 */
                display: flex;
                justify-content: center;
                align-items: center;
            }
            .edit {
                margin-bottom: 20px;
                width: 250px;
                height: 30px;
            }
            span {
                width: 100px;
                margin-bottom: 20px;
                font-size: 20px;
            }
            .submit {
                width: 360px;
                height: 40px;
                background-color: rgb(255, 158, 1);
                color: white;
                border: none;
                border-radius: 5px;
                font-size: 20px;
            }
            .submit:active {
                background-color: greenyellow; /*鼠标按下时的颜色*/
            }
        </style>
    </head>
    <body>
        <div class="container">
            <h1>表白墙</h1>
            <p>输入后点击提交, 会将信息显示在表格中</p>
            <div class="div1">
                <span>谁: </span>
                <input type="text" class="edit">
            </div>
            <div class="div1">
                <span>对谁: </span>
                <input type="text" class="edit">
            </div>
            <div class="div1">
                <span>说什么: </span>
                <input type="text" class="edit">
            </div>
            <div class="div1">
                <input type="button" value="提交" class="submit">
            </div>
        </div>
    </body>
</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>
        <style>
            * {
                /* 去掉各个标签的边距 */
                margin: 0px;
                padding: 0px;
            }
            .container {
                width: 400px;
                margin: 0 auto; /* 居中 */
            }
            h1 {
                text-align: center;
                margin-top: 20px;
                margin-bottom: 20px;
            }
            p {
                text-align: center;
                color: grey;
                margin-bottom: 10px;
            }

            .div1 {
                height: 50px;
                /* 弹性布局 */
                display: flex;
                justify-content: center;
                align-items: center;
            }
            .edit {
                margin-bottom: 20px;
                width: 250px;
                height: 30px;
            }
            span {
                width: 100px;
                margin-bottom: 20px;
                font-size: 20px;
            }
            .submit {
                width: 360px;
                height: 40px;
                background-color: rgb(255, 158, 1);
                color: white;
                border: none;
                border-radius: 5px;
                font-size: 20px;
            }
            .submit:active {
                background-color: greenyellow; /*鼠标按下时的颜色*/
            }
        </style>
    </head>
    <body>
        <div class="container">
            <h1>表白墙</h1>
            <p>输入后点击提交, 会将信息显示在表格中</p>
            <div class="div1">
                <span>谁: </span>
                <input type="text" class="edit">
            </div>
            <div class="div1">
                <span>对谁: </span>
                <input type="text" class="edit">
            </div>
            <div class="div1">
                <span>说什么: </span>
                <input type="text" class="edit">
            </div>
            <div class="div1">
                <input type="button" value="提交" class="submit">
            </div>
        </div>
    </body>
    <script>
        let btn = document.querySelector('.submit');
        btn.onclick = function() {
            let edits = document.querySelectorAll('.edit'); // 获取我们输入信息的元素
            // 拿到信息
            let name1 = edits[0].value;
            let name2 = edits[1].value;
            let message = edits[2].value;

            // 创建新节点,插入进入
            let new_div = document.createElement('div');
            new_div.className = "div1";
            new_div.innerHTML = name1 + "对" + name2 + "说:" + message;

            let parent = document.querySelector('.container');
            parent.appendChild(new_div); // 插入其后面
        }
    </script>
</html>

实现效果:

3. 待办事项

分为两部分:样式设计和动画效果

样式设计

目标样式:

实现代码:

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>
        <style>
            * {
                margin: 0px;
                padding: 0px;
                box-sizing: border-box; /* 让盒子不要被撑大 */
            }
            .nav {
                width: 800px;
                height: 100px;
                margin: 0 auto;
                /* 弹性布局 */
                display: flex;
                align-items: center;
            }
            .nav input {
                width: 600px;
                height: 50px;
            }
            .nav button {
                width: 200px;
                height: 50px;
                background-color: orange;
                color: white;
                border-radius: 5px;
                border-style: none;
                font-size: 20px;
            }
            .nav button:active {
                background-color: greenyellow;
            }

            .container {
                width: 800px;
                margin: 0 auto;
                /* 弹性布局 */
                display: flex;
            }
            .container .undone,
            .container .done {
                width: 50%;
                height: 100%;
            }
            .container h3 {
                height: 50px;
                text-align: center;
                line-height: 50px;
                background-color: black;
                color: white;
            }

            /* 每一行数据的样式 */
            .row {
                height: 50px;
                display: flex;
                align-items: center;
            }
            .row span {
                width: 300px;
                margin-left: 10px;
            }
            .row button {
                width: 50px;
                height: 30px;
            }
            

        </style>
    </head>
    <body>
        <div class="nav">
            <input type="text">
            <button>新建任务</button>
        </div>
        <div class="container">
            <div class="undone">
                <h3>未完成</h3>
                <!-- 这里的每一个row都表示一条未完成的内容 -->
                <div class="row">
                    <input type="checkbox"><span>吃饭</span>
                   <button>删除</button>
                </div>
            </div>
            <div class="done">
                <h3>已完成</h3>
                <!-- 已完成的内容 -->
                <!-- ...... -->
            </div>
        </div>
    </body>
</html>

下面我们实现一下如下所示的动画效果:

  1. 当我们在输入框中输入信息后,点击"新建任务",则在未完成的下方会显示出该信息。
  2. 当我们勾选了未完成下方的任务信息,则表示完成了该任务,该任务会从未完成的下方移动到以完成的下方。
  3. 当我们点击删除按钮时,则该条任务就会被删除。

实现代码:

html 复制代码
<script>
    // 1.新建任务事件的实现
    let Add = document.querySelector('.nav button');
    Add.onclick = function() 
    {
        // 获取输入框任务信息
        let input_info = document.querySelector('.nav input').value;
        if(input_info == "") return; // 如果输入为空,则不做操作

        // 创建和row样式一样的新节点
        let new_task = document.createElement('div');
        new_task.className = "row";
        let new_checkbox = document.createElement('input');
        new_checkbox.type = "checkbox";
        let new_span = document.createElement('span');
        new_span.innerHTML = input_info; // 新任务信息设为输入框中的内容
        let new_btn = document.createElement('button');
        new_btn.innerHTML = "删除";
        new_task.appendChild(new_checkbox);
        new_task.appendChild(new_span);
        new_task.appendChild(new_btn);

        // 将新节点插入到未完成列表中
        let undone_list = document.querySelector('.undone');
        undone_list.appendChild(new_task);

        // 完成插入后清空输入框
        document.querySelector('.nav input').value = "";


        // 2.点击复选框后将元素放到 "已完成"的事件
        let all_checkbox_btn = document.querySelectorAll('.row input');
        // 给每一个复选框都绑定一个点击事件
        for(let i = 0; i < all_checkbox_btn.length; i++)
        {
            all_checkbox_btn[i].onclick = function() {
                // 拿到获取到当前元素的父元素
                let cur_task = this.parentNode;
                // 判断该任务应该放在哪一个列表下
                let target;
                if(this.checked)
                {
                    target = document.querySelector('.done');
                }
                else
                {
                    target = document.querySelector('.undone');
                }
                // 移动该任务
                target.appendChild(cur_task);
            }
        }

        // 3.点击删除按钮删除该任务
        let all_dele_btn = document.querySelectorAll('.row button');
        // 给每一个复选框都绑定一个点击事件
        for(let i = 0; i < all_dele_btn.length; i++)
        {
            all_dele_btn[i].onclick = function() {
                // 拿到获取到当前元素的父元素
                let cur_task = this.parentNode;
                // 拿到获取到当前任务的父元素
                let cur_list = cur_task.parentNode;
                // 删除该任务
                cur_list.removeChild(cur_task);
            }
        }
    }
</script>

注意:这里的代码是将复选框事件和删除事件都写在新建任务事件的代码中的,因为:

如果我们将这三个事件分开写,由于当我们运行完成这个html代码后,JS中的代码之后执行一次,那么当点击"新建任务"按钮时,页面上新出现任务中的 <input type="checkbox"> 和删除按钮就都没有被绑定而由于上面那段 for 循环早就已经执行完毕了,新来的复选框并没有赶上那趟"绑定",所以它身上没有任何点击事件。

如果我们将复选框事件和删除事件都写在新建任务事件的代码中,那么当我们每次新增事件后,其中的各个绑定代码都会再执行一次,就不会出现没有绑定的情况了。

演示效果:


感谢各位观看!希望能多多支持!

相关推荐
zzqssliu10 小时前
Vue3 + Pinia 重构跨境代购前端:从taocarts的React方案学到的状态管理心得
前端·react.js·重构
gjf05_0510 小时前
人该怎样活着呢?版本71.5
学习
IT_陈寒10 小时前
SpringBoot自动配置偷偷给我埋了个坑
前端·人工智能·后端
PieroPc10 小时前
通用产品标签打印 (为制衣厂 打印纸箱错印或不足 补打修改纸箱通用程序)html版
前端·javascript·vue.js
小新同学^O^10 小时前
简单学习 --> 限流和熔断
数据库·python·学习
专注API从业者10 小时前
用 Open Claw + 淘宝商品接口,快速实现电商商品监控与智能选品(附完整代码)
大数据·前端·数据结构·数据库
muddjsv10 小时前
前端开发语言使用流行度排行与分析
前端·javascript·typescript
心.c10 小时前
CommonJS和ES Module
javascript·后端·node.js