当前位置 : 首页 » 文章分类 :   »  JavaScript-DOM

JavaScript-DOM

JavaScript DOM 学习笔记


Page Visibility API​​ 页面可见性API

https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API

JavaScript 中可通过 ​​Page Visibility API​​ 精确检测页面是否处于前台(用户可见)

visibilityState 页面可见状态

document.visibilityState ​返回当前页面的可见状态

  • visible 页面内容至少部分可见(例如标签页在前台、窗口未被最小化)。
  • hidden 页面内容对用户完全不可见(如标签页切换到后台、窗口最小化、屏幕锁定等)。

​visibilitychange 页面可见状态变化事件

​visibilitychange 事件​​:当页面可见状态变化时触发,例如用户切换标签页、最小化窗口等

js 代码示例:

// 监听可见性变化
document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'visible') {
    console.log('页面处于前台'); // 用户正在查看当前页面
  } else {
    console.log('页面处于后台'); // 用户离开页面
  }
});

// 直接获取当前状态
const isForeground = document.visibilityState === 'visible';
console.log(`当前是否前台: ${isForeground}`);

​visibilitychange 触发时机

​visibilitychange 触发时机

  • 切换浏览器标签页:触发
  • 最小化浏览器窗口:触发,变为 hidden
  • 其他窗口覆盖浏览器:不触发,仍是 visible
  • 锁屏:大多数浏览器会触发,变为 hidden。经测试 chrome, edge 会触发。
  • 浏览器失去焦点:不触发,仍是 visible

其他窗口覆盖浏览器不触发 ​visibilitychange 是合理的:
从浏览器的角度来看,只要标签页是当前激活的标签,visibilityState 就是 visible
Page Visibility API,主要是为了区分 『用户在看这个标签页』 vs 『用户切换到其他标签页了』,它不关心是否有其他窗口遮挡
如果每次窗口被遮挡就暂停,会导致后台音乐播放、视频播放等被中断

页面可见状态 visibilityState 与 窗口焦点状态 onfocus/onblur

假如有2块屏幕,网站页面在第二块屏幕的前台页面可看到,但鼠标在第一个屏幕上,那么 visibilityState 可见状态是什么?
答:visible
多显示器场景,如果页面所在的浏览器标签页处于​​激活状态​​(即该标签页是当前浏览器的前台标签),即使系统焦点在另一个显示器上,该页面仍然被认为是可见的,即 visibilityState === 'visible'

即使页面被其他窗口​​部分覆盖​​,只要浏览器窗口未被最小化且标签页在前台,visibilityState 状态仍为 visible

可见性状态 visibilityState 与 窗口焦点状态 window.onfocus/onblur 无关,只要页面是浏览器的激活页面 visibilityState 就是 visible,无论窗口是否在焦点上。

window.onfocus = () => console.log("窗口聚焦(前台)");
window.onblur = () => console.log("窗口失焦(后台)");

实例:页面切换时暂停视频

const video = document.getElementById('myVideo');
document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    video.pause(); // 离开页面时暂停
  } else {
    video.play(); // 返回页面时继续
  }
});

requestIdleCallback 闲时回调 API

requestIdleCallback 是浏览器 JavaScript 的一个 API,允许开发者在浏览器空闲时期调度低优先级的任务,避免阻塞关键操作(如用户交互、动画渲染),从而提升页面性能与用户体验。

用途:执行非紧急的后台任务(如日志上报、数据分析、预加载资源),不影响用户感知的延迟(如点击响应、动画流畅度)。

实现原理:

  • 浏览器在每一帧(通常 16ms/帧)中处理完高优先级任务后,若仍有空闲时间,则执行注册的 requestIdleCallback 回调。
  • 若无空闲时间,回调会延迟到下一次空闲时段执行。

用法:

const requestId = requestIdleCallback(callback[, options]);

参数​​:

  • callback:空闲时执行的函数,接收一个 IdleDeadline 对象作为参数。
  • options(可选):
    • timeout:指定回调超时时间(毫秒)。若超时后仍未空闲,浏览器会强制执行回调。

      ​返回值​​:唯一 ID(用于 cancelIdleCallback 取消回调)。

window 对象(浏览器窗口)

Window
https://developer.mozilla.org/zh-CN/docs/Web/API/Window

所有浏览器对象的最顶层是 window 对象​​。它代表当前打开的浏览器窗口或标签页。
window 对象表示一个包含 DOM 文档的窗口,其 document 属性指向窗口中载入的 DOM文档 。
window 作为全局变量,代表了脚本正在运行的窗口,暴露给 Javascript 代码。

window 对象常用操作方法:
window.innerWidth 浏览器窗口的宽度(不包含工具栏) console.log(window.innerWidth)
window.innerHeight 浏览器窗口的高度(不包含工具栏) console.log(window.innerHeight)
window.open() 打开新浏览器窗口 window.open(“https://example.com")
window.close() 关闭当前窗口 window.close()
window.scrollTo() 滚动到指定位置 window.scrollTo(0, 500)
window.alert() 显示警告弹窗 window.alert(“警告信息”)
window.setTimeout() 设置延迟执行的定时器 setTimeout(() => {}, 1000)
window.setInterval() 设置周期性执行的定时器 setInterval(() => {}, 1000)

pageYOffset = scrollY 文档在垂直方向已滚动的像素值,文档从顶部开始滚动过的像素值
pageYOffset 属性是 scrollY 属性的别名
为了跨浏览器兼容,请使用 window.pageYOffset 代替 window.scrollY


window. 可省略

在浏览器环境中,全局变量和函数实际上是被添加到 window 对象上的。window 对象是浏览器中的全局对象,代表了当前浏览器窗口。
window 对象可以省略,如: alert() 等价于 window.alert()


document 对象

document 对象是 window 对象中最重要的二级对象,代表当前窗口加载的 HTML 文档
由于 window 对象可以省略,可以直接使用 document 对象,所以 window.document === document

// document 是 window 的属性
console.log(window.document === document); // true

// 实际用例
const title = document.title; // 获取页面标题
const bodyContent = document.body.innerHTML; // 获取 body 内容
const element = document.getElementById("myElement"); // 获取 DOM 元素

referrer 上一个页面url

document.referrer 返回 跳转或打开到当前页面 的页面的 URI
如果用户直接打开了这个页面(不是通过页面跳转,而是通过地址栏或者书签等打开的),则该属性为空字符串。


location 对象

Location 对象存储在 Window 对象的 Location 属性中,表示当前窗口中显示的文档的 Web 地址。
location 对象包含当前 URL 的信息并提供导航方法。
它的 href 属性存放的是文档的完整 URL,其他属性则分别描述了 URL 的各个部分。

当一个 Location 对象被转换成字符串,href 属性的值被返回。这意味着你可以使用表达式 location 来替代 location.href

Location
https://developer.mozilla.org/zh-CN/docs/Web/API/Location

主要属性 及 操作

console.log(window.location === location); // true

// location 的关键属性和方法
location.href;      // 完整 URL
location.protocol;  // http: 或 https:
location.host;      // 主机名和端口
location.hostname;  // 域名
location.pathname;  // 路径部分
location.search;    // 查询字符串 (?后部分)
location.hash;      // 哈希部分 (#后部分)

location.reload();  // 重新加载当前页面
location.assign("https://new-url.com"); // 导航到新页面
location.replace("https://new-url.com"); // 替换当前页面

href 页面完整url

protocol 协议

包含URL对应协议的一个DOMString,最后有一个”:”。

host 域名:端口号

对于没有端口的页面, host 等于 hostname
对于带端口的页面, host 包括整个 域名:端口, hostname只包含域名

hostname 不带端口号的域名

port 端口号

pathname url的path

包含URL中路径部分的一个DOMString,开头有一个“/“

search url的查询串

包含URL参数的一个DOMString,开头有一个“?”

hash 页内锚点

包含块标识符的DOMString,开头有一个“#”

origin 源信息(只读)

包含页面来源的域名的标准形式

通过location获取当前页面的url等信息

window.location.protocol: http:
window.location.host: localhost:4000
window.location.hostname: localhost
window.location.origin: http://localhost:4000
window.location.pathname: /article/JavaScript/
window.location.href: http://localhost:4000/article/JavaScript/

window.location与document.location

window 对象的 location 属性 等于 document 对象的 location 属性, 都是引用了 location 对象

window.location === document.location //true
document.location===location // true
window.location===location // true

navigator 提供浏览器和操作系统的信息

console.log(navigator.userAgent); 
// 示例输出: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36..."

navigator.platform;  // 操作系统平台
navigator.language;  // 浏览器主语言
navigator.onLine;    // 是否联网
navigator.geolocation; // 获取位置信息接口

// 实际应用:检测浏览器功能
if ("geolocation" in navigator) {
    navigator.geolocation.getCurrentPosition(showPosition);
} else {
    console.log("地理定位不可用");
}

platform 操作系统

platform 属性是一个只读的字符串,声明了运行浏览器的操作系统和(或)硬件平台。

userAgent 用户代理

userAgent 属性是一个只读的字符串,声明了浏览器用于 HTTP 请求的用户代理头的值。
一般来讲,它是在 navigator.appCodeName 的值之后加上斜线和 navigator.appVersion 的值构成的。
例如 “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36”

注 用户代理头中也有个 user-agent header


screen 屏幕信息

screen.width;       // 屏幕宽度(以像素为单位)
screen.height;      // 屏幕高度
screen.availWidth;  // 可用屏幕宽度(减去窗口装饰)
screen.availHeight; // 可用屏幕高度
screen.colorDepth;  // 颜色深度(位)
screen.pixelDepth;  // 像素深度(位)

// 应用场景:响应式设计
if (screen.width < 768) {
    document.body.classList.add("mobile-layout");
}

console 控制台

console 提供浏览器控制台接口

console.log("日志消息");
console.error("错误消息");
console.warn("警告消息");
console.info("信息消息");
console.debug("调试消息");

console.group("分组标题");
console.log("组内消息");
console.groupEnd();

console.table([{name: "John", age: 30}, {name: "Jane", age: 25}]);

// 计时功能
console.time("timer");
// 执行一些操作...
console.timeEnd("timer"); // 显示执行时间

history 历史记录

history.length;     // 历史记录中的条目数
history.state;      // 当前历史记录的关联状态对象

history.back();     // 返回上一页
history.forward();  // 前进到下一页
history.go(-2);     // 后退两页

// 添加历史记录并更改URL(不会实际加载页面)
history.pushState({page: "settings"}, "Settings", "/settings"); 

sessionStorage 会话存储

会话存储(标签页关闭时清除)
不同 源(Origin) 之间 sessionStorage 是隔离的,不同标签页之间也是隔离的。

sessionStorage.setItem("sessionId", "xyz123");
const id = sessionStorage.getItem("sessionId");

localStorage 持久化存储

持久性存储(关闭浏览器后仍然存在)
不同 源(Origin) 之间 localStorage 是隔离的。

// 保存数据
localStorage.setItem("username", "john_doe");
localStorage.setItem("preferences", JSON.stringify({theme: "dark"}));

// 读取数据
const username = localStorage.getItem("username");
const preferences = JSON.parse(localStorage.getItem("preferences"));

// 移除数据
localStorage.removeItem("username");
localStorage.clear(); // 清除所有

indexedDB 数据库

大型结构化数据存储
不同 源(Origin) 之间 indexedDB 是隔离的。

// 打开数据库
const request = indexedDB.open("myDatabase", 1);

request.onupgradeneeded = (event) => {
    const db = event.target.result;
    const store = db.createObjectStore("users", {keyPath: "id"});
    store.createIndex("email", "email", {unique: true});
};

request.onsuccess = (event) => {
    const db = event.target.result;
    
    // 添加数据
    const transaction = db.transaction("users", "readwrite");
    const store = transaction.objectStore("users");
    store.add({id: 1, name: "John", email: "john@example.com"});
    
    // 获取数据
    const getRequest = store.get(1);
    getRequest.onsuccess = () => {
        console.log(getRequest.result);
    };
};

DOM 操作

// 获取<html>元素,即 根元素
const root = document.documentElement;

// 获取<head>和<body>
const head = document.head;
const body = document.body;

// 获取所有<h1>元素
const headings = document.getElementsByTagName("h1");

// 使用CSS选择器查找元素
const element = document.querySelector("#container > .item");

// 遍历元素
const listItems = document.querySelectorAll("ul > li");
listItems.forEach(item => {
    console.log(item.textContent);
});

// 动态修改DOM
const newDiv = document.createElement("div");
newDiv.textContent = "新添加的元素";
document.body.appendChild(newDiv);

const toRemove = document.getElementById("oldElement");
toRemove.parentNode.removeChild(toRemove);

scrollTop()

scrollTop() 方法设置或返回被选元素的【垂直滚动条位置】,即元素距离他容器顶部的像素距离
当滚动条位置位于最顶部时,位置是0;即当一个元素的容器没有产生垂直方向的滚动条,那它的 scrollTop 的值默认为0。
当滚动条位置位于最底部时,位置是元素的高度;

1.未设置时默认为0
2.为负值时不做任何响应
3.设置为超出本身最大值时,默认为最大值

scrollTop() 实现聊天窗口自动滚动

<div id="div-received-msg" class="div-received-msg"></div>
// 始终显示滚动条最底部
$("#div-received-msg").scrollTop($("#div-received-msg").prop("scrollHeight"));

其中 scrollHeight 是对象的高度,包含内边距,但不包括水平滚动条、边框和外边距。

scrollTop() 实现瀑布数据流加载

如果元素滚动到底,下面等式返回true,没有则返回false.
element.scrollHeight - element.scrollTop === element.clientHeight


JavaScript 获取 html 元素值

JavaScript 中取得元素的方法有4种:分别是:

  • 1、getElementById() :通过id取得HTML元素。
  • 2、getElementsByName() :通过name取得元素,是一个数组。
  • 3、getElementsByTagName() :通过HTML标签取得元素,是一个数组。
  • 4、getElementsByClassName() :根据类名获得元素,是一个数组

getElementById()

getElementById() 方法可返回对拥有指定 ID 的第一个对象的引用。
HTML DOM 定义了多种查找元素的方法,除了 getElementById() 之外,还有 getElementsByName() 和 getElementsByTagName()。
不过,如果您需要查找文档中的一个特定的元素,最有效的方法是 getElementById()。
在操作文档的一个特定的元素时,最好给该元素一个 id 属性,为它指定一个(在文档中)唯一的名称,然后就可以用该 ID 查找想要的元素。

例1,获取元素标签内的值

<html>
  <head>
  <script type="text/javascript">
    function getValue()
      {
      var x=document.getElementById("myHeader")
      alert(x.innerHTML)
      }
  </script>
  </head>

  <body>
    <h1 id="myHeader" onclick="getValue()">This is a header</h1>
    <p>Click on the header to alert its value</p>
  </body>
</html>

例2,自定义id(x)方法
getElementById() 是一个重要的方法,在 DOM 程序设计中,它的使用非常常见。我们为您定义了一个工具函数,这样您就可以通过一个较短的名字来使用 getElementById() 方法了:

function id(x) {
  if (typeof x == "string") return document.getElementById(x);
  return x;
  }

上面这个函数接受元素 ID 作为它们的参数。对于每个这样的参数,您只要在使用前编写 x = id(x) 就可以了。


getElementsByName()

getElementsByName() 方法可返回带有指定名称的对象的集合。
该方法与 getElementById() 方法相似,但是它查询元素的 name 属性,而不是 id 属性。
另外,因为一个文档中的 name 属性可能不唯一(如 HTML 表单中的单选按钮通常具有相同的 name 属性),所有 getElementsByName() 方法返回的是元素的数组,而不是一个元素。

例,统计文档内name为myInput的标签有多少个

<html>
  <head>
    <script type="text/javascript">
    function getElements()
      {
      var x=document.getElementsByName("myInput");
      alert(x.length);
      }
    </script>
  </head>

  <body>
    <input name="myInput" type="text" size="20" /><br />
    <input name="myInput" type="text" size="20" /><br />
    <input name="myInput" type="text" size="20" /><br />
    <br />
    <input type="button" onclick="getElements()" value="名为 'myInput' 的元素有多少个?" />
  </body>
</html>

getElementsByTagName()

getElementsByTagName() 方法可返回带有指定标签名的对象的集合。
getElementsByTagName() 方法返回元素的顺序是它们在文档中的顺序。
如果把特殊字符串 “*” 传递给 getElementsByTagName() 方法,它将返回文档中所有元素的列表,元素排列的顺序就是它们在文档中的顺序。
注意:传递给 getElementsByTagName() 方法的字符串可以不区分大小写。

例1,统计文档内有多少个input标签

<html>
  <head>
    <script type="text/javascript">
      function getElements()
        {
        var x=document.getElementsByTagName("input");
        alert(x.length);
        }
    </script>
  </head>

  <body>
    <input name="myInput" type="text" size="20" /><br />
    <input name="myInput" type="text" size="20" /><br />
    <input name="myInput" type="text" size="20" /><br />
    <br />
    <input type="button" onclick="getElements()" value="How many input elements?" />
  </body>
</html>

例2,统计文档内有多少表格table

var tables = document.getElementsByTagName("table");
alert ("This document contains " + tables.length + " tables");

例3,获得文档中的第4个段落
如果您非常了解文档的结构,也可以使用 getElementsByTagName() 方法获取文档中的一个特定的元素。例如,下面的代码可以获得文档中的第四个段落:
var myParagragh = document.getElementsByTagName("p")[3];
不过,如果您需要操作某个特定的元素,使用 getElementById() 方法将更为有效。

例4,获取id=”main”的元素中的所有p元素
下面的例子返回包含文档中所有p元素的列表,并且这些p元素应该是 id=”main” 的元素的后代(子、孙等等):
document.getElementById("main").getElementsByTagName("p");


getElementsByClassName()

getElementsByClassName() 方法返回文档中所有指定类名的元素集合,作为 NodeList 对象,元素在集合中的顺序以其在代码中的出现次序排序。
若获取class为多个类的元素,多个类名使用空格分隔,如 “test demo”。
NodeList 对象代表一个有顺序的节点列表。NodeList 对象 我们可通过节点列表中的节点索引号来访问列表中的节点(索引号由0开始)。
提示: 你可以使用 NodeList 对象的 length 属性来确定指定类名的元素个数,并循环各个元素来获取你需要的那个元素。
注意: Internet Explorer 8 及更早 IE 版本不支持 getElementsByClassName() 方法。

例1,获取class为”example”和”color”的所有元素
var x = document.getElementsByClassName("example color");

例2,统计文档中有多少个class为example的元素

<html>
  <body>
    <div class="example">样式 class="example" 的 div 元素</div>
    <div class="example">另外一个样式 class="example" 的 div 元素</div>
    <p class="example">样式 class="example" 的 p 元素</p>
    <p>点击按钮查看文档中有多少个类名为 "example" 的元素。</p>
    <button onclick="myFunction()">点我</button>
    <p><strong>注意:</strong> Internet Explorer 8 及更早 IE 版本不支持 getElementsByClassName() 方法。</p>
    <p id="demo"></p>

    <script>
    function myFunction() {
        var x = document.getElementsByClassName("example");
        document.getElementById("demo").innerHTML = x.length;
    }
    </script>
  </body>
</html>

例3,修改所有样式class为”example”的元素的背景颜色

<html>
  <head>
    <style>
      .example {
          border: 1px solid black;
          margin: 5px;
      }
    </style>
  </head>

  <body>
    <div class="example">样式 class="example" 的 Div 元素</div>
    <div class="example">另外一个样式 class="example" 的 Div 元素</div>
    <p class="example">样式为 class="example" 的 p 元素。</p>
    <p>这是一个插入在 p 元素中样式 class="example" 的<span class="example">span</span> 元素 。</p>
    <p>点击按钮修改所有样式 class="example" 的背景颜色。</p>
    <button class="example" onclick="myFunction()">点我</button>
    <p><strong>注意:</strong> Internet Explorer 8 及更早 IE 版本不支持 getElementsByClassName() 方法。</p>

    <script>
    function myFunction() {
        var x = document.getElementsByClassName("example");
        var i;
        for (i = 0; i < x.length; i++) {
            x[i].style.backgroundColor = "red";
        }
    }
    </script>
  </body>
</html>

例4,修改第一个类为”example color”的div元素的背景颜色

<html>
  <head>
    <style>
      div {
          border: 1px solid black;
          margin: 5px;
      }
    </style>
  </head>

  <body>
    <div class="example">
      <p>P 元素在在第一个样式为 class="example" 的 Div 元素中。Div 的索引值为 0。</p>
    </div>
    <div class="example color">
      <p>P 元素在在第一个样式为 class="example color" 的 Div 元素中。Div 的索引值为 0。</p>
    </div>
    <div class="example color">
      <p>P 元素在在第二个样式为 class="example color" 的 Div 元素中。Div 的索引值为 1。</p>
    </div>
    <p>点击按钮修改第一个类为 "example color" 的 div 元素的背景颜色。</p>
    <button onclick="myFunction()">点我</button>
    <p><strong>注意:</strong> Internet Explorer 8 及更早 IE 版本不支持 getElementsByClassName() 方法。</p>

    <script>
    function myFunction() {
        var x = document.getElementsByClassName("example color");
        x[0].style.backgroundColor = "red";
    }
    </script>
  </body>
</html>

innerHTML 与 value 的区别

getElementById().innerHTML 与 getElementById().value 的区别
有value属性的标签才能操作其value值,只有input等表单输入标签才有value值。
例如:
<input type="text" id="txt1" value="hello"/>
这样一个元素,当你使用document.getElementById(“txt1”).value时,可以得到其value值,即”hello”这个字符串。
如果一个元素没有value值,那么使用document.getElementById().value时是取不到。这是理所当然的,没有的东西怎么访问?
比如一个div标记,就不一定有value值。

innerHTML是指元素起始标记和结束标记之间的内容。
例如:
<label id="lb1">this is a label</label>
当你使用document.getElementById(“lb1”).innerHTML可以取到<label></label>之间的内容,即“this is a label”。

一个实例如下:

<html>
  <head>
    <script type="text/javascript">
      function getValue()
      {
      var x=document.getElementById("myHeader")
      alert(x.innerHTML)
      }
      function getValue2()
      {
      var x=document.getElementById("myInput")
      alert(x.value)
      }
    </script>
  </head>

  <body>
    <h1 id="myHeader" onclick="getValue()">这是标题</h1>
    <input id="myInput" type="text" value="value值" onclick="getValue2()" />
    <p>点击标题,会提示出它的innerHTML值。</p>
    <p>点击input框,会提示出它的value值。</p>
  </body>
</html>

HttpOnly 的设计目的
​​安全机制​​:HttpOnly 是浏览器提供的安全特性
​​防 XSS​​:专门防御跨站脚本攻击 (XSS)
​​敏感数据保护​​:用于保护包含敏感信息(如会话 ID、身份令牌)的 Cookie

JavaScript 访问限制
document.cookie 属性会​​完全忽略​​所有标记为 HttpOnly 的 Cookie
JavaScript ​​无法通过任何 API​​ 读取 HttpOnly Cookie
即使尝试遍历 Cookie 或使用特殊技巧,仍然无法获取


对于同源请求,浏览器​​自动且无条件​​发送所有相关 Cookie,无需任何特殊 JS 设置(如 credentials: ‘include’)

例如
页面访问​​:http://localhost:8000/user/profile
​​API访问​​:http://localhost:8000/api/v1/user/findDetail
是同源的,所以会自动携带 access_token 等 Cookie
但是如果 api 接口是 http://api.localhost:8000/data 就不是同源了,不会自动携带 Cookie


document.cookie 返回结果样式 cookie1=value1; cookie2=value2; ...

// 设置cookie
document.cookie = "username=john_doe; expires=Thu, 18 Dec 2025 12:00:00 UTC; path=/";

// 读取cookie
function getCookie(name) {
    const cookies = document.cookie.split(';');
    for (const cookie of cookies) {
        const [key, value] = cookie.split('=');
        if (key.trim() === name) return decodeURIComponent(value);
    }
    return null;
}

console.log(getCookie("username"));

https://github.com/js-cookie/js-cookie


上一篇 Spring-JDBC

下一篇 c3p0

阅读
评论
5.9k
阅读预计26分钟
创建日期 2017-05-22
修改日期 2025-08-25

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论