JavaScript | DOM API 操作元素

一、WebAPI 背景知识

JS 分成三个大的部分:

  • ECMAScript: 基础语法部分
  • DOM API: 操作页面结构
  • BOM API: 操作浏览器

要想写实际的程序,光会语言是不够的,还需要掌握相关的 "生态”,配套的库 / 框架
对于在浏览器上运行 JS 来说,最最核心的库,就是 DOM API

就是浏览器给 JS 提供的原生接口
基于这样的接口,就可以针对页面的上的元素进行操作了

DOM => 文档 对象 模型

HTML 中,会把每个 html 标签,都视为是一个 JS 中可以操作的对象,操作这个对象就可以影响到界面的显示

浏览器给 JS 提供的 API 非常丰富,也有很多组
DOM API
BOM APl
其实还有一些其他的
websocket APl,canvas APl…
统称为 WebAPI,我们主要是介绍DOM

原生的DOM API 能用,但是并不方便
因此除了原生的 API 之外,也存在了大量的第三方库 / 框架,其中 jquery 就是最知名的一个库
Vue,React 等前端框架,本质上还是对 DOM 的封装

jQuery

jQuery是一套跨浏览器的JavaScript库,简化HTML与JavaScript之间的操作。
特点是轻量级,丰富的DOM选择器,事件、样式、动画支持,Ajax操作支持,可扩展性强

Bootstrap

boostrap是一套追求一致性的框架。
特点是跨设备,跨浏览,响应布局,支持html5 css3,支持less动态样式扩展

扫描二维码关注公众号,回复: 16831240 查看本文章

jQuery UI

jquery ui是jquery对桌面端的扩展,可以通过可视化界面进行配置。

API:

  • API 是一个更广义的概念,而 WebAPI 是一个更具体的概念,特指 DOM+BOM

  • 所谓的 API 本质上就是一些现成的函数 / 对象,让程序猿拿来就用,方便开发
    相当于一个工具箱,只不过程序猿用的工具箱数目繁多,功能复杂

DOM:

  • DOM 全称为 Document Object Model.

  • W3C 标准给我们提供了一系列的函数, 让我们可以操作:

    • 网页内容
    • 网页结构
    • 网页样式

DOM 树:

  • 一个页面的结构是一个树形结构,称为 DOM 树

重要概念:

  • 文档: 一个页面就是一个 文档,使用 document 表示.

  • 元素:页面中所有的标签都称为 元素,使用 element 表示.

  • 节点:网页中所有的内容都可以称为 节点,(标签节点,注释节点,文本节点,属性节点等),使用 node表示

这些文档等概念在 JS 代码中就对应一个个的对象
所以才叫 “文档对象模型”


二、获取元素

1、querySelector

  • 要想操作页面上的元素,就需要先拿到对应的 JS 对象
  • DOM 中提供了一组 API 能够获取到网页的元素,最重要的两个:
    querySelector , querySelectorAll

其实是一个 document 这样的对象的属性
页面中的全局对象,一个页面加载好了,就会自动生成一个全局变量,就叫做 document,这里面就有一些属性和方法,让我们来操作页面的内容

<div class="one">
    one
</div>

<div class="two">
    two
</div>

<ul>
    <li>
       three 
    </li>
</ul>

<script>
    // querySelector 参数就是一个 CSS 的选择器
    let div = document.querySelector('.one');
    console.log(div);

    // id 选择器
    let obj = document.querySelector('#two');
    console.log(obj);

    // 复合选择器
    let obj2 = document.querySelector('ul li');
    console.log(obj2); 
</script>

页面结果:

one

two

  • three

2、querySelectAll

<ul>
    <li>aaa</li>
    <li>bbb</li>
    <li>ccc</li>
</ul>

<script>
    let obj2 = document.querySelector('ul li');
    console.log(obj2); 
</script>

在这里插入图片描述

当 querySelector 的参数的选择器,匹配到了多个元素的时候,此时返回的对象,就是匹配结果中的第一个元素
像这种情况,如果我们想把这些 li 都选中,就需要使用 querySelectAll ,querySelectAll 返回的是一个 “数组” ,就包含了所有被选中的元素

let obj2 = document.querySelectorAll('ul li');

在这里插入图片描述

但是准确的说,querySelectorAll 返回的不是一个真正的原生数组,而是一个对象,只不过这个对象,有 length,也能够通过下标的方式来访问内部元素
这样的对象使用起来和数组非常相似 (一模一样),称为 “伪数组”


三、事件

1、什么是事件

  • JS 要构建动态页面,就需要感知到用户的行为
  • 用户对于页面的一些操作(点击,选择,修改等),操作都会在浏览器中产生一个个事件,被 JS 获取到,从而进行更复杂的交互操作
  • 浏览器就是一个哨兵,在侦查敌情(用户行为),一旦用户有反应(触发具体动作),哨兵就会点燃烽火台的狼烟(事件),后方就可以根据狼烟来决定下一步的对敌策略

JS 中的很多代码,都是通过 “事件” 来触发的

事件就是浏览器对于用户的操作行为进行了一个 “统称” (准确的说,事件也不一定全是用户操作产生的,但是大部分是的)

例如,鼠标在页面上移动,就会产生一个鼠标移动事件
再例如,鼠标在页面某个位置点击,就会产生一个鼠标点击事件。再例如,鼠标滚轮,来滚动页面,就会产生一组滚动事件。再例如,用户按下键盘的某个按键,也会产生一个键盘事件。再例如,用户修改浏览器窗口大小,也会产生一个窗口大小改变事件

JS 干的一个主要工作,就是在不同的事件中,进行不同的处理


2、事件三要素

  • 事件源 :哪个HTML元素产生的事件.
  • 事件类型 :鼠标移动 / 鼠标点击 / 键盘事件 / 窗口大小改变事件…
  • 事件的处理程序 :当事件产生之后,执行什么样的 JS 代码,进一步如何处理,往往是一个回调函数

3、点击事件

<!-- 事件源:button -->
<button>这是一个按钮</button>

<script>
    let button = document.querySelector('button');
    // 事件类型:onclick   事件处理函数:function
    button.onclick = function() {
    
    
        alert('hello');
    }
</script>

称此函数为回调函数:这个函数不会立即调用,而是在合适的实际,被 库 / 框架 自动的调用

另一种写法:这个写法,就把页面 (HTML) 写的更乱,我们期望 结构,样式,行为,能够分离

<button onclick="f()">这是一个按钮</button>

<script>
    function f() {
    
    
        alert('hello');
    }
</script>

四、操作元素

操作 = 获取+修改

  1. 操作元素内容
  2. 操作元素的属性
  3. 操作元素的样式

1、操作元素内容

通过 对象 里面的一个属性 innerHTML 来实现 (元素里面包含的 html 代码是什么样子的)

1.1、 打印内容

<div id="screen">hello world</div>

<button id="btn">这是一个按钮</button>

<script>
    let btn = document.querySelector('#btn');
    btn.onclick = function() {
    
    
        let screen = document.querySelector('#screen');
        console.log(screen.innerHTML);
    }
</script>

在这里插入图片描述

当我们点击多次按钮,可以看到,在控制台上,并没有显示多条数据,而是显示了个数字,控制台默认下会把相同的打印合并成一条的,可以设置在控制台中对相似消息进行分组

在这里插入图片描述


1.2、获取内容按钮

<div id="screen">
    <ul>
        <li>aaa</li>
        <li>aaa</li>
        <li>aaa</li>
    </ul>
</div>

<button id="btn">获取内容按钮</button>

在这里插入图片描述


1.3、 修改内容按钮

<div id="screen">
    <ul>
        <li>aaa</li>
        <li>aaa</li>
        <li>aaa</li>
    </ul>
</div>

<button id="btn">修改内容按钮</button>

<script>
    let btn = document.querySelector('#btn');
    btn.onclick = function() {
    
    
        let screen = document.querySelector('#screen');
        screen.innerHTML = '<h1>修改后的内容</h1>'
    }
</script>

在这里插入图片描述


1.4、点击加一

div 显示整数,一个按钮,每次点击这个按钮,就让里面的整数+1

注意: 这里,innerHTML 得到的是 string 类型,要想进行数字相加,就需要把字符串转成整数

let val = screen.innerHTML;
console.log(typeof(val)); // string

val = parseInt(val);

Java 里的 parselnt 是 Integer 类的成员方法。此处 JS 中的 parselnt 相当于是一个全局的函数

由于 JS 是动态类型,转换成数字之后,仍然可以赋值给 valval,就从 string => number 类型

<div id="screen">
    0
</div>

<button id="plus">+</button>

<script>
    let plusBtn = document.querySelector('#plus');
    plusBtn.onclick = function() {
    
    
        // 1、获取 screen 的值
        let screen = document.querySelector('#screen');
        let val = screen.innerHTML;
        val = parseInt(val);

        // 2、将这个值 + 1
        val = val + 1;
        
        // 3、把新值写回去
        screen.innerHTML = val;
    }
</script>

在这里插入图片描述


1.5、input 点击加一

<input type="text" id="screen">

input 作为一个单标签(单身狗),不配拥有 innerHTML,此处是通过 input 的 value 属性,来获取到内部的内容的

<input type="text" id="screen" value="0">
<button id="plus">+</button>

<script>
    let plusBtn = document.querySelector('#plus');
    plusBtn.onclick = function() {
    
    
        // 1、获取 screen 的值
        let screen = document.querySelector('#screen');
        let val = screen.value;
        val = parseInt(val);

        // 2、将这个值 + 1
        val = val + 1;
        
        // 3、把新值写回去
        screen.value = val;
    }
</script>

在这里插入图片描述


2、操作元素的属性

2.1、点击切换图片

通过 dom 对象 . 属性名 就可以进行操作了

<img src="picture1.jpg" alt="">

<script>
    let img = document.querySelector('img');
    img.onclick = function() {
    
    
        console.log(img.src); // 打印 src 属性的内容
        
        if (img.src.indexOf('picture1.jpg') >= 0) {
    
    
            img.src = 'picture2.jpg';
        } else if (img.src.indexOf('picture2.jpg') >= 0) {
    
    
            img.src = 'picture1.jpg';
        }
    }
</script>

在这里插入图片描述

一个 HTML 标签里,能写哪些属性,就同样可以通过 JS 中的 DOM 对象来获取到一样的属性,

可以通过 console.dir 这个方法,打印出一个 dom 对象的全部属性和值

console.dir(img);


3、获取/修改表单元素属性

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

  • value : input 的值.
  • disabled : 禁用
  • checked : 复选框会使用
  • selected : 下拉框会使用
  • type : input 的类型(文本, 密码, 按钮, 文件等)

这些属性,都属于表单元素专有的属性


3.1、点击计数

使用一个输入框输入初始值(整数). 每次点击按钮, 值 + 1

<input type="text" id="text" value="0">
<input type="button" id="btn" value='点我+1'>

    <script>
		var text = document.querySelector('#text');
		var btn = document.querySelector('#btn');
		
		btn.onclick = function () {
    
    
			var num = +text.value;
			console.log(num);
			num++;
			text.value = num;
		}
	</script>
  • input 具有一个重要的属性 value, 这个 value 决定了表单元素的内容
  • 如果是输入框, value 表示输入框的内容, 修改这个值会影响到界面显式; 在界面上修改这个值也会影响到代码中的属性
  • 如果是按钮, value 表示按钮的内容. 可以通过这个来实现按钮中文本的替换

3.2、切换按钮的文本

假设这是个播放按钮, 在 “播放” - “暂停” 之间切换

<input type="button" value="播放">

<script>
    let input = document.querySelector('input');
    input.onclick = function() {
    
    
        if (input.value == '播放') {
    
    
            input.value = '暂停';
        } else if (input.value == '暂停') {
    
    
            input.value = '播放';
        }
    }
</script>

3.3、全选 / 取消全选按钮

实现一个全选效果,主要是操作 input 的 checked 属性

  1. 点击全选按钮,则选中所有选项
  2. 只要某个选项取消,则自动取消全选按钮的勾选状态
<input type="checkbox" id="all"> 全选 <br>
<input type="checkbox" class="girl"> 薛宝钗 <br>
<input type="checkbox" class="girl"> 林黛玉 <br>
<input type="checkbox" class="girl"> 王熙凤 <br>
<input type="checkbox" class="girl"> 贾探春 <br>

<script>
    // 1、获取元素
    let all = document.querySelector('#all');
    let girls = document.querySelectorAll('.girl'); // 

    // 2、给 all 注册点击事件
    all.onclick = function() {
    
    
        for (let i = 0; i < girls.length; i++) {
    
    
            // all.checked 就是 all 这个复选框的选中状态
            girls[i].checked = all.checked;
        }
    }

    // 3、针对每个 girl 注册点击事件,实现对于 all 的取消操作
    for (let i = 0; i < girls.length; i++) {
    
    
        girls[i].onclick = function() {
    
    
            all.checked = checkGirls(girls);
        }
    }

    function checkGirls(girls) {
    
    
        // 判断是不是所有的 girl 都被选中了
        for (let i = 0; i < girls.length; i++) {
    
    
            if (!girls[i].checked) {
    
    
                // 只要有一个是未选中,all 就是未选中状态
                return '';
            }
        }
        // 遍历完,所有都是选中状态,就让 all 也是选中状态
        return 'checked';
    }
</script>

4、操作元素样式

本质上也是操作元素属性

  1. style 对应行内样式 (直接把样式写到 style 里面)
  2. className / classList 对应 内部样式 / 外部样式,应用了一个 / 一组 CSS 类名

4.1、点击加字体大小

let div = document.querySelector('div');
div.onclick = function() {
    
    
    // 1、获取当前的字体大小
    console.log(div.style.fontSize);   
}

注意:

1、CSS 不区分大小 写,一般不用驼峰。JS 不能支持 作为变量名,不能使用脊柱。所有的 CSS 属性都是同样的规则映射过去的

2、当前这里得到 fontSize 是一个字符串,要想相加,就得转成整数
‘20px’ => parselnt => 20
parselnt 转换的时候,会从头往后去转换,遇到非数字字符 ‘px’ ,就转换停止了

3、当修改CSS属性值的时候,一定要注意单位!! 如果单位不合适 / 遗漏,就会失效

<div style="font-size: 20px;">这是一个文本</div>

<script>
    let div = document.querySelector('div');
    div.onclick = function() {
    
    
        // 1、获取当前的字体大小
        console.log(parseInt(div.style.fontSize));
        let fontSize = parseInt(div.style.fontSize);

        // 2、在当前字体大小的基础上,多增加 5px
        fontSize += 5;
        div.style.fontSize = fontSize + 'px';
    }
</script>

在 HTML 中,表示类名的属性,就是 class

但是在 JS 里,属性名变成了 className / classList ,为什么不直接使用 class 这个名字?

class 在 JS 中也是一个关键字 ( JS ES6 版本以上,也引入了类这个概念)

如果要修改的样式比较多,通过 style 来修改就麻烦了,可以直接借助 CSS 类来修改


4.2、夜间模式

<style>
    .light {
    
    
        background-color: #fff;
        color: #000;
    }

    .dark {
    
    
        background-color: #000;
        color: #fff;
    }
</style>


<div class="light" style="height: 300px;">这是一段话</div>
<button>关灯</button>


<script>
    let div = document.querySelector('div');
    let button = document.querySelector('button');
    button.onclick = function() {
    
    
        if (div.className == 'light') {
    
    
            div.className = 'dark';
            button.innnerHTML = '开灯';
        } else if (div.className == 'dark') {
    
    
            div.className = 'light';
            button.innerHTML = '关灯';
        }
     }
</script>

4.4、切换颜色

在这里插入图片描述
部署到 tomcat \webapps\ROOT 中

    <style>
        div {
      
      
            width: 500px;
            height: 300px;
            font-size: 20px;
            font-weight: bold;
            text-align: center;
            line-height: 300px;
            
            background-image: url(f:/Photos/520.png);
            background-size: 100%, 100%;
        }

        .one {
      
      
            color: orange;
        }

        .two {
      
      
            color: green;
        }

        button {
      
      
            width: 150px;
            height: 50px;
            background-color: rgb(0, 128, 128);
            border-radius: 10px;
            border: none;
            outline: none;
        }

        button:active {
      
      
            background-color: #666;
        }
    </style>

    <div class="one">have a good day!</div><br>
    <button style="font-size: 17px;">orange</button>

    <script>
        let div = document.querySelector('div');
        let button = document.querySelector('button');
        button.onclick = function() {
      
      
            if (div.className == 'one') {
      
      
                div.className = 'two';
                button.innerHTML = 'green';
            } else if (div.className == 'two') {
      
      
                div.className = 'one';
                button.innerHTML = 'orange';
            }
        }
    </script>

5、操作节点

针对元素操作,其实是操作元素的属性 (元素本身没有发生改变)
针对节点操作,其实是新增节点 / 删除节点

5.1、新增节点

分成两个步骤:

  1. 创建元素节点

  2. 把元素节点插入到 dom 树中

第一步相当于生了个娃, 第二步相当于给娃上户口

创建新节点:

使用 createElement 方法来创建一个元素,options 参数暂不关注

<script>
    let newDiv = document.createElement('div'); // 创建标签
    newDiv.id = 'newDiv';
    newDiv.className = 'one';
    newDiv.innerHTML = 'hello';
    console.log(newDiv);
</script>

在这里插入图片描述

此处创建的节点,并没有被挂在 dom 树上,因此浏览器页面中,是显示不出来的

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

  • createTextNode 创建文本节点

  • createComment 创建注释节点

  • createAttribute 创建属性节点

我们以 createElement 为主即可

把节点挂在dom树上:

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

<div class="container"></div>

<script>
    let newDiv = document.createElement('div'); // 创建标签
    newDiv.id = 'newDiv';
    newDiv.className = 'one';
    newDiv.innerHTML = 'hello';
    console.log(newDiv);

    let container = document.querySelector('.container');
    container.appendChild(newDiv);
</script>

在这里插入图片描述

还可以使用 insertBefore 将节点插入到指定节点之前

  • var insertedNode = parentNode.insertBefore(newNode, referenceNode);
  • insertedNode 被插入节点(newNode)
  • parentNode 新插入节点的父节点
  • newNode 用于插入的节点
  • referenceNode newNode 将要插在这个节点之前

如果 referenceNode 为 null 则 newNode 将被插入到子节点的末尾.

注意: referenceNode 引用节点不是可选参数

<div class="container">
	<div>11</div>
	<div>22</div>
	<div>33</div>
	<div>44</div>
</div>

<script>
	var newDiv = document.createElement('div');
	newDiv.innerHTML = '我是新的节点';
	
	var container = document.querySelector('.container');
	console.log(container.children);
	container.insertBefore(newDiv, container.children[0]);
</script>

在这里插入图片描述

注意1: 如果针对一个节点插入两次, 则只有最后一次生效(相当于把元素移动了)

<div class="container">
	<div>11</div>
	<div>22</div>
	<div>33</div>
	<div>44</div>
</div>

<script>
	var newDiv = document.createElement('div');
	newDiv.innerHTML = '我是新的节点';

	var container = document.querySelector('.container');
	console.log(container.children);
	// 此处的 children 里有 4 个元素
	container.insertBefore(newDiv, container.children[0]);
	// 此处的 children 里有 5 个元素(上面新插了一个), 0 号元素是 新节点,
	// 1 号元素是 11, 2号节点是 22, 所以是插入到 22 之前.
	container.insertBefore(newDiv, container.children[2]);
</script>

在这里插入图片描述

注意2: 一旦一个节点插入完毕, 再针对刚刚的节点对象进行修改, 能够同步影响到 DOM 树中的内容

<div class="container">
	<div>11</div>
	<div>22</div>
	<div>33</div>
	<div>44</div>
</div>

<script>
	var newDiv = document.createElement('div');
	newDiv.innerHTML = '我是新的节点';
	var container = document.querySelector('.container');
	console.log(container.children);
	container.insertBefore(newDiv, container.children[0]);
	// 插入完毕后再次修改 newDiv 的内容
	newDiv.innerHTML = '我是新节点2';
</script>

在这里插入图片描述


5.2、删除节点

删除节点,removeChild 方法来实现
得先拿到父节点,然后再拿到待删除的子节点,通过 removeChild 就能删除了

  • oldChild = element.removeChild(child);
  • child 为待删除节点
  • element 为 child 的父节点
  • 返回值为该被删除节点
  • 被删除节点只是从 dom 树被删除了, 但是仍然在内存中, 可以随时加入到 dom 树的其他位置.
  • 如果上例中的 child节点 不是 element 节点的子节点,则该方法会抛出异常
<div class="container"></div>

<button>删除 div</button>

<script>
    let newDiv = document.createElement('div'); // 创建标签
    newDiv.id = 'newDiv';
    newDiv.className = 'one';
    newDiv.innerHTML = 'hello';
    console.log(newDiv);

    let container = document.querySelector('.container');
    container.appendChild(newDiv);

    let button = document.querySelector('button');
    button.onclick = function() {
    
    
        container.removeChild(newDiv); // 前面已经获取了
    }
</script>

在这里插入图片描述


五、代码案例

1、猜数字

在这里插入图片描述

Math.random 得到的 [0,1) 随机的 小数 ,如何生成 1 - 100 呢?
先 *100,得到 [0,100) 之间的小数。然后向下取整 Math.floor ,也就是直接舍弃小数部分

<button id="resetBtn">重新开始一局游戏</button> <br>
<span>要猜的数字:</span>
<input type="text">
<button id="guessBtn"></button> <br>
<span>结果:</span> <span id="result"></span> <br>
<span>已经猜的次数:</span> <span id="guessCount">0</span>
    
<script>
    // 1、需要用到的元素
    let resetBtn = document.querySelector('#resetBtn');
    let input = document.querySelector('input');
    let guessBtn = document.querySelector('#guessBtn');
    let resultSpan = document.querySelector('#result');
    let guessCountSpan = document.querySelector('#guessCount');
    
    // 2、生成一个 1 - 100 的随机数
    let toGuess = Math.floor(Math.random() * 100) + 1;
    console.log(toGuess);

    // 3、实现点击 猜 按钮的逻辑
    guessBtn.onclick = function() {
    
    
        // 1) 读取 input 输入的内容,转成整数
        if (input.value == '') {
    
    
            return;
        }
        let curNum = parseInt(input.value);
        // 2) 判断大小 给出提示
        if (curNum < toGuess) {
    
    
            resultSpan.innerHTML = '低了';
            resultSpan.style.color = 'red';
        } else if (curNum > toGuess) {
    
    
            resultSpan.innerHTML = '高了';
            resultSpan.style.color = 'red';
        } else {
    
    
            resultSpan.innerHTML = '猜对了';
            resultSpan.style.color = 'green'               ;
        }
        // 3) 更新猜的次数
        let guessCount = parseInt(guessCountSpan.innerHTML);
        guessCountSpan.innerHTML = guessCount + 1;
    }

    // 4、实现 reset 操作,开始游戏
    resetBtn.onclick = function() {
    
    
        // 让页面刷新即可
        // location 是和 document 并列关系的对象,用来控制页面的链接/地址,通过 reload 操作就可以刷新页面
        location.reload();
    }
</script>

2、表白墙

在这里插入图片描述

<style>
    * {
      
      
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }

    .container {
      
      
        width: 100%;
    }

    h3 {
      
      
        text-align: center;
        padding: 30px 0; /* 上下内边距 20,左右为 0 */
        font-size: 24px;
    }

    p {
      
      
        text-align: center;
        color: #999;
        padding: 10px 0;
    }

    .row {
      
      
        width: 400px;
        height: 50px;
        margin: 0 auto;

        display: flex;
        justify-content: center;
        align-items: center;
    }

    .row span {
      
      
        width: 60px;
        font-size: 20px;
    }

    .row input {
      
      
        width: 300px;
        height: 40px;
        line-height: 40px;
        font-size: 20px;
        text-indent: 0.5em;
        /* 去掉输入框的轮廓线 */
        outline: none;
    }

    .row #submit {
      
      
        width: 200px;
        height: 40px;
        font-size: 20px;
        line-height: 40px;
        margin: 0 auto;
        color: white;
        background-color: orange;
        /* 去掉边框 */
        border: none;
        border-radius: 10px;
    }

    /* 按下的效果 */
    .row #submit:active {
      
      
        background-color: grey;
    }
</style>

<div class="container">
    <h3>表白墙</h3>
    <p>输入后点击提示,会将信息显示在表格中</p>
    <div class="row">
        <span>谁:</span>
        <input type="text">
    </div>
    <div class="row">
        <span>对谁:</span>
        <input type="text">
    </div>
    <div class="row">
        <span>说:</span>
        <input type="text">
    </div>
    <div class="row">
        <button id="submit">提交</button>        
    </div>
</div>

<script>
    // 当用户点击 submit,就会获取 input 中的内容,把内容构造成一个 div,插入页面末尾
    let submitBtn = document.querySelector('#submit');
    submitBtn.onclick = function() {
      
      
        // 1、获取 2 个 input
        let inputs = document.querySelectorAll('input');
        let from = inputs[0].value;
        let to = inputs[1].value;
        let msg = inputs[2].value;
        if (from == '' || to == '' || msg == '') {
      
       // 用户还未填写完毕
            return;
        }
        // 2、生成一个新的 div,内容就是 input 中的内容,新的 div 加到页面中
        let div = document.createElement('div');
        div.innerHTML = from + ' 对 ' + to + ' 说 ' + msg;
        div.className = 'row'; // 应用 row 的样式
        let container = document.querySelector('.container');
        container.appendChild(div);
        // 3、清空之前输入框的内容
        for (let i = 0; i < inputs.length; i++) {
      
      
            inputs[i].value = '';
        }
    }
</script>

刚才咱们写的表白墙程序,是通过一些 div.row 来保存咱们提交的消息,这些 div.row,是挂在, DOM,树上,就是在内存中的,容易失去的
一旦页面刷新 / 关闭了,此时,之前内存中保存的数据,就没了

为了解决上述的数据容易丢失问题,有以下解决方案:

  1. 可以把提交的数据,保存在浏览器本地 (浏览器提供了 localStorage / indexDB 这样的机制,能够实现本地存储),本质上,是通过浏览器,把你要存的数据,存到当前电脑的磁盘上
    问题:只有我在自己的电脑上能看到,别人看不到

  2. 可以把提交的数据,通过网络通信,传输给服务器,由服务器进行保存

    • 服务器保存在内存里
    • 服务器保存在文件中
    • 服务器保存在数据库里

3、待办事项

在这里插入图片描述

<style>
    * {
      
      
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }
    .container {
      
      
        width: 800px;
        margin: 0 auto;
        display: flex;
    }
    .todo,
    .done {
      
      
        width: 50%;
        height: 100%;
    }
    .container h3 {
      
      
        height: 50px;
        text-align: center;
        line-height: 50px;
        background-color: #333;
        color: #fff;
    }
    .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;
        border: none;
        background-color: orange;
        color: #fff;
    }
    .row {
      
      
        height: 50px;
        display: flex;
        align-items: center;
    }
    .row input {
      
      
        margin: 0 10px;
    }
    .row span {
      
      
        width: 300px;
    }
    .row button {
      
      
        width: 50px;
        height: 40px;
    }
</style>

<div class="nav">
    <input type="text">
    <button>新建任务</button>
</div>
<div class="container">
    <div class="todo">
        <h3>未完成</h3>
        <div class="row">
            <input type="checkbox">
            <span>任务</span>
            <button>删除</button>
        </div>
    </div>
    <div class="done">
        <h3>已完成</h3>
    </div>
</div>

<script>
    // 一、实现新增任务
    let addTaskButton = document.querySelector('.nav button');
    addTaskButton.onclick = function () {
      
      
        // 1. 获取到任务内容的输入框
        let input = document.querySelector('.nav input');
        // 2. 获取到输入框内容
        let taskContent = input.value;
        // 3. 根据内容新建一个元素节点
        let row = document.createElement('div');
        row.className = 'row';
        let checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        let span = document.createElement('span');
        span.innerHTML = taskContent;
        let button = document.createElement('button');
        button.innerHTML = '删除';
        row.appendChild(checkbox);
        row.appendChild(span);
        row.appendChild(button);
        // 4. 把新节点插入到 todo 中
        let todo = document.querySelector('.todo');
        todo.appendChild(row);

        // 二、点击复选框后将元素放到 "已完成"
        //    在事件回调函数中使用 this 能够获取到当前处理事件的元素.
        //    通过 this.parentNode 属性能够获取到当前元素的父元素.
        //    点击 checkbox 时, 会先修改 value , 再触发点击事件
        
        // 修改 addTaskButton.onclick
        // 5. 给 checkbox 注册点击事件
        checkbox.onclick = function () {
      
      
            //
            var row = this.parentNode;
            // 注意! 是先触发 checked 为 true, 然后再调用 onclick 函数
            if (this.checked) {
      
      
                var target = document.querySelector('.done');
            } else {
      
      
                var target = document.querySelector('.todo');
            }
            target.appendChild(row);
        }

        // 三、点击删除按钮删除该任务
        // 6. 给删除按钮注册点击事件
        button.onclick = function () {
      
      
            let row = this.parentNode;
            let grandParent = row.parentNode;
            grandParent.removeChild(row);
        }
    }
</script>

猜你喜欢

转载自blog.csdn.net/qq_56884023/article/details/124914276