22.2 JavaScript 常用操作

1. BOM操作

handlebars 复制代码
浏览器对象模型(BOM): 是JavaScript与浏览器交互的接口集合.
它提供了一组对象, 用于操作浏览器窗口, 历史记录, 文档等.
BOM可以通过Javascript代码来访问和控制浏览器的功能和行为.

BOM的核心对象是window对象, 它表示浏览器的窗口或框架.
通过window对象, 可以访问浏览器的各种属性和方法.
例如, 可以使用window对象的alert方法显示一个弹窗, 或者使用window对象的location属性获取当前页面的URL.

BOM还提供了其他一些对象,
如document对象用于操作当前页面的内容,
history对象用于浏览器的历史记录,
navigator对象用于获取浏览器的信息等.

通过BOM, 可以实现很多与浏览器交互的功能, 例如打开新窗口, 改变URL, 获取用户的屏幕尺寸等.
浏览器对象模型是Web开发中非常重要的一部分, 它使得我们可以通过JavaScript与用户的浏览器进行交互和控制.

1.1 window对象

handlebars 复制代码
window对象: 是浏览器提供的全局对象, 它表示当前浏览器窗口或标签页.
在JavaScript中, 通过window对象可以访问各种浏览器提供的功能和属性.

下面是一些常见的window对象的功能和属性:
* 1. 打开新窗口或标签页: window.open()方法可以在浏览器中打开一个新的窗口或标签页, 并加载指定的URL.

* 2. 跳转页面: window.location属性可以获取或设置当前浏览器窗口的URL.
     通过修改window.location, 可以在当前窗口中加载不同的页面.

* 3. 监听事件: window.addEventListener()方法可以用来监听各种事件, 比如鼠标点击, 键盘按键, 页面加载等.

* 4. 调整窗口大小: window.resizeTo()和window.resizeBy()方法可以调整当前窗口的大小, 可以根据指定的像素值或相对值来进行调整.

* 5. 显示对话框: window.alert(), window.confirm()和window.prompt()方法用于显示各种对话框, 分别用于显示警告, 确认和输入框.

* 6. 访问子窗口或框架: 如果当前页面包含框架或嵌套窗口, 可以使用window.frames属性来访问子窗口或框架的内容.

除了上述功能和属性外, window对象还提供了许多其他的功能, 如定时器, 浏览器历史记录, 窗口滚动等.
可以在浏览器环境中直接使用window对象, 并通过它来实现各种与浏览器交互的功能.

需要注意的是, window对象在浏览器环境中有效, 在其他环境(如Node.js)中可能不存在或不具备相同的功能.

1.1.1 新建窗口

handlebars 复制代码
window.open()方法: 是用来打开新的浏览器窗口或标签页的函数.
该方法接受两个参数: URL和窗口名称.

语法: window.open(url, name, features);


参数说明:
* 1. url: 要在新窗口中加载的URL.
     可以是一个绝对URL(如: "https://www.example.com")或相对URL(如:"/page.html").
     
* 2. name: 可选参数, 表示新窗口的名称或目标.
     它可以接受以下几个特殊的取值:
     - _blank: 在新的标签页或窗口中打开URL.
     - _parent: 在父级窗口中打开URL.
     - _self: 在当前窗口或标签页中打开URL(默认值).
     - _top: 在最顶级的窗口中打开URL.

    除了上述特殊值, name参数还可以是用户自定义的窗口名称.
    如果提供了相同名称的窗口, 那么后续打开的URL将在同一窗口中加载, 而不是每次都打开一个新窗口.
            
* 3. features: 可选参数: 是一个以逗号分隔的字符串, 用于设置打开窗口的各种选项.
     以下是一些常见的选项:
     - width=400: 指定窗口的宽度为400像素.
       可以使用像素值px, 使用百分比%, 他CSS单位'em', 'rem'等
       窗口尺寸可能会受到浏览器的限制或用户设置的影响. 
       因此, 不能保证窗口会以精确的尺寸打开.
     - height=300: 指定窗口的高度为300像素. 
     - top=100: 指定窗口距离浏览器窗口顶部的距离为100像素.
     - left=200: 指定窗口距离浏览器窗口左侧的距离为200像素.
     - resizable=yes: 允许用户改变窗口的大小(默认为可改变).
     - scrollbars=yes: 显示窗口的滚动条(默认为显示).
     - toolbar=no: 不显示工具栏.
     - location=no: 不显示地址栏.
     - status=no: 不显示状态栏.
     - menubar=no: 不显示菜单栏.
handlebars 复制代码
在新的标签页中打开 "https://www.example.com":
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>打开一个新的浏览器窗口</title>
</head>
<body>
<script>
    // 在一个页面打开一个新的页面, 新页面是子页面.
    window.open("https://www.example.com", "_blank");
</script>
</body>
</html>
handlebars 复制代码
需要注意的是, 某些浏览器可能会对弹出窗口进行阻止或弹出警告, 取决于用户的浏览器设置和网站的规则.
handlebars 复制代码
打开一个高400px, 宽400px的窗口:
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>设置窗口</title>
</head>
<body>
<script>
    window.open('https://www.example.com', '', 'height=400px, width=400px');
</script>
</body>
</html>
handlebars 复制代码
桌面窗口与浏览器窗口顶部的距离为100像素, 桌面窗口与浏览器窗口左部的距离为100像素:
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>设置窗口2</title>
</head>
<body>
<script>
    window.open('https://www.example.com', '', 'height=400px, width=400px,top=100px, left=100px');
</script>
</body>
</html>

1.1.2 获取窗口大小

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>获取窗口大小</title>
</head>
<body>
<script>
  console.log(window.innerHeight, window.innerWidth)
</script>
</body>
</html>

1.1.3 关闭当前的页面

handlebars 复制代码
window.close(): 用于关闭当前浏览器窗口或标签页.
当调用window.close()函数时, 浏览器会尝试关闭当前活动窗口或标签页.
然而, 这个函数的行为受到浏览器的安全策略的限制, 通常只能在由JavaScript打开的新窗口或标签页中调用window.close(),
对于通过用户手动打开的窗口或标签页, 直接调用window.close()是无效的.
handlebars 复制代码
需要注意的是, 由于安全原因, 现代浏览器默认会阻止通过JavaScript自动关闭或修改用户打开的窗口或标签页.
因此, 一般情况下, 在常规网页中使用window.close()函数是无效的.
handlebars 复制代码
新建一个网页使用定时器在3秒后关闭窗口:
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>关闭窗口示例</title>
</head>
<body>
<h1>将在3秒后关闭窗口</h1>

<script>
    setTimeout(function () {
        window.close();
    }, 3000); // 延迟3秒执行
</script>
</body>
</html>
handlebars 复制代码
window.navigator: 是Web浏览器提供的JavaScript API对象, 可以用于获取有关用户浏览器和操作系统的信息.
它包含了一些属性和方法, 用于访问浏览器导航相关的信息, 例如浏览器类型, 用户语言偏好, 操作系统等.
开发者可以使用这些信息进行浏览器兼容性处理或者根据用户环境做出相应的逻辑判断.

以下是一些常用的属性和方法(window可以省略不写):
* 1. navigator.userAgent: 返回浏览器的用户代理字符串.
* 2. navigator.appName(弃用): 返回浏览器的名称, 通常是浏览器厂商自定义的字符串.
     但需要注意, 这个属性在现代浏览器中往往返回'Netscape', 因为它是早期浏览器的标识字符串, 为了向后兼容而保留了这个值.
* 3. navigator.appVersion(弃用): 返回浏览器的版本信息, 通常是浏览器厂商自定义的字符串.
     这个属性的值可以包含数字和其他标识符, 用于标识浏览器的特定版本和修订号.
* 4. navigator.language: 返回用户的首选语言, 通常是浏览器界面的语言.
* 5. navigator.platform: 返回用户的操作系统平台.
* 6. navigator.cookieEnabled: 返回一个布尔值, 表示浏览器是否启用了Cookie.
* 7. navigator.onLine: 返回一个布尔值, 表示浏览器是否处于联网状态.
* 8. navigator.geolocation: 提供了获取用户地理位置信息的方法.
* 9. navigator.mediaDevices: 提供了访问媒体设备(例如摄像头和麦克风)的方法.

需要注意的是, navigator对象的属性和方法的支持情况可能因不同浏览器和版本而异.
开发者在使用时应该进行兼容性处理.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>navigator对象</title>
</head>
<body>
<script>
    console.log(navigator.userAgent)
    console.log(navigator.appName)
    console.log(navigator.appVersion)
    console.log(navigator.language)
    console.log(navigator.platform)
    console.log(navigator.cookieEnabled)
    console.log(navigator.onLine)
    console.log(navigator.geolocation)
    console.log(navigator.mediaDevices)
</script>
</body>
</html>
handlebars 复制代码
解释: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36

操作系统: Windows NT 10.0, 表示你的操作系统为 Windows 10.
硬件架构: Win64, 表明你的计算机是基于 x64 架构的.
基础浏览器: Chrome/115.0.0.0, 表示你的浏览器是 Chrome, 版本号为 115.0.0.0.
渲染引擎: AppleWebKit/537.36, 表明你的浏览器使用的是 WebKit 渲染引擎, 版本号为 537.36.
带有Gecko内核的Chrome浏览器: KHTML, like Gecko, 表示你的浏览器在某种程度上类似于基于Gecko内核的浏览器(如 Firefox).

1.3 history子属性

handlebars 复制代码
history对象: 是浏览器提供的JavaScript对象, 它提供了与浏览器会话历史记录相关的功能.
通过history对象, 可以在浏览器的历史记录中前进, 后退和跳转到特定的页面.

常用方法:
- back(): 在浏览器历史记录中后退一个页面.
- forward(): 在浏览器历史记录中前进一个页面.

(以下不常用, 不做演示.)
- go(n): 前进或后退指定数量的页面, 参数n为正数表示前进, 负数表示后退.
- pushState(state, title, url): 向浏览器历史记录中添加一条新的状态, 并且不会引发页面的刷新.
- replaceState(state, title, url): 用新的状态替换当前页面在浏览器历史记录中的记录, 同样不会引发页面的刷新.
- length: 返回浏览器历史记录中页面的数量.

需要注意的是, 由于安全原因, JavaScript在浏览器历史记录中的导航只能在同源页面中进行,
即只能在同一域名, 协议和端口下进行页面的导航操作.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页面</title>
</head>
<body>
<h1>home页面</h1>
</body>
</html>
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父页面</title>
</head>
<body>
<a href="/6.1%20home.html">主页面</a>
</body>
</html>
js 复制代码
window.history.back();  // 网页后退到上一页
js 复制代码
window.history.forward();  // 网页前进

1.4 location子属性

handlebars 复制代码
location对象: 是JavaScript中的一个内置对象, 提供了与窗口的URL相关的信息和方法.

常用方法:
* 1. href: 返回当前页面的完整URL.
* 2. protocol: 返回当前页面使用的协议(例如: "http:" 或 "https:").
* 3. host: 返回当前页面的主机名和端口号.
* 4. hostname: 返回当前页面的主机名.
* 5. port: 返回当前页面使用的端口号.
* 6. pathname: 返回当前页面的路径部分.
* 7. search: 返回当前页面的查询字符串部分(即URL中?之后的部分).
* 8. hash: 返回当前页面URL的片段标识符(即URL中#之后的部分).
* 9. assign(url): 加载一个新的URL, 并跳转到该URL.
* 10. reload(): 重新加载当前页面.
* 11. replace(url): 用新的URL替换当前页面.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>URL相关的信息</title>
</head>
<body>
<script>
    let location_list = [
        location.href,
        location.href,
        location.protocol,
        location.host,
        location.hostname,
        location.port,
        location.pathname,
        location.search,
        location.hash,
    ]

    for (let element of location_list) {
        console.log(element);
    }
</script>
</body>

</html>
handlebars 复制代码
assign()与replace()的效果是一样的, 
* 使用assign()方法后, 用户可以通过后退按钮返回到之前的页面.
* 使用replace()方法后, 将无法通过后退按钮返回到之前的页面.
js 复制代码
// 加载一个新的网页, 可以返回到之前的网页.
location.assign('https://www.baidu.com/')
js 复制代码
// 替换当前网页, 无法返回到替换之前的网页.
location.replace('https://www.baidu.com/')
js 复制代码
// 刷新网页的效果.
location.reload()

1.5 弹框

handlebars 复制代码
在JavaScript中, 可以使用弹框(也称为对话框)与用户进行交互或显示信息.

需要注意的是, 弹框方法会阻塞JavaScript的执行, 直到用户关闭对话框为止.
另外, 弹框方法对于网页设计来说并不是最佳实践, 一般建议使用自定义的模态框或弹窗组件来代替浏览器原生的弹框.

以下是常见的JavaScript弹框方法:

1.5.1警告框

handlebars 复制代码
alert(): 显示带有一段消息和一个确定按钮的警告框.
用户需要点击确定按钮才能关闭对话框. 示例:
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>弹窗</title>
</head>
<body>
<script>
    alert("Hello, World!");
</script>
</body>
</html>

1.5.2 确认框

handlebars 复制代码
confirm(): 显示带有一段消息和确定, 取消两个按钮的确认框, 点击确认返回true, 点击取消返回false.
用户可以点击确定或取消按钮来选择是否执行某个操作.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>确认框</title>
</head>
<body>
<script>
    let result = confirm("是否确定删除?");
    if (result) {
        // 执行删除操作.
        console.log(result)
    } else {
        // 取消删除.
        console.log(result)
    }
</script>
</body>
</html>

1.5.3 输入框

handlebars 复制代码
prompt(): 显示带有一段消息, 输入框和确定, 取消两个按钮的提示框.
点击确认返回输入框的内容, 点击取消返回null.
用户可以在输入框中输入内容, 并根据点击确定或取消按钮来返回相应的值. 示例:
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>提示框</title>
</head>
<body>
<script>
    // 第二个参数设置默认值.
    let name = prompt("Please enter your name:", 'qq');

    // 什么都不输入返回空字符串.
    // console.log(typeof name, name)
    if (name) {
        console.log("Hello, " + name);
    } else {
        console.log("Hello, Stranger");

    }
</script>
</body>
</html>

2. 定时器

2.1 单次触发

handlebars 复制代码
setTimeout(): 是一个JavaScript函数, 用于在指定的延迟时间后执行一段代码或调用一个函数.

语法: setTimeout(function, delay, arg1, arg2, ...);
- function: 要执行的函数或要调用的代码块.
- delay: 延迟的时间, 以毫秒为单位. 表示在多长时间后执行函数或代码块.
- arg1, arg2, ...: 可选参数, 当要执行的代码是函数调用时, 这些参数会作为参数传递给函数.
javascript 复制代码
// 使用示例:
setTimeout(() => {
  console.log('这行代码将在延迟时间后执行');
}, 2000);

// 或者
function func1() {
    console.log('这行代码将在延迟时间后执行');
}

setTimeout(func1, 2000) 
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>定时器</title>
</head>
<body>
<script>
    setTimeout(() => {
        console.log('这行代码将在延迟时间后执行');
    }, 2000);
</script>
</body>
</html>
handlebars 复制代码
示例中, setTimeout()函数将会在2000毫秒(即2秒)后执行传入的回调函数, 输出"这行代码将在延迟时间后执行".

2.2 循环触发

handlebars 复制代码
setInterval: 是另一个用于定时器的JavaScript函数, 与setTimeout类似.
它允许以指定的时间间隔重复执行特定的代码或函数.
通过指定一个回调函数和重复的时间间隔(以毫秒为单位), setInterval会在每个时间间隔之后触发回调函数的执行.
与setTimeout不同, setInterval会一直重复执行, 直到明确地使用clearInterval来停止它.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>循环执行定时器</title>
</head>
<body>
<script>
    function func1() {
        alert('快起床了')
    }

    setInterval(func1, 3000)

</script>
</body>
</html>
handlebars 复制代码
要使用clearInterval, 需要将setInterval的返回值存储在一个变量中, 然后使用该变量作为clearInterval的参数.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>清除定时器</title>
</head>
<body>
<script>
    let timer = setInterval(function () {
        alert('快起床了');
    }, 2000);

    // 10秒后清除定时器
    setTimeout(function () {
        clearInterval(timer);
    }, 8000);
</script>
</body>

</html>

3. DOM树操作

handlebars 复制代码
DOM树(Document Object Model)是指HTML文档的结构化表示.
它将HTML文档中的每个元素, 属性和文本都表示为一个对象, 并通过对象之间的关系构成一个层次结构, 从而形成一棵树状结构.

DOM树的根节点是document对象, 它代表整个HTML文档.
每个HTML元素都是树中的一个节点, 元素之间的嵌套关系决定了它们在DOM树中的父子关系。

DOM树中的每个节点都有一个对应的JavaScript对象, 程序可以通过操作这些对象来修改HTML页面的结构和内容.
通过这些对象, 可以访问和修改节点的属性, 样式, 文本内容等.

总之, DOM树提供了一种方便的方式来操作和操纵HTML文档, 使得开发人员可以轻松地访问和修改页面的内容和结构.
handlebars 复制代码
DOM标准规定HTML文档中的每个成分都是一个节点(node):

文档节点(document对象):  代表整个文档.
元素节点(element对象):   代表一个元素(标签).
文本节点(text对象):      代表元素中的文本.
属性节点(attribute对象): 代表一个属性.
注释节点(comment对象):   注释.

3.1 标签查找

handlebars 复制代码
以下方法和属性都是用于在DOM中进行元素标签的查找和导航.

* 1. 直接查找:
     - document.getElementById(id): 通过元素的唯一ID获取一个元素的引用.
     - document.getElementsByClassName(className): 通过元素的类名获取一组元素的引用.
     - document.getElementsByTagName(tagName): 通过元素的标签名获取一组元素的引用。

     这些方法可以根据元素的ID, 类名或标签名来直接查找匹配的元素.
     getElementById返回的是一个单个元素对象.
     getElementsByClassName和getElementsByTagName返回的是一个包含匹配元素的HTMLCollection列表.

* 2. 间接查找:
     - element.parentElement: 获取某个元素的父级元素.
     - element.children: 获取某个元素的所有子元素, 返回一个HTMLCollection对象.
     - element.firstElementChild: 获取某个元素的第一个子元素.
     - element.lastElementChild: 获取某个元素的最后一个子元素.
     - element.nextElementSibling: 获取某个元素的下一个兄弟元素.
     - element.previousElementSibling: 获取某个元素的上一个兄弟元素.

      这些属性和方法可用于在DOM树中进行导航, 实现在父级元素和子元素之间, 兄弟元素之间进行查找和操作.

请注意, 对于元素的查找和导航, 可以根据需要选择不同的方法和属性来处理.
要注意处理返回的结果类型, 并根据情况进行判断和处理.
handlebars 复制代码
命名约定: 'xxEle: 表示一个具体的 <xx> 元素的引用或变量名.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>直接查找</title>
</head>

<body>
<div id="d1">
    <div>div>div</div>
    <p class="c1">div>p1
        <span>div>p1>span</span>
    </p>
    <p>div>p2</p>
</div>
<div>div+div</div>

<script>
    // id查找.
    let divEle0 = document.getElementById('d1');
    console.log(divEle0);


    // 获取类为c1的标签, 值是一个数组.
    console.log(document.getElementsByClassName('c1'));
    // 使用索引取出第一个class='c1'的标签.
    let pEle = document.getElementsByClassName('c1')[0];
    console.log(pEle);

    // 获取所有div标签, 值是一个数组.
    console.log(document.getElementsByTagName('div'));
    // 获取第整个页面中第二个重现的div标签.
    let divEle1 = document.getElementsByTagName('div')[1];
    console.log(divEle1);
</script>
</body>
</html>

3.2 间接查找

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>间接查找</title>
</head>

<body>
<div id="d1">
    <div>div>div</div>
    <p class="c1">div>p1
        <span>div>p1>span</span>
    </p>
    <p>div>p2</p>
</div>
<div>div+div</div>

<script>
    // 通过c1类查找标签p.
    let pEle = document.getElementsByClassName('c1')[0];
    // 查找p标签的父标签--> div.
    divEle0 = pEle.parentElement;
    console.log(divEle0);

    // 获取第一个div的所有子标签, 返回一个数组.
    console.log(divEle0.children);

    // 获取第一个div的第一个子标签.
    console.log(divEle0.firstElementChild);

    // 获取第一个div的最后一个子标签.
    console.log(divEle0.lastElementChild);

    // 获取第一个div的下一个兄弟标签.
    console.log(divEle0.nextElementSibling);

    // 获取第一个div的上一个兄弟标签. --> null 它的上面没有标签.
    console.log(divEle0.previousElementSibling);
</script>
</body>
</html>

3.3 结点操作

handlebars 复制代码
节点操作是指通过操作DOM(文档对象模型)中的元素来修改网页的结构和内容.

下面是一些常见的节点操作:
* 1. 获取元素: 使用querySelector或getElementById方法获取特定的元素. 
     例如: const element = document.querySelector('#myElement');  // 通过id获取元素.

* 2. 创建元素: 使用createElement方法创建新的节点元素(只是创建, 还需要添加节点的操作).
     例如: const newElement = document.createElement('div');  // 创建一个新的div元素.

* 3. 添加节点: 
     添加子节点: 使用appendChild或insertAdjacentElement方法添加节点到DOM中.
     例如: parentElement.appendChild(childElement);  // 将childElement作为parentElement的子节点添加到DOM中.
     
     使用方法在目标节点后插入新节点作为弟弟节点.
     例如: targetNode.insertAdjacentElement("afterend", newNode);  // 在targetNode的后面添加newNode节点作为它的弟弟.
           参数说明:
           afterend: 在节点之后插入新的元素.
           beforebegin: 在节点之前插入新的元素.
           afterbegin: 在节点内部的子节点之前插入新的元素(大儿子).
           beforeend: 在节点内部的子节点之后插入新的元素(小儿子).

* 4. 删除节点: 使用removeChild方法将一个元素从DOM中移除(父节点中删除).
     例如: parentElement.removeChild(childElement);  // 从DOM中移除childElement.
          element.remove();  // 直接删除节点.

* 5. 修改元素属性: 使用setAttribute方法或removeAttribute方法来添加或移除元素的属性.
     例如: element.setAttribute('class', 'newClass');  // 添加class属性为newClass.
           element.removeAttribute('src');  // 移除src属性.
     * 可以使用: 节点.属性=值, 的方式来直接设置节点的属性值.

* 6. 修改元素内容: 使用textContent, innerText或innerHTML属性来修改元素的文本内容或HTML内容.
     例如: element.textContent = 'Hello, World!';  // 修改元素的文本内容.
           element.innerText = 'Hello, World!';  // 修改元素的文本内容.
           element.innerHTML = '<strong>Hello</strong>, World!';  // 修改元素的HTML内容.
     区别: textContent: 返回或设置指定元素的纯文本内容, 包括隐藏元素或注释等.
           innerText:  返回或设置指定元素元素的可见文本内容, 不包括隐藏元素或注释等.
           innerHTML:  返回或设置指定元素的HTML内容.

这些只是节点操作的一些基本例子, DOM还提供了许多其他的方法和属性来满足各种需求.

3.3.1 获取节点

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>获取节点</title>
</head>
<body>
<div id="d1">div标签</div>

<script>
    // 获取节点, id前面带#号.
    const divEle = document.querySelector('#d1');
    console.log(divEle)

    const divEle1 = document.getElementById('d1')
    console.log(divEle1)
</script>
</body>
</html>

3.3.2 添加节点

handlebars 复制代码
添加节点通常可以分为两个步骤: 创建节点和将节点添加到目标位置.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>创建节点</title>
</head>
<body>
<script>
    // 创建标签.
    const newElement = document.createElement('div');
    // 为标签添加文本内容.
    newElement.innerText = 'Hello, World!';
    // 在body下添加节点.
    document.body.appendChild(newElement);
</script>
</body>
</html>

3.3.3 删除节点

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>删除子项</title>
</head>
<body>
<div id="d1">
    <p>Hello, World!</p>
</div>

<script>
    // 获取div节点.
    const divEle = document.querySelector('#d1');
    // 获取p节点.
    const pEle = divEle.firstElementChild;
    // 从div标签中删除p标签.
    divEle.removeChild(pEle);

    // 获取p节点并直接删除.
    // const pEle = document.querySelector('#d1 p');
    // pEle.remove();
</script>
</body>
</html>

3.3.4 修改元素属性

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>设置属性</title>
    <style>
        div {
            width: 100px;
            height: 100px;
            border-style: inset;
        }

        .aqua_color {
            background-color: aqua;
        }

        .red_color {
            background-color: red;
        }
    </style>
</head>
<body>
<div id='d0' class="aqua_color"></div>
<hr>
<div id='d1' class="aqua_color"></div>

<script>
    // 获取div标签.
    const divEle0 = document.getElementById('d0');
    const divEle1 = document.getElementById('d1');

    // 设置元素的class属性为red_color.
    divEle0.setAttribute('class', 'red_color');

    // 移除元素的class属性.
    divEle1.removeAttribute('class');
</script>
</body>
</html>

3.3.5 修改元素内容

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>修改元素内容</title>
</head>
<body>
<div id="d0">
    <p style="display:none;">这是一个隐藏的示例文本。</p>
</div>
<div id="d1"> div1</div>
<div id="d2"> div2</div>

<script>
    // 获取div节点.
    const divEle0 = document.getElementById('d0');
    const divEle1 = document.getElementById('d1');
    const divEle2 = document.getElementById('d2');
    console.log('textContent:', divEle0.textContent);
    console.log('innerText:', divEle0.innerText);
    console.log('innerHTML:', divEle0.innerHTML);


    let str = '<strong>Hello</strong>, World!'
    divEle0.textContent = str
    divEle1.innerText = str
    divEle2.innerHTML = str
</script>
</body>
</html>

3.3.6 练习

handlebars 复制代码
* 0. 准备一张图片.
* 1. 通过DOM操作动态标签创建img标签.
* 2. 为标签添加属性.
* 3. 最后将标签添加到页面中.
html 复制代码
<div id="d1">
    <div>div>div</div>
    <p class="c1">div>p1
        <span>div>p1>span</span>
    </p>
!!! <img> 添加到这里!!!
    <p>div>p2
    </p>
</div>
<div>div+div</div>
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加img标签</title>
</head>
<body>
<div id="d1">
    <div>div>div</div>
    <p class="c1">div>p1
        <span>div>p1>span</span>
    </p>

    <p>div>p2
    </p>
</div>
<div>div+div</div>

<script>
    // 创建img节点
    const imgEle = document.createElement('img');
    // 为标签设置属性, 使用: 节点.属性=值的方式.
    imgEle.title = '猫咪';
    imgEle.alt = '一张图片';
    imgEle.height = 300;
    imgEle.src = 'https://s2.loli.net/2022/02/24/PJrNIYfZ723F5x4.png';

    // 获取一个节点作为参考点.
    const pEle = document.getElementsByClassName('c1')[0];

    // 在目标节点后插入新节点作为弟弟节点.
    pEle.insertAdjacentElement("afterend", imgEle);
</script>
</body>
</html>

3.4 获form表单数据

handlebars 复制代码
节点.value属性可以用来获取或设置以下表单标签的值:
    <input>标签: 包括各种类型的输入框, 如文本输入框, 密码输入框等.
    <select>标签: 用于创建下拉选择框.
    <textarea>标签: 用于创建多行文本输入框.

3.4.1 获取input框数据

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>获取input框数据</title>
</head>
<body>
<form action="">
    <label for="d0">数据1: </label>
    <input type="text" id="d0" name="data0" value="123">

    <label for="d1">数据1: </label>
    <input type="text" id="d1" name="data1">
</form>

<script>
    const inputEle0 = document.getElementById('d0');
    // 输出: 123
    console.log(inputEle0.value);

    const inputEle1 = document.getElementById('d1');
    // 输出: 空
    console.log(inputEle1.value);
    // 在第二个输入框中写入456
    inputEle1.value = 456
</script>
</body>
</html>

3.4.2 获取select单选框数据

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>获取select单选框数据</title>
</head>
<body>
<form action="">
    <label for="d0">单选:</label>
    <select id="d0">
        <option value="vip1">vip1</option> /* 默认选中 */
        <option value="vip2">vip2</option>
        <option value="vip3">vip3</option>
    </select>
</form>

<script>
    // 获取节点.
    const selectEle = document.getElementById('d0');
    // 获取单选框的值, 输出: vip1.
    console.log(selectEle.value)
    // 设置单选框的值.
    selectEle.value = 'vip3'
</script>
</body>
</html>

3.4.3 获取textarea文本框数据

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>获取textarea文本框数据</title>
</head>
<body>
<form action="">
    <label for="d0">说明: </label>
    <textarea id="d0"> </textarea>
</form>

<script>
    // 获取节点.
    const textareaEle = document.getElementById('d0');
    // 获取文本框信息.
    console.log(textareaEle.value);
    // 将字符串输入到文本框.
    textareaEle.value = 'zxc'
</script>
</body>
</html>

3.4.4 获取file数据

handlebars 复制代码
<input type="file">元素可以设置为允许选择和上传多个文件.
要启用多文件选择, 可以将multiple属性添加到<input>元素上.

节点.value属性: 获取文件的路径, 由于安全性限制, 大多数现代浏览器都会将实际的文件路径替换为虚假路径(fakepath).
节点.files属性: 可以获取到选择的文件信息, 它返回一个FileList对象, 实际上是一个文件数组.
节点.files[0]: 获取选择的第一个文件对象.
文件对象.name: 获取文件的名称.
文件对象.size: 获取文件的大小.
文件对象.type: 获取文件的类型.

使用JavaScript动态添加文件到<input type="file">框是不允许的.
浏览器出于安全性的考虑, 组织JavaScript直接访问<input type="file">输入框的文件内容, 包括通过脚本设置文件.
这种限制是为了保护用户的隐私和防止潜在的滥用.
用户必须手动选择文件并进行提交. 无法通过脚本访问或设置文件输入框中的文件, 这是一个由浏览器实施的安全策略, 无法绕过.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>获取file数据</title>
</head>
<body>
<form action="">
    <label for="d0">文件: </label>
    <input type="file" id="d0">
</form>
</body>
</html>
js 复制代码
// 先在HTML操作, 选中一个文件...
// 获取节点.
let fileEle = document.getElementById('d0');
// 文件节点.value只能获取文件虚假的路径.
fileEle.value;    
'C:\\fakepath\\2022-11-09_01369.png'

// 获取文件数组对象.
fileEle.files;            
FileList {0: File, length: 1}

// 获取第一个文件对象.
fileEle.files[0];
File { name: '2022-11-09_01369.png', lastModified: 1667976088529,
       lastModifiedDate: Wed Nov 09 2022 14:41:28 GMT+0800 (中国标准时间), ...}

      name: "2022-11-09_01369.png"
      size: 642199
      type: "image/png"
      ...

3.5 属性操作

handlebars 复制代码
classList是DOM元素的一个属性, 它表示了元素的类名列表.
通过classList, 可以对元素的类进行操作, 包括获取所有的类, 添加类, 判断是否包含某个类以及切换类的状态.

classList属性和相关的方法:
* 1. 结点.classList: 获取元素的类名列表.
     返回的是一个DOMTokenList对象, 可以通过它来操作类名.

* 2. 结点.classList.add("属性"): 向元素的类名列表中添加一个类名.
     如果类名已存在, 则不会重复添加.

* 3. 结点.classList.contains("属性"): 判断元素的类名列表中是否包含某个类名.
     返回true表示存在该类名, 返回false表示不存在.
     
* 4. 结点.classList.remove(): 用于从元素的类列表中移除一个或多个类名.
     如果类名不存在于元素的类列表中, 不会产生任何效果.
     
* 5. 结点.classList.toggle("属性"): 切换元素的类名状态.
     如果元素的类名列表中存在指定类名, 则会移除该类名并返回false, 否则会添加该类名并返回true.

3.5.1 获取所有类名

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>查看类名</title>
    <style>
        .box_color {
            background-color: aqua;
        }

        .box_size {
            height: 100px;
            width: 100px
        }
    </style>

</head>
<body>
<div id='d0' class="box_color box_size"></div>

<script>
    // 获取节点.
    const divEle = document.getElementById('d0');
    // 返回的是一个DOMTokenList对象.
    console.log(divEle.classList)
    // 遍历类名.
    divEle.classList.forEach(className => {
        console.log(className);
    });
</script>
</body>
</html>

3.5.2 添加类

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加类</title>
    <style>
        .box_color {
            background-color: aqua;
        }

        .box_size {
            height: 100px;
            width: 100px
        }
    </style>

</head>
<body>
<div id='d0' class="box_color box_size"></div>
<hr>
<div id='d1'></div>

<script>
    // 获取节点.
    const divEle = document.getElementById('d1');
    // 为节点添加类名.
    divEle.classList.add('box_color', 'box_size');
</script>
</html>

3.5.3 判断是否包含某个类

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>判断是否包含某个类</title>
    <style>
        .box_color {
            background-color: aqua;
        }

        .box_size {
            height: 100px;
            width: 100px
        }
    </style>
</head>
<body>
<div id='d0' class="box_color box_size"></div>
<hr>
<div id='d1'></div>

<script>
    // 获取节点.
    const divEle0 = document.getElementById('d0');
    const divEle1 = document.getElementById('d1');

    // 判断是否包含某个类.
    console.log(divEle0.classList.contains('box_color'));
    console.log(divEle0.classList.contains('box_size'));

    console.log(divEle1.classList.contains('box_color'));
    console.log(divEle1.classList.contains('box_size'));
</script>
</body>
</html>

3.5.4 移除类名

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>移除类名</title>
    <style>
        .box_color {
            background-color: aqua;
        }

        .box_size {
            height: 100px;
            width: 100px
        }
    </style>
</head>
<body>
<div id='d0' class="box_color box_size"></div>

<script>
    // 获取节点.
    const divEle0 = document.getElementById('d0');
    // 移除多个类名.
    divEle0.classList.remove('box_color', 'box_size');
</script>
</body>
</html>

3.5.5 切换状态

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>切换状态</title>
    <style>
        div {
            height: 100px;
            width: 100px;
            border-radius: 50%;
        }

        .div_color {
            background-color: greenyellow;
        }

    </style>
</head>
<body>
<div id="d0" class="div_color"></div>

<script>
    // 获取节点.
    const divEle = document.getElementById('d0');
    // divEle.classList.toggle('div_color')
</script>
</body>
</html>
js 复制代码
// 第一次执行, 元素的类名列表中存在指定类名, 移除该类名并返回false. 
divEle.classList.toggle('div_color')

// 再次执行, 元素的类名列表中不存在指定类名, 添加该类名并返回true. 

...

3.6 样式操作

handlebars 复制代码
DOM操作标签样式时, 使用style方法来设置.
格式:  节点.style.属性 = '值';

注意事项: CSS中的连字符(-)在JavaScript中需要转换成驼峰体的形式.
例如, background-color在JavaScript中的写法是backgroundColor.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>样式操作</title>
</head>
<body>
<div id="d0"></div>

<script>
    // 获取节点.
    let divEle = document.getElementById("d0");
    // 设置宽高300px, 圆形, 边框, 背景颜色.
    divEle.style.width = '100px'
    divEle.style.height = '100px'
    divEle.style.borderRadius = '50%'
    divEle.style.border = '1px solid black'
    divEle.style.backgroundColor = 'aqua';
</script>
</body>
</html>

4. 事件

handlebars 复制代码
满足某个条件自动触发的动作称为事件.

当用户点击某个对象时调用的事件句柄:
- onclick:     当用户点击某个对象时触发的事件句柄.
- ondblclick:  当用户双击某个对象时触发的事件句柄.

元素获得焦点和失去焦点事件:
- onfocus:     当元素获得焦点时触发的事件句柄.
- onblur:      当元素失去焦点时触发的事件句柄.

字段的改变和选择事件:
- onchange:    当字段内容被改变时触发的事件句柄.
- onselect:    在文本框中的文本被选中时触发的事件句柄.
- onsubmit:    当确认按钮被点击时触发的事件句柄,一般用于表单提交.

键盘按键事件:
- onkeydown:   当某个键盘按键被按下时触发的事件句柄.   
- onkeypress:  当某个键盘按键被按下并松开时触发的事件句柄.
- onkeyup:     当某个键盘按键被松开时触发的事件句柄.

鼠标事件:
- onmousedown: 当鼠标按钮被按下时触发的事件句柄.
- onmousemove: 鼠标被移动.
- onmouseout:  鼠标从某元素移开时触发的事件句柄.
- onmouseover: 鼠标移到某元素之上时触发的事件句柄.

页面加载事件: 
- onload:      一张页面或一幅图像完成加载时触发的事件句柄

4.1 绑定事件

handlebars 复制代码
绑定事件是一种在编程中实现交互和响应的常见技术.

绑定事件指的是在编程中将一个事件(如点击, 鼠标移动, 键盘按键等)与一个特定的事件处理函数相关联的过程.
当事件被触发时, 相关的事件处理函数将被调用以执行特定的逻辑或功能.

通过将事件和事件处理函数进行绑定, 可以定义用户的操作如何触发相应的行为.
例如, 在一个按钮上绑定点击事件, 当用户点击该按钮时, 相关的事件处理函数将被执行.

绑定事件可以通过多种方式实现, 如在HTML中使用特定的事件属性(如'onclick', 'onmouseover'等),
或者使用JavaScript提供的方法(如'addEventListener')来动态地绑定事件处理函数.

4.2 HTML属性绑定

handlebars 复制代码
HTML属性绑定: 在HTML元素的标签上直接添加事件属性.
例如, 使用onclick属性可以指定一个函数或执行的代码, 当元素被点击时会触发该事件. 

这种方式简单易用, 适用于简单的交互.
但是如果需要处理复杂的逻辑或者多个事件, 可能会导致HTML代码冗长和难以维护.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>绑定事件</title>
</head>
<body>
<!-- 当按钮被点击时, 执行名为myFunction的JavaScript函数. -->
<button onclick="myFunction()">点击我</button>

<script>
    // 点击button按钮时执行myFunction函数.
    function myFunction() {
        alert('你点击了按钮!')
    }
</script>
</body>
</html>

4.3 addEventListener方法绑定

handlebars 复制代码
addEventListener是JavaScript中的一个方法, 是用来给元素添加事件监听器的.

addEventListener方法接受两个参数: 
* 1. 要监听的事件类型(比如'click')和一个事件处理函数.
* 2. 当事件类型触发时, 事件处理函数将被执行.

这种方式更加灵活, 可以在JavaScript代码中处理更复杂的逻辑和多个事件.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>绑定事件2</title>
</head>
<body>
<button id="myButton">点击我</button>

<script>
    // 获取节点.
    const buttonEle = document.getElementById('myButton');
    buttonEle.addEventListener('click', function () {
        alert('你点击了按钮!')
    })
</script>
</body>
</html>

4.4 DOM属性绑定

handlebars 复制代码
DOM属性绑定: 使用JavaScript DOM(文档对象模型)属性来绑定事件处理函数.
通过获取元素对象, 直接将事件处理函数赋值给对象的事件属性来绑定事件.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>绑定事件3</title>
</head>
<body>
<button id="myButton">点击我</button>

<script>
    // 获取节点.
    const buttonEle = document.getElementById('myButton');
    buttonEle.onclick = function () {
        alert('你点击了按钮!')
    }
</script>
</body>
</html>

4.5 关键字this

handlebars 复制代码
在事件处理函数中, 关键字this: 表示当前触发事件的元素对象.

当事件被触发时, this引用的是触发事件的元素对象.
这使得可以在事件处理函数中访问和操作当前元素的属性, 样式, 内容等.

在HTML中使用属性绑定方式(onclick 属性)来绑定事件处理函数时, 确实需要显式传递this.
使用事件监听器(addEventListener)绑定事件处理函数与DOM属性绑定时, 不需要显式传递this.
事件处理函数内部的this将会自动引用触发事件的元素.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>关键字this</title>

</head>
<body>
<!--this的值在运行时才确定,-->
<button onclick="myFunction(this)">点击我</button>

<script>
    function myFunction(ths) {
        console.log()
        // 使用this访问当前点击的按钮元素对象.
        ths.style.backgroundColor = 'red'; // 改变背景颜色
        ths.innerText = '已点击'; // 修改按钮文本
    }
</script>
</body>
</html>
handlebars 复制代码
在JavaScript中使用this关键字来访问当前点击的按钮元素对象.
当点击按钮时, 调用了名为myFunction的函数, 并将this作为参数传递给该函数.

在函数内部, 通过访问传递进来的参数ths, 即this的值, 来操作当前点击的按钮元素.
使用'ths.style.backgroundColor;'来改变按钮的背景颜色, 使用'ths.innerText;'来修改按钮的文本内容.

通过将'this'作为参数传递给函数, 可以在函数内部访问到当前的DOM元素对象, 从而实现对该元素的操作和修改.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>关键字this 2</title>
</head>
<body>
<button id="myButton">点击我</button>

<script>
    // 获取节点.
    const button = document.getElementById('myButton');
    // 绑定事件.
    button.addEventListener('click', myFunction);

    function myFunction() {
        // 使用 this 访问当前点击的按钮元素对象.
        this.style.backgroundColor = 'red';
        this.innerText = '已点击';
    }
</script>
</body>
</html>
handlebars 复制代码
在这个示例中, 事件处理函数myFunction直接传递给addEventListener, 而不需要手动传递this或绑定到参数中.
事件处理函数内部的this将在运行时自动引用按钮元素对象, 因此可以通过this来修改按钮的样式和文本.

4.6 加载事件

handlebars 复制代码
<script>标签可以放在<head>或<body>内, 而通常将其放在<body>内, 并且放在最后面是一种最佳实践.
浏览器在解析HTML文档时是自上而下运行的.
所以, 当给页面上的元素绑定事件时, 需要等到文档加载完毕, 确保所需元素已经存在于DOM中.
handlebars 复制代码
使用window.onload事件可以确保在<script>标签产生之前, DOM中的所有对象都已经加载完毕.
window.onload是一个事件, 在整个文档以及所有图像, 脚本, 链接和子框架完全加载后触发.
这意味着在window.onload事件触发时, 可以确保整个文档已经准备就绪, 可以安全地操作和访问DOM元素.

注意: 使用onload属性给window或其他元素绑定事件时, 只能存在一个onload函数.
后面的onload函数会覆盖之前存在的onload函数, 这是因为onload属性只能保存一个函数引用.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>onload事件</title>
    <script>
        // 等页面完成加载后才能执行function内的代码.
        window.onload = function () {
            // 获取节点.
            let btnEle = document.getElementById('d0')
            // 点击按钮出现弹窗.
            btnEle.onclick = function () {
                alert('abc')
            }
        }
    </script>
</head>
<body>
<button id="d0">点我</button>
</body>
</html>

4.7 点击事件

4.7.1 开关灯案例

handlebars 复制代码
一个简单的开关灯: 点击按钮时, 会在<body>标签上添加或删除c_close类, 从而改变背景颜色.
html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>开关灯事件</title>
    <style>
        .c_close {
            background-color: black;
        }
    </style>
</head>

<body id="d1" class="c_close">
<button>开/关</button>

<script>
    // 获取节点.
    let bodyElement = document.getElementById('d1');
    // 点击按钮触的函数执行.
    bodyElement.onclick = function () {
        // 切换状态.
        bodyElement.classList.toggle('c_close');
    };
</script>
</body>
</html>

4.7.2 时间显示

handlebars 复制代码
在input中展示时间.
* 1. 在input款内显示时间.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>时钟模拟</title>
</head>
<body>
<label for="d0">时间: </label>
<input type="text" id="d0">

<script>
    // 获取结点.
    const inputEle = document.getElementById('d0')

    // 定时器执行的函数.
    function timetable() {
        /* 时间对象声明必须放在函数内, 时间对象就是一次性使用的东西.
        值固定了需要重新声明获取新的时间, 不然写在外面时间就永远是同一个时间. */
        let newTime = new Date()
        // 将本地化时间设置到input框内.
        inputEle.value = newTime.toLocaleString()
    }

    // 1秒执行一次函数.
    setInterval(timetable, 1000)
</script>
</body>
</html>
handlebars 复制代码
* 2. 添加开始个暂停按钮.

setInterval()函数: 返回一个唯一的标识符, 用于标识setInterval创建的定时器.
这个值可以作为参数传递给clearInterval()函数, 以便后续清除定时器.

正常情况下, 这个标识符是一个数字, 但具体的值并不重要.
它只是用作标识定时器的一种机制. 
实际上, 它是由JavaScript引擎生成的, 因此可能看到的值可以是任何数字.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>时钟模拟2</title>
</head>
<body>
<input type="text" id="d0">
<button id="d1">开始</button>
<button id="d2">停止</button>
<script>
    // 获取结点.
    let inputEle = document.getElementById('d0')
    let startEle = document.getElementById('d1')
    let stopEle = document.getElementById('d2')

    // 定时器执行的函数.
    function showTime() {
        let currentTime = new Date();
        inputEle.value = currentTime.toLocaleString()
    }

    // 绑定开始按钮.
    startEle.onclick = function () {
        // 在非严格模式下, 如果没有显示地声明变量,  它将成为一个全局变量.
        t = setInterval(showTime, 1000)
        console.log(t)
    }
    // 绑定暂停按钮.
    stopEle.onclick = function () {
        clearInterval(t)
    }
</script>
</body>
</html>
handlebars 复制代码
码代的缺陷: 点击一次开始都对应一次停止, 如果按下多个开始, 同一时间就开启了多个定时器, 再点停止就无法, 停下来了.
* 主要看定时器的标识, 多次点击开始时以下创建了多个定时器.
handlebars 复制代码
解决问题: 添加判断条件, 每次只能启动一个计时器.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>时钟模拟2</title>
</head>
<body>
<input type="text" id="d0">
<button id="d1">开始</button>
<button id="d2">停止</button>
<script>
    // 获取结点.
    let inputEle = document.getElementById('d0')
    let startEle = document.getElementById('d1')
    let stopEle = document.getElementById('d2')
    // 定义一个计时器, 并设置初始值.
    let time_num = null

    // 定时器执行的函数.
    function showTime() {
        let currentTime = new Date();
        inputEle.value = currentTime.toLocaleString()
    }

    // 绑定开始按钮.
    startEle.onclick = function () {
        // 当time_num为null时取反, 启动定时器.
        // 设置的目的: 只能点击一个开始按钮, 开启一个定时器. 多点无效.
        if (!time_num) {
            time_num = setInterval(showTime, 1000)
            console.log(time_num)
        }

    }
    // 绑定暂停按钮.
    stopEle.onclick = function () {
        // 清除定时器.
        clearInterval(time_num)
        // 重置计数器.
        time_num = null
    }
</script>
</body>
</html>
handlebars 复制代码
* 主要看定时器的标识, 多次点击开始时不会而外创建定时器.

4.8 焦点事件

handlebars 复制代码
input文本框内默认有提示信息.
在获取焦点的时候, 如果输入框内的数据不是字符串'输入用户名', 则将提示信息清空.
在失去焦点的时候, 如果输入框内没有数据则恢复提示信息, 否则什么都不做.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>焦点事件</title>
</head>
<body>
<label for="d0">账户:</label>
<input type="text" value="输入用户名" id="d0">
<script>
    // 获取节点.
    let inputEle = document.getElementById('d0')
    // 获取焦点时将框内的值清空.
    inputEle.onfocus = function () {
        if (inputEle.value === '输入用户名') {
            inputEle.value = "";
        }

        // 失去焦点时, 如果输入款内没有谁, 恢复提示.
        inputEle.onblur = function () {
            if (!inputEle.value) {
                inputEle.value = "输入用户名";
            }

        }
    }
</script>
</body>
</html>

4.9 文本域变化事件

handlebars 复制代码
省市联动: 是指根据用户在选择省份时的选择, 动态更新对应省份的城市列表.
通过js动态创建一个两个下拉选择框, 第一个下拉框的数据不变, 第二个下拉框的数据随着第一个下拉框的选择变化.
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文本域变化事件</title>
</head>
<body>

<!--第一个选择框-->
<label for="d0">省份:</label>
<select name="" id="d0">
    <option value="" selected disabled>--请选择--</option>
</select>

<!--第二个选项框-->
<label for="d1">城市/区:</label>
<select name="" id="d1">
</select>

<script>
    // 0. 写一个自定义对象存入数据.
    let data = {
        "河北": ["廊坊", "邯郸", '唐山'],
        "山东": ["威海市", "烟台市", '临沂市'],
        "北京": ["朝阳区", "海淀区", '昌平区'],
        "上海": ['浦东新区', '静安区', '黄浦区'],
        "深圳": ['南山区', '宝安区', '福田区']
    };

    //  1. 获取省份选择框.
    let sel1Ele = document.getElementById('d0');

    // 2. 获取所有自定义对象的键, 添加到省份选择框中.
    for (let key in data) {
        // 2.0 循环创建option结点.
        let optionEle = document.createElement('option');
        // 2.1 为结点设置提交的值.
        optionEle.value = key;
        // 2.2 为结点设置显示给用户的值.
        optionEle.innerText = key;
        // 2.3 添加结点.
        sel1Ele.appendChild(optionEle);
    }

    // 3. 获取城市输入框.
    let sel2Ele = document.getElementById('d1')
    // 4.为城市输入框框绑定文本域变化事件.
    sel1Ele.onchange = function () {
        // 4.3. 切换省份时, 清除之前的城市记录.
        sel2Ele.innerHTML = '<option value="" selected disabled>--请选择--</option>'

        // 4.0 获取省份框的值.
        let msg = sel1Ele.value
        // 4.1 通过键-->省 获取对应的值--> 城市列表.
        let values = data[msg]

        // 4.2 通过索引取值.
        for (let i in values) {
            // 0. 创建option节点.
            let option2Ele = document.createElement('option')
            // 1. 为结点设置提交的值.
            option2Ele.value = values[i]
            // 2. 为结点设置显示给用户的值.
            option2Ele.innerText = values[i]
            // 3. 插入结点.
            sel2Ele.appendChild(option2Ele)
        }
    }
</script>
</body>
</html>
相关推荐
Ajiang282473530419 分钟前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
ggdpzhk19 分钟前
VUE:基于MVVN的前端js框架
前端·javascript·vue.js
幽兰的天空23 分钟前
Python 中的模式匹配:深入了解 match 语句
开发语言·python
小曲曲1 小时前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
学不会•2 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS3 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
Theodore_10223 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
活宝小娜5 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点5 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow5 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js