Skip to content

BOM、DOM ​

BOM ​

js
window对象是BOM的根对象,其它对象都是window对象的属性;浏览器环境全局对象,表示一个标签页(窗口);
在全局作用下,this关键字指向window;所有子对象或子属性都可以省略'window.';
var 声明的对象,都是window的子属性;
function 声明的全局函数,也是window的子属性;

改变地址的锚点值;
window.onhashchange = function(){}  //捕捉锚点改变

打开关闭页面
`window.open(url,name,attr,boolean)` //url地址,name名字,attr属性设置 boolean:false新历史,true替换历史;
`window.close()` //直接调用方法,关闭当前窗口;
window对象是BOM的根对象,其它对象都是window对象的属性;浏览器环境全局对象,表示一个标签页(窗口);
在全局作用下,this关键字指向window;所有子对象或子属性都可以省略'window.';
var 声明的对象,都是window的子属性;
function 声明的全局函数,也是window的子属性;

改变地址的锚点值;
window.onhashchange = function(){}  //捕捉锚点改变

打开关闭页面
`window.open(url,name,attr,boolean)` //url地址,name名字,attr属性设置 boolean:false新历史,true替换历史;
`window.close()` //直接调用方法,关闭当前窗口;

location ​

javascript
location.href:用于获得或设置路径值;
location.hash:用于获得或设置锚点值(url从#开始的部分);
location.host:用于获得或设置主机名和端口号;
location.pathname:用于获得或设置路径名;
location.port:用于获得或设置端口号;
location.protocol:用于获得协议;
location.search:用于获得地址栏中从?开始的部分;
location.assign('地址')跳转有历史记录;
location.replace('地址')跳转没有历史记录(免登录常用)
location.reload()刷新,重新加载页面;
location.href:用于获得或设置路径值;
location.hash:用于获得或设置锚点值(url从#开始的部分);
location.host:用于获得或设置主机名和端口号;
location.pathname:用于获得或设置路径名;
location.port:用于获得或设置端口号;
location.protocol:用于获得协议;
location.search:用于获得地址栏中从?开始的部分;
location.assign('地址')跳转有历史记录;
location.replace('地址')跳转没有历史记录(免登录常用)
location.reload()刷新,重新加载页面;

history ​

history:历史页面,拥有的方法如下:

  • back();返回上一个;
  • forward();返回下一个;forward(前锋);
  • go(num);0:当前,-1 上一个,1 下一个;也可以 2 或-2;
  • pushState({p: '/b'},null,'/b'),在网址后面添加 b; 不会刷新页面
  • replaceState():与 pushstate 相同,不会保留历史栈
  • listen(location => {}):监听路由的变化;

window.onhashchange,当 hash 值发生改变时触发,e.oldURL,e.newURL可以访问

window 页面事件 ​

以下均为 window 的方法

  • load:页面加载完成
  • beforeunload:页面即将离开,页面刷新、页面跳转都会触发;
  • pageshow:页面显示
  • pagehide:页面离开
  • popstate:浏览器前进后退时触发,页面跳转不触发
  • hashchange:当 hash 发生改变时触发,e.oldURL和newURL可以访问;

实践:

监听页面停留时间:可以通过beforeunload和onpageshow控制;

  • appCodeName:浏览器代号
  • appName:服务器名称
  • appVersion:浏览器版本
  • cookieEnabled:检测 Cookies
  • platform:硬件平台
  • userAgent:浏览器信息
  • systemLanguage:代理语言
js
window.onload = function () {
    var txt = “<p> 浏览器代号 : “ + navigator.appCodeName + “</p>”;
    txt+= “<p> 浏览器名称 : “ + navigator.appName + “</p>”;
    txt+= “<p> 浏览器版本 : “ + navigator.appVersion + “</p>”;
    txt+= “<p> 启用 Cookies: “ + navigator.cookieEnabled + “</p>”;
    txt+= “<p> 硬件平台 : “ + navigator.platform + “</p>”;
    txt+= “<p> 用户代理 : “ + navigator.userAgent + “</p>”;
    txt+= “<p> 用户代理语言 : “ + navigator.systemLanguage + “</p>”;
    document.getElementById(“example”).innerHTML=txt;
}
window.onload = function () {
    var txt = “<p> 浏览器代号 : “ + navigator.appCodeName + “</p>”;
    txt+= “<p> 浏览器名称 : “ + navigator.appName + “</p>”;
    txt+= “<p> 浏览器版本 : “ + navigator.appVersion + “</p>”;
    txt+= “<p> 启用 Cookies: “ + navigator.cookieEnabled + “</p>”;
    txt+= “<p> 硬件平台 : “ + navigator.platform + “</p>”;
    txt+= “<p> 用户代理 : “ + navigator.userAgent + “</p>”;
    txt+= “<p> 用户代理语言 : “ + navigator.systemLanguage + “</p>”;
    document.getElementById(“example”).innerHTML=txt;
}
  • getBattery:电池状态
  • vibrate:设备震动

设备手机电池状态 ​

getBattery 电池状态

js
navigator.getBattery().then((battery) => console.log(battery))
// 返回
{
  charging, // 是否在充电
    chargingTime, // 充满电所需时间
    dischargingTime, // 当前电量可使用时间
    level,
    剩余电量

  onchargingchange, // 监听充电状态变化
    onchargingtimechange, // 监听充满电所需时间变化
    ondischargingtimechange, // 监听当前电量可使用时间变化
    onlevelchange // 监听电量变化
}
navigator.getBattery().then((battery) => console.log(battery))
// 返回
{
  charging, // 是否在充电
    chargingTime, // 充满电所需时间
    dischargingTime, // 当前电量可使用时间
    level,
    剩余电量

  onchargingchange, // 监听充电状态变化
    onchargingtimechange, // 监听充满电所需时间变化
    ondischargingtimechange, // 监听当前电量可使用时间变化
    onlevelchange // 监听电量变化
}

使用场景:提示用户电量已充满,或者为了让用户有安全感,电量低于 99%的时候来个弹框提示"该充电啦"✅

使设备进行震动 ​

vibration

js
// 震动一次
navigator.vibrate(100)

// 连续震动,震动200ms、暂停100ms、震动300ms
navigator.vibrate([200, 100, 300])
// 震动一次
navigator.vibrate(100)

// 连续震动,震动200ms、暂停100ms、震动300ms
navigator.vibrate([200, 100, 300])

效果如下:不好意思你得用你自己的手握住手机才能感受得到;

使用场景:通过振动来提供感官反馈,比如太久没有触摸屏幕的时候连续震动提醒用户 ✅

页面显示隐藏 ​

js
document.addEventListener('visibilitychange', () => {
  console.log(`页面可见性:${document.visibilityState}`)
  console.log(`页面可见性:${document.hidden}`)
})
document.addEventListener('visibilitychange', () => {
  console.log(`页面可见性:${document.visibilityState}`)
  console.log(`页面可见性:${document.hidden}`)
})

document.visibilityState的状态值:

  • 当页面离开时会触发该函数,hidden 的属性值

  • 当页面显示时,会返回一个 visible

document.hidden:当页面显示状态返回 false;

使用场景:当程序切到后台的时候,如果当前有视频播放或者一些动画执行,可以先暂停 ✅

页面方向陀螺仪 ​

deviceOrientation(如果 IOS 失效,可以将域名协议改为 https)

image-20250228182734882

从左到右分别为 alpha、beta、gamma

js
window.addEventListener('deviceorientation', (event) => {
  let { alpha, beta, gamma } = event

  console.log(`alpha:${alpha}`)
  console.log(`beta:${beta}`)
  console.log(`gamma:${gamma}`)
})
window.addEventListener('deviceorientation', (event) => {
  let { alpha, beta, gamma } = event

  console.log(`alpha:${alpha}`)
  console.log(`beta:${beta}`)
  console.log(`gamma:${gamma}`)
})

使用场景:页面上的某些元素需要根据手机摆动进行移动,达到视差的效果,比如王者荣耀进入游戏的那个界面,手机转动背景图会跟着动 😂

网络状态 ​

在线online 离线offline

监听当前的网络状态变动事件:

js
window.addEventlistener('online', xxx)
window.addEventlistener('offline', () => {
  alert('您断网啦;')
})
window.addEventlistener('online', xxx)
window.addEventlistener('offline', () => {
  alert('您断网啦;')
})

PC 端测试:点击 NetWork,之后点击 offline,可以测试;

手机端:关闭移动网络之后就可以提示了;

​

notification 桌面通知 ​

PC 端的桌面通知,如网页端的微信, 当收到消息时,右下角会出现一个通知(尽管你把浏览器最小化),因为这个通知时独立于浏览器的,是系统的一个原生控件:

js
const notice = new Notification('前端宇宙情报局', {
  body: '这20个不常用的Web API真的有用吗?,别问,问就是有用🈶',
  icon: '我的掘金头像',
  data: {
    url: 'https://www.baidu.com',
  },
})

// 点击回调
notice.onclick = () => {
  window.open(notice.data.url) // 当用户点击通知时,在浏览器打开百度网站
}
const notice = new Notification('前端宇宙情报局', {
  body: '这20个不常用的Web API真的有用吗?,别问,问就是有用🈶',
  icon: '我的掘金头像',
  data: {
    url: 'https://www.baidu.com',
  },
})

// 点击回调
notice.onclick = () => {
  window.open(notice.data.url) // 当用户点击通知时,在浏览器打开百度网站
}

注意:想要成功的调起通知,首先要用户的授权 ✅

image-20250724145613964

image-20250724145630765

js
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>获取通知权限示例</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body class="p-8 bg-gray-50">
    <div class="max-w-md mx-auto bg-white p-6 rounded-lg shadow-md">
        <h1 class="text-2xl font-bold mb-4 text-gray-800">通知权限管理</h1>
        <p class="text-gray-600 mb-6">点击按钮获取或查看通知权限状态</p>

        <button id="checkPermission" class="bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded mr-2">
            <i class="fa fa-info-circle mr-1"></i> 检查权限状态
        </button>

        <button id="requestPermission" class="bg-green-500 hover:bg-green-600 text-white py-2 px-4 rounded">
            <i class="fa fa-bell mr-1"></i> 请求通知权限
        </button>
        <!-- 发起通知 -->
        <button id="notify" class="bg-purple-500 hover:bg-purple-600 text-white py-2 px-4 rounded">
            <i class="fa fa-bullhorn mr-1"></i> 发起通知
        </button>

        <div id="status" class="mt-6 p-4 rounded border"></div>
    </div>

    <script>
        // 权限状态文本映射
        const permissionText = {
            'default': '尚未决定(点击"请求通知权限"按钮授权)',
            'granted': '已授予(可以显示通知)',
            'denied': '已拒绝(需要在浏览器设置中手动开启)'
        };

        // 权限状态样式映射
        const permissionStyles = {
            'default': 'border-yellow-300 bg-yellow-50 text-yellow-800',
            'granted': 'border-green-300 bg-green-50 text-green-800',
            'denied': 'border-red-300 bg-red-50 text-red-800'
        };

        // 检查权限状态
        document.getElementById('checkPermission').addEventListener('click', () => {
            if (!("Notification" in window)) {
                showStatus('当前浏览器不支持通知功能', 'denied');
                return;
            }

            const status = Notification.permission;
            showStatus(`当前权限状态:${permissionText[status]}`, status);
        });

        // 请求权限
        document.getElementById('requestPermission').addEventListener('click', () => {
            if (!("Notification" in window)) {
                showStatus('当前浏览器不支持通知功能', 'denied');
                return;
            }

            // 只有当权限为default时才需要请求
            if (Notification.permission === 'default') {
                Notification.requestPermission().then(permission => {
                    showStatus(`权限已更新:${permissionText[permission]}`, permission);
                });
            } else {
                showStatus(`无需重复请求,当前状态:${permissionText[Notification.permission]}`, Notification.permission);
            }
        });

        // 显示状态信息
        function showStatus(message, status) {
            const statusEl = document.getElementById('status');
            statusEl.textContent = message;
            statusEl.className = `mt-6 p-4 rounded border ${permissionStyles[status] || ''}`;
        }

        // 页面加载时自动检查一次
        window.addEventListener('load', () => {
            if ("Notification" in window) {
                const status = Notification.permission;
                showStatus(`初始权限状态:${permissionText[status]}`, status);
            } else {
                showStatus('当前浏览器不支持通知功能', 'denied');
            }
        });

        // 发起通知
        document.getElementById('notify').addEventListener('click', () => {
            if (Notification.permission === 'granted') {
                new Notification('前端宇宙情报局', {
                    body: '这20个不常用的Web API真的有用吗?,别问,问就是有用🈶',
                    // 使用有效的图片URL
                    icon: 'https://picsum.photos/48/48',
                    data: {
                        url: 'https://www.baidu.com',
                    },
                });
            } else {
                showStatus('请先授予通知权限', 'denied');
            }
        });
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>获取通知权限示例</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body class="p-8 bg-gray-50">
    <div class="max-w-md mx-auto bg-white p-6 rounded-lg shadow-md">
        <h1 class="text-2xl font-bold mb-4 text-gray-800">通知权限管理</h1>
        <p class="text-gray-600 mb-6">点击按钮获取或查看通知权限状态</p>

        <button id="checkPermission" class="bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded mr-2">
            <i class="fa fa-info-circle mr-1"></i> 检查权限状态
        </button>

        <button id="requestPermission" class="bg-green-500 hover:bg-green-600 text-white py-2 px-4 rounded">
            <i class="fa fa-bell mr-1"></i> 请求通知权限
        </button>
        <!-- 发起通知 -->
        <button id="notify" class="bg-purple-500 hover:bg-purple-600 text-white py-2 px-4 rounded">
            <i class="fa fa-bullhorn mr-1"></i> 发起通知
        </button>

        <div id="status" class="mt-6 p-4 rounded border"></div>
    </div>

    <script>
        // 权限状态文本映射
        const permissionText = {
            'default': '尚未决定(点击"请求通知权限"按钮授权)',
            'granted': '已授予(可以显示通知)',
            'denied': '已拒绝(需要在浏览器设置中手动开启)'
        };

        // 权限状态样式映射
        const permissionStyles = {
            'default': 'border-yellow-300 bg-yellow-50 text-yellow-800',
            'granted': 'border-green-300 bg-green-50 text-green-800',
            'denied': 'border-red-300 bg-red-50 text-red-800'
        };

        // 检查权限状态
        document.getElementById('checkPermission').addEventListener('click', () => {
            if (!("Notification" in window)) {
                showStatus('当前浏览器不支持通知功能', 'denied');
                return;
            }

            const status = Notification.permission;
            showStatus(`当前权限状态:${permissionText[status]}`, status);
        });

        // 请求权限
        document.getElementById('requestPermission').addEventListener('click', () => {
            if (!("Notification" in window)) {
                showStatus('当前浏览器不支持通知功能', 'denied');
                return;
            }

            // 只有当权限为default时才需要请求
            if (Notification.permission === 'default') {
                Notification.requestPermission().then(permission => {
                    showStatus(`权限已更新:${permissionText[permission]}`, permission);
                });
            } else {
                showStatus(`无需重复请求,当前状态:${permissionText[Notification.permission]}`, Notification.permission);
            }
        });

        // 显示状态信息
        function showStatus(message, status) {
            const statusEl = document.getElementById('status');
            statusEl.textContent = message;
            statusEl.className = `mt-6 p-4 rounded border ${permissionStyles[status] || ''}`;
        }

        // 页面加载时自动检查一次
        window.addEventListener('load', () => {
            if ("Notification" in window) {
                const status = Notification.permission;
                showStatus(`初始权限状态:${permissionText[status]}`, status);
            } else {
                showStatus('当前浏览器不支持通知功能', 'denied');
            }
        });

        // 发起通知
        document.getElementById('notify').addEventListener('click', () => {
            if (Notification.permission === 'granted') {
                new Notification('前端宇宙情报局', {
                    body: '这20个不常用的Web API真的有用吗?,别问,问就是有用🈶',
                    // 使用有效的图片URL
                    icon: 'https://picsum.photos/48/48',
                    data: {
                        url: 'https://www.baidu.com',
                    },
                });
            } else {
                showStatus('请先授予通知权限', 'denied');
            }
        });
    </script>
</body>
</html>

保存页面中的信息,比如用户名、密码等;比较小,只有 4kb;

不同浏览器的 cookie 是不相通的;

谷歌浏览器的 cookie 不允许访问本地的 cookie,只允许访问网上的,而火狐和 ie 可以访问本地的;

如果不在浏览器中设置过期时间,cookie 被保存在内存中,生命周期随浏览器的关闭而结束,这种 cookie 简称会话 cookie。

如果设置 cookie 的过期时间,cookie 被 保存在硬盘中,关闭浏览器后,cookie 数据仍然存在,直到过期时间结束才消失。

操作方式 ​

  • 存储:document.cookie = "key=value"; 设置临时存储,键值对;
js
document.cookie = "key=12;expires=" + 字符串格式时间;有过期时间;
document.cookie = "key=12;expires=" + 字符串格式时间;有过期时间;

date.setSeconds();设置秒,可以设置所有时间;

  • 读取:document.cookie;获取的是字符串,中间用分号和空格分开的;

  • 删除:将过期时间设置成负数;

js
var date = new Date()
date.setDate(date.getDate() + 10) //设置10天以后过期;
date.toString() //10天以后的字符串格式时间
var date = new Date()
date.setDate(date.getDate() + 10) //设置10天以后过期;
date.toString() //10天以后的字符串格式时间
  • (1)(失效) Session 会在浏览器关闭之后失效,Cookie 则可以在理论上永久有效(设置过期时间)。
  • (2)(存放) Cookie 数据存放在客户的浏览器上, Session 数据存放在服务器上。
  • (3)(黑客) Cookie 不安全,黑客可以分析本地的 Cookie, 并进行 Cookie 欺骗。 而 Session 保存在远程服务器上,相对安全(重要的信息应该存在 session);
  • (4)(限制) Cookie 有大小限制,一般是 4KB。 域名 20-50 个以内,Session 则没有这方面的限制。
  • (5)(禁用) 浏览器的设置可能禁用 Cookie,这时所有关于 Cookie 的应用都将失败,但是 Session 却永远不会有这个问题;

Session 依赖 cookie,因为 session id 存在客户端。

  1. 安装:npm i js-cookie
  2. 用法:

在项目中引入:import Cookie from 'js-cookie'

(1)Cookie.set('name','value', {expires: 7, path:''}),name 和 value 不可少

(2)Cookie.get('name', {domain: 'sub.example.com'}),name 不可少

(3)Cookie.remove('name', {path: '',domain: ''}),name 不可少

  1. 解决命名空间冲突问题
js
const Cookies2 = Cookies.noConflict()
Cookies2.set('name', 'value')
const Cookies2 = Cookies.noConflict()
Cookies2.set('name', 'value')
  1. 安全
js
// 需要使用https才有效
Cookies.set('name', 'value', { secure: true })
// 需要使用https才有效
Cookies.set('name', 'value', { secure: true })
  1. 设置默认值
js
const api = Cookies.withAttributes({ path: '/', domain: '.example.com' })
const api = Cookies.withAttributes({ path: '/', domain: '.example.com' })
  1. 控制读写
js
var cookie = Cookies.withConverter({
  // 读
  read: function (value, name) {
    if (name === 'escaped') {
    }
    return Cookies.converter.read(value, name)
  },
  // 写
  write: function (value, name) {
    return value.toUpperCase()
  },
})
// 之后使用cookie对象来进行读写操作
var cookie = Cookies.withConverter({
  // 读
  read: function (value, name) {
    if (name === 'escaped') {
    }
    return Cookies.converter.read(value, name)
  },
  // 写
  write: function (value, name) {
    return value.toUpperCase()
  },
})
// 之后使用cookie对象来进行读写操作

web Storage(HTML5) ​

区别 ​

localStorage的储存没有时间限制,永久保存,除非主动删除;

sessionStorage用于临时保存同一窗口(或标签页)的数据,在关闭窗口之后将会删除这些数据;

兼容:ie8+

特点 ​

(1)生命周期:

  • localStorage:永久的,关闭浏览器都不会消失,除非主动删除数据;

  • sessionStorage:仅在当前会话下有效,只要窗口没关闭,数据永远存在,刷新页面都在;两个窗口的 sessionStorage 数据是不一样的;

(2)存储大小:两者都是 5MB;

(3)存储位置:都保存在客户端,不与服务器进行交互通信;

(4)存储类型:仅支持字符串类型,对象数组需要使用 JSON 对象的 stringify 和 parse 处理;

(5)应用场景:

  • localStorage:常用于长期登录,适合长期保存在本地的数据;
  • sessionStorage:敏感账号一次性登录;

用法 ​

localStorage 和 sessionStorage 使用方法一致;

  1. 储存:setItem(key, value)
  2. 获取:getItem(key)
  3. 删除:removeItem(key)
  4. 清空:clear();
  5. 索引:key(index) 可以通过索引获取;

除了以上方式,还支持点的方式或中括号方式:

设置:localStorage.age = 18

获取:localStorage.age

当储存的值是对象或者数组时:

储存:localStorage.setItem('test',JSON.stringify({id:1,age:18});

取值:JSON.parse(localStorage.getItem('test');

全屏事件 ​

常用于在后台里面需要点击全屏时的事件

js
/**
 * @method launchFullScreen 开启全屏
 * @param {Object} elem = document.documentElement 作用的元素
 */
const launchFullScreen = (elem = document.documentElement) => {
  if (elem.requestFullScreen) {
    elem.requestFullScreen()
  } else if (elem.mozRequestFullScreen) {
    elem.mozRequestFullScreen()
  } else if (elem.webkitRequestFullScreen) {
    elem.webkitRequestFullScreen()
  }
}

/**
 * @method exitFullScreen 关闭全屏
 */
const exitFullScreen = () => {
  if (document.exitFullscreen) {
    document.exitFullscreen()
  } else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen()
  } else if (document.webkitCancelFullScreen) {
    document.webkitCancelFullScreen()
  }
}
/**
 * @method launchFullScreen 开启全屏
 * @param {Object} elem = document.documentElement 作用的元素
 */
const launchFullScreen = (elem = document.documentElement) => {
  if (elem.requestFullScreen) {
    elem.requestFullScreen()
  } else if (elem.mozRequestFullScreen) {
    elem.mozRequestFullScreen()
  } else if (elem.webkitRequestFullScreen) {
    elem.webkitRequestFullScreen()
  }
}

/**
 * @method exitFullScreen 关闭全屏
 */
const exitFullScreen = () => {
  if (document.exitFullscreen) {
    document.exitFullscreen()
  } else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen()
  } else if (document.webkitCancelFullScreen) {
    document.webkitCancelFullScreen()
  }
}

DOM ​

DOM 模型 ​

方法描述
getElementById()返回带有指定 ID 的元素。
getElementsByTagName()返回包含带有指定标签名称的所有元素的节点列表(集合/节点数组)。
getElementsByClassName()返回包含带有指定类名的所有元素的节点列表。
appendChild()把新的子节点添加到指定节点。
removeChild()删除子节点。
replaceChild()替换子节点。
insertBefore()在指定的子节点前面插入新的子节点。
createAttribute()创建属性节点。
createElement()创建元素节点。
createTextNode()创建文本节点。
getAttribute()返回指定的属性值。
setAttribute()把指定属性设置或修改为指定的值。

节点和元素操作 ​

javascript
html文件的根节点为html,获取方式为document.documentElement;
childNodes:获取所有子节点(包含空文本换行);类数组对象(不是数组),获取一个元素的所有子节点;元素有序排列,可以通过做引访问;
children:所有子元素;
parentNode:获得一个元素节点的父节点;最高级别节点是document;
parentElement:父元素;
firstChild:第一个子节点;
firstElementChild:第一个子元素;
lastChild:最后一个子节点;
lastElementChild:最后一个子元素;
previousSibling:获得上一个兄弟节点;
previousElementSibling:上一个兄弟元素;
nextSibling:下一个兄弟节点;
nextElementSibling:下一个兄弟元素;
节点名:
nodeName:返回一个string类型的值,只读属性(不能赋值);

节点值:
nodeValue:(节点的内容)

节点类型:
nodeType:number类型值;
innerHTML:获得/设置对象内全部的HTML代码,字符串类型
textContent:获得或设置元素的文本内容,不能识别标签;
html文件的根节点为html,获取方式为document.documentElement;
childNodes:获取所有子节点(包含空文本换行);类数组对象(不是数组),获取一个元素的所有子节点;元素有序排列,可以通过做引访问;
children:所有子元素;
parentNode:获得一个元素节点的父节点;最高级别节点是document;
parentElement:父元素;
firstChild:第一个子节点;
firstElementChild:第一个子元素;
lastChild:最后一个子节点;
lastElementChild:最后一个子元素;
previousSibling:获得上一个兄弟节点;
previousElementSibling:上一个兄弟元素;
nextSibling:下一个兄弟节点;
nextElementSibling:下一个兄弟元素;
节点名:
nodeName:返回一个string类型的值,只读属性(不能赋值);

节点值:
nodeValue:(节点的内容)

节点类型:
nodeType:number类型值;
innerHTML:获得/设置对象内全部的HTML代码,字符串类型
textContent:获得或设置元素的文本内容,不能识别标签;

属性集合 attribute ​

通过元素的 attributes 可以获得属性集合;属性集合是一个类数组;

可以通过索引或属性名获得元素对应的属性节点;

javascript
1、a.attributes[index].value;
2、a.attributes['属性名'].value;
3、a.getAttributeNode('属性名').value;
4、a.getAttribute('属性名');     //常用法
1、a.attributes['属性名'].nodeValue = value;
2、a.setAttributeNode();
3、a.setAttributeNode('name','value');   //可以新增,常用法
1、a.removeAttributeNode();
2、a.removeAttribute('属性名');
操作数组方法增删改
HTML5新增:classList
a.classList.add('');
a.classList.remove('');
a.classList.replace('','');    //修改
a.classList.toggle('');        //切换类名
document.getElementById():通过id选择元素;
document(node).getElementsByTagName():通过元素名选择元素集合,集合是类数组对象;
document.getElementsByName():通过name属性选择元素(一般情况用来选择表单-radio/checkbox--checked属性),选择结果是类数组对象;
document(node).getElementsByClassName():通过类名选择元素,结果是类数组对象;
document.documentElement():选择整个HTML;
document.querySelector():通过css选择器选择第一个匹配的元素,结果是一个元素节点;
document.querySelectorAll():通过css选择器选择所有匹配的元素,结果是一个类数组对象;
创建元素:document.createElement('标签名');
在结尾追加节点:parentNode.appendChild(childNode);
在指定父节点的某个子节点之前插入节点:parentNode.insertBefore(newChild,existingChild);
1、parentNode.removeChlid(childNode);    //返回被删除的元素
2、DOM.remove();          //没有返回值
   li.remove();
parentNode.replaceChild(newNode,oldNode);
1、a.attributes[index].value;
2、a.attributes['属性名'].value;
3、a.getAttributeNode('属性名').value;
4、a.getAttribute('属性名');     //常用法
1、a.attributes['属性名'].nodeValue = value;
2、a.setAttributeNode();
3、a.setAttributeNode('name','value');   //可以新增,常用法
1、a.removeAttributeNode();
2、a.removeAttribute('属性名');
操作数组方法增删改
HTML5新增:classList
a.classList.add('');
a.classList.remove('');
a.classList.replace('','');    //修改
a.classList.toggle('');        //切换类名
document.getElementById():通过id选择元素;
document(node).getElementsByTagName():通过元素名选择元素集合,集合是类数组对象;
document.getElementsByName():通过name属性选择元素(一般情况用来选择表单-radio/checkbox--checked属性),选择结果是类数组对象;
document(node).getElementsByClassName():通过类名选择元素,结果是类数组对象;
document.documentElement():选择整个HTML;
document.querySelector():通过css选择器选择第一个匹配的元素,结果是一个元素节点;
document.querySelectorAll():通过css选择器选择所有匹配的元素,结果是一个类数组对象;
创建元素:document.createElement('标签名');
在结尾追加节点:parentNode.appendChild(childNode);
在指定父节点的某个子节点之前插入节点:parentNode.insertBefore(newChild,existingChild);
1、parentNode.removeChlid(childNode);    //返回被删除的元素
2、DOM.remove();          //没有返回值
   li.remove();
parentNode.replaceChild(newNode,oldNode);

自定义属性 ​

javascript
HTML5新增,方便保存和操作数据;
语法要求:
所有自定义属性要求 data-  前缀;属性为dataset;
语法:box.dataset;
     box.dataset.name/id/index;
     box.dataset.name/id/index = '';
删除:delete box.dataset.name/id/index;

设置css:
<style>
    div[data-class]{
        width: 100px;
        height: 100px;
        background: #8959a8;
        border: 1px solid #cccccc;
    }
    div[data-class="my"]{
        box-shadow: 0 0 5px 5px #CCCCCC;
    }
</style>
<div id="div1" data-class = "myClass"></div>
<div id="div2" data-class = "my" ></div>

1.如何设置
        通过JavaScript内置的setAttribute('data属性名','新内容')即可设置
        通过该数据类型的 dataset 方法设置data值,IE10以上才支持;
            var button = document.queryselector('button')
            button.dataset.data属性名 = '新内容' ; 这里的data属性名是指data-后面的名字

2.如何获取
        通过JavaScript内置的getAttribute('data属性名') 即可获取
        通过该数据类型的 dataset 方法设置data值,IE10以上才支持;
            var button = document.queryselector('button')
            data = button.dataset.data属性名 ; 这里的data属性名是指data-后面的名字
HTML5新增,方便保存和操作数据;
语法要求:
所有自定义属性要求 data-  前缀;属性为dataset;
语法:box.dataset;
     box.dataset.name/id/index;
     box.dataset.name/id/index = '';
删除:delete box.dataset.name/id/index;

设置css:
<style>
    div[data-class]{
        width: 100px;
        height: 100px;
        background: #8959a8;
        border: 1px solid #cccccc;
    }
    div[data-class="my"]{
        box-shadow: 0 0 5px 5px #CCCCCC;
    }
</style>
<div id="div1" data-class = "myClass"></div>
<div id="div2" data-class = "my" ></div>

1.如何设置
        通过JavaScript内置的setAttribute('data属性名','新内容')即可设置
        通过该数据类型的 dataset 方法设置data值,IE10以上才支持;
            var button = document.queryselector('button')
            button.dataset.data属性名 = '新内容' ; 这里的data属性名是指data-后面的名字

2.如何获取
        通过JavaScript内置的getAttribute('data属性名') 即可获取
        通过该数据类型的 dataset 方法设置data值,IE10以上才支持;
            var button = document.queryselector('button')
            data = button.dataset.data属性名 ; 这里的data属性名是指data-后面的名字

DOM 事件 ​

一般事件
事件描述
onclick鼠标点击事件,多用在某个对象控制的范围内的鼠标点击
onDblClick鼠标双击事件
onMouseDown鼠标上的按钮被按下了
onMouseUp鼠标按下后,松开时激发的事件
onMouseMove鼠标移动时触发的事件
onContextMenu当浏览者按下鼠标右键出现菜单时或者通过键盘的按键触发页面菜单时触发的事件 [试试在页中加入 onContentMenu="return false"就可禁止使用鼠标右键了]
onMouseOver当鼠标移动到某对象范围的上方时触发的事件
onMouseOut当鼠标离开某对象范围时触发的事件
onKeyPress当键盘上的某个键被按下并且释放时触发的事件.[注意:页面内必须有被聚焦的对象]
onKeyDown当键盘上某个按键被按下时触发的事件[注意:页面内必须有被聚焦的对象]
onKeyUp当键盘上某个按键被按放开时触发的事件[注意:页面内必须有被聚焦的对象]
页面相关事件
事件描述
onAbort图片在下载时被用户中断
onBeforeUnload当前页面的内容将要被改变时触发的事件(刷新或者关闭)
onUnload当前页面将被改变时触发的事件(关闭)
onError捕抓当前页面因为某种原因而出现的错误,如脚本错误与外部数据引用的错误
onLoad页面内空完成传送到浏览器时触发的事件,包括外部文件引入完成
onMove浏览器的窗口被移动时触发的事件
onResize当浏览器的窗口大小被改变时触发的事件
onScroll浏览器的滚动条位置发生变化时触发的事件
onStop浏览器的停止按钮被按下时触发的事件或者正在下载的文件被中断
表单相关事件
事件描述
onBlur当前元素失去焦点时触发的事件 [鼠标与键盘的触发均可]
onChange当前元素失去焦点并且元素的内容发生改变而触发的事件 [鼠标与键盘的触发均可](多选框)
onFocus当某个元素获得焦点时触发的事件
onReset当表单中 RESET 的属性被激发时触发的事件
onSubmit一个表单被递交时触发的事件
滚动字幕事件
事件描述
onBounce在 Marquee 内的内容移动至 Marquee 显示范围之外时触发的事件
onFinish当 Marquee 元素完成需要显示的内容后触发的事件
onStart当 Marquee 元素开始显示内容时触发的事件
编辑事件
事件描述
onBeforeCopy当页面当前的被选择内容将要复制到浏览者系统的剪贴板前触发的事件
onBeforeCut当页面中的一部分或者全部的内容将被移离当前页面[剪贴]并移动到浏览者的系统剪贴板时触发的事件
onBeforeEditFocus当前元素将要进入编辑状态
onBeforePaste内容将要从浏览者的系统剪贴板传送[粘贴]到页面中时触发的事件
onBeforeUpdate当浏览者粘贴系统剪贴板中的内容时通知目标对象
onCopy当页面当前的被选择内容被复制后触发的事件
onCut当页面当前的被选择内容被剪切时触发的事件
onDrag当某个对象被拖动时触发的事件 [活动事件]
onDragDrop一个外部对象被鼠标拖进当前窗口或者帧
onDragEnd当鼠标拖动结束时触发的事件,即鼠标的按钮被释放了
onDragEnter当对象被鼠标拖动的对象进入其容器范围内时触发的事件
onDragLeave当对象被鼠标拖动的对象离开其容器范围内时触发的事件
onDragOver当某被拖动的对象在另一对象容器范围内拖动时触发的事件 [活动事件]
onDragStart当某对象将被拖动时触发的事件
onDrop在一个拖动过程中,释放鼠标键时触发的事件
onLoseCapture当元素失去鼠标移动所形成的选择焦点时触发的事件
onPaste当内容被粘贴时触发的事件
onSelect当文本内容被选择时的事件
onSelectStart当文本内容选择将开始发生时触发的事件
数据绑定
事件描述
onAfterUpdate当数据完成由数据源到对象的传送时触发的事件
onCellChange当数据来源发生变化时
onDataAvailable当数据接收完成时触发事件
onDatasetChanged数据在数据源发生变化时触发的事件
onDatasetComplete当来子数据源的全部有效数据读取完毕时触发的事件
onErrorUpdate当使用 onBeforeUpdate 事件触发取消了数据传送时,代替 onAfterUpdate 事件
onRowEnter当前数据源的数据发生变化并且有新的有效数据时触发的事件
onRowExit当前数据源的数据将要发生变化时触发的事件
onRowsDelete当前数据记录将被删除时触发的事件
onRowsInserted当前数据源将要插入新数据记录时触发的事件
外部事件
事件描述
onAfterPrint当文档被打印后触发的事件
onBeforePrint当文档即将打印时触发的事件
onFilterChange当某个对象的滤镜效果发生变化时触发的事件
onHelp当浏览者按下 F1 或者浏览器的帮助选择时触发的事件
onPropertyChange当对象的属性之一发生变化时触发的事件
onReadyStateChange当对象的初始化属性值发生变化时触发

滚动距离

jsx
window.onscroll:窗口滚动条事件;
window.onresize:窗口大小改变事件;
window.onscroll = window.onresize = function(){}   //同时触发;
距离定位父元素的竖直距离:document.documentElemt.scrollTop;
react获取点击元素的左边距:e.currentTarget.offsetLeft
距离滚动元素的可视范围距离: document.getElementById(index).offsetTop - document.getElementById(index).parentElement.scrollTop
window.onscroll:窗口滚动条事件;
window.onresize:窗口大小改变事件;
window.onscroll = window.onresize = function(){}   //同时触发;
距离定位父元素的竖直距离:document.documentElemt.scrollTop;
react获取点击元素的左边距:e.currentTarget.offsetLeft
距离滚动元素的可视范围距离: document.getElementById(index).offsetTop - document.getElementById(index).parentElement.scrollTop

滚动代码的常用属性

jsx
1.offsetTop 当前对象到其上级层顶部的距离。

2.offsetLeft 当前对象到其上级层左边的距离。

3.offsetWidth
  当前对象的宽度。(包括边线的宽) 与style.width属性的区别在于:

  1)如对象的宽度设定值为百分比宽度,则无论页面变大还是变小,style.width都返回此百分比。

  2)而offsetWidth则返回在不同页面中对象的宽度值而不是百分比值

4.offsetHeight
	当前对象的高度。(包括边线的高)

  1)与style.height属性的区别在于:如对象的宽度设定值为百分比高度,则无论页面变大还是变小,style.height都返回此百分比

  2)而offsetHeight则返回在不同页面中对象的高度值而不是百分比值

5.clientWidth 是对象可见的宽度,不包滚动条等边线,会随窗口的显示大小改变。

6.clientHieght 网页可见区域高(clientHieght+scrollTop > offsetTop => 元素可见)

7.scrollLeft 对象的最左边到对象在当前窗口显示的范围内的左边的距离,即是在出现了横向滚动条的情况下,滚动条拉动的距离。

8.scrollTop 对象的最顶部到对象在当前窗口显示的范围内的顶边的距离,即是在出现了纵向滚动条的情况下,滚动条拉动的距离。

9.window.screenTop 网页正文部分上

10.window.screenLeft 网页正文部分左

11.window.screen.height 屏幕分辨率的高

12.window.screen.width 屏幕分辨率的宽

13.window.screen.availHeight 屏幕可用工作区高度
1.offsetTop 当前对象到其上级层顶部的距离。

2.offsetLeft 当前对象到其上级层左边的距离。

3.offsetWidth
  当前对象的宽度。(包括边线的宽) 与style.width属性的区别在于:

  1)如对象的宽度设定值为百分比宽度,则无论页面变大还是变小,style.width都返回此百分比。

  2)而offsetWidth则返回在不同页面中对象的宽度值而不是百分比值

4.offsetHeight
	当前对象的高度。(包括边线的高)

  1)与style.height属性的区别在于:如对象的宽度设定值为百分比高度,则无论页面变大还是变小,style.height都返回此百分比

  2)而offsetHeight则返回在不同页面中对象的高度值而不是百分比值

5.clientWidth 是对象可见的宽度,不包滚动条等边线,会随窗口的显示大小改变。

6.clientHieght 网页可见区域高(clientHieght+scrollTop > offsetTop => 元素可见)

7.scrollLeft 对象的最左边到对象在当前窗口显示的范围内的左边的距离,即是在出现了横向滚动条的情况下,滚动条拉动的距离。

8.scrollTop 对象的最顶部到对象在当前窗口显示的范围内的顶边的距离,即是在出现了纵向滚动条的情况下,滚动条拉动的距离。

9.window.screenTop 网页正文部分上

10.window.screenLeft 网页正文部分左

11.window.screen.height 屏幕分辨率的高

12.window.screen.width 屏幕分辨率的宽

13.window.screen.availHeight 屏幕可用工作区高度

原生事件处理

jsx
1、HTML事件处理:直接添加到html结构中; ,
2、DOM 0级事件处理:事件绑定,将一个事件处理函数赋值给一个元素的事件处理属性;只能为元素绑定一个事件处理函数;(将事件处理属性赋值为null就可以解绑)
    document.getElementById("btn").onclick = function(){ alert("hello"); } //脚本里面绑定
3、DOM 2级事件处理:事件监听,
    node.addEventListener(eventType,callback,bool=false):
    eventType(事件类型):click,input.....(没有on)
    callback:事件监听函数
    boll:默认值false  冒泡(false)/捕获(true)
    事件监听允许一个元素添加多个事件处理函数;与添加顺序有关;
    事件移除:
    node.removeEventListener(eventType,fnname/arguments.callee);    //arguments.callee当前函数引用
4、IE事件处理:attachEvent(eventType,callback);
   IE事件移除:detachEvent(eventType,callback);
   eventType(事件类型):click,input.....(有on)
1、HTML事件处理:直接添加到html结构中; ,
2、DOM 0级事件处理:事件绑定,将一个事件处理函数赋值给一个元素的事件处理属性;只能为元素绑定一个事件处理函数;(将事件处理属性赋值为null就可以解绑)
    document.getElementById("btn").onclick = function(){ alert("hello"); } //脚本里面绑定
3、DOM 2级事件处理:事件监听,
    node.addEventListener(eventType,callback,bool=false):
    eventType(事件类型):click,input.....(没有on)
    callback:事件监听函数
    boll:默认值false  冒泡(false)/捕获(true)
    事件监听允许一个元素添加多个事件处理函数;与添加顺序有关;
    事件移除:
    node.removeEventListener(eventType,fnname/arguments.callee);    //arguments.callee当前函数引用
4、IE事件处理:attachEvent(eventType,callback);
   IE事件移除:detachEvent(eventType,callback);
   eventType(事件类型):click,input.....(有on)

事件的处理周期(事件流)-事件的传播方式

jsx
在DOM标准中,事件处理周期分三个阶段:
1、事件捕获  从最不具体的事物到最具体的事物,事件沿DOM树向下传播
2、目标触发  运行事件监听函数
3、事件冒泡  从最具体的事物到最不具体的事物,事件沿DOM树向上传播
DOM 0 只能使用事件冒泡,低版本IE只有冒泡;
DOM 2级事件处理:事件监听,
    node.addEventListener(eventType,callback,bool=false):
    eventType(事件类型):click,input.....(没有on)
    callback:事件监听函数a
    boll:默认值false  事件冒泡(false)/ 事件捕获(true)
在DOM标准中,事件处理周期分三个阶段:
1、事件捕获  从最不具体的事物到最具体的事物,事件沿DOM树向下传播
2、目标触发  运行事件监听函数
3、事件冒泡  从最具体的事物到最不具体的事物,事件沿DOM树向上传播
DOM 0 只能使用事件冒泡,低版本IE只有冒泡;
DOM 2级事件处理:事件监听,
    node.addEventListener(eventType,callback,bool=false):
    eventType(事件类型):click,input.....(没有on)
    callback:事件监听函数a
    boll:默认值false  事件冒泡(false)/ 事件捕获(true)

阻止捕获/冒泡

jsx
IE8以下event不属于DOM,属于BOM,使用event时需要写全称;

DOM标准方法阻止事件捕获/冒泡(react可用):event.stopPropagation();
IE中阻止事件捕获/冒泡:event.canceBubble = true;
IE8以下event不属于DOM,属于BOM,使用event时需要写全称;

DOM标准方法阻止事件捕获/冒泡(react可用):event.stopPropagation();
IE中阻止事件捕获/冒泡:event.canceBubble = true;

阻止事件的默认行为

jsx
阻止默认事件(react可用):event.preventDefault();  - event.returnValue = false;  //兼容IE
阻止默认事件(react可用):event.preventDefault();  - event.returnValue = false;  //兼容IE

事件委托(委派)

jsx
将事件处理函数添加给事件目标的祖先元素;
通过事件冒泡的特性,判断事件的源,为目标添加事件;
每个事件处理函数都有一个event对象用于描述事件信息;
在event对象中,有一个target / srcElement属性指向事件目标;
示例:
box.onclick = function (event) {
    event = event || window.event;
    // console.log(event.target); // 标准
    // console.log(event.srcElement); // IE
    var target = event.target || event.srcElement; // 兼容
    if (target.nodeName === 'BUTTON') {
        box.innerHTML += '<button>按钮</button>';
    }
}
将事件处理函数添加给事件目标的祖先元素;
通过事件冒泡的特性,判断事件的源,为目标添加事件;
每个事件处理函数都有一个event对象用于描述事件信息;
在event对象中,有一个target / srcElement属性指向事件目标;
示例:
box.onclick = function (event) {
    event = event || window.event;
    // console.log(event.target); // 标准
    // console.log(event.srcElement); // IE
    var target = event.target || event.srcElement; // 兼容
    if (target.nodeName === 'BUTTON') {
        box.innerHTML += '<button>按钮</button>';
    }
}

鼠标事件属性

jsx
type:事件类型;-contextmenu(鼠标右键点击)
button:鼠标按键编号;
鼠标事件对象属性:
clientX \clientY :根据浏览器可视区域左上角计算坐标;
pageX \ pageY :根据页面左上角计算坐标;
layerX \ layerY :根据页面左上角计算坐标;
offsetX \ offsetY :根据(父)元素左上角计算点击坐标;
screenX \ screenY :根据屏幕左上角计算点击坐标;
type:事件类型;-contextmenu(鼠标右键点击)
button:鼠标按键编号;
鼠标事件对象属性:
clientX \clientY :根据浏览器可视区域左上角计算坐标;
pageX \ pageY :根据页面左上角计算坐标;
layerX \ layerY :根据页面左上角计算坐标;
offsetX \ offsetY :根据(父)元素左上角计算点击坐标;
screenX \ screenY :根据屏幕左上角计算点击坐标;

键盘事件属性

jsx
keydown-按下(返回最后一个输入值)
keycode/which:键盘按键编码(回车13、空格32、ctrl7、数字48-57、字母65-90);
altkey/shiftkey/ctrlkey:返回布尔值,表示是否同时按下;
input:获得用户输入内容;(动态显示输入值,每次变化都可以输出前面的全部)
keydown-按下(返回最后一个输入值)
keycode/which:键盘按键编码(回车13、空格32、ctrl7、数字48-57、字母65-90);
altkey/shiftkey/ctrlkey:返回布尔值,表示是否同时按下;
input:获得用户输入内容;(动态显示输入值,每次变化都可以输出前面的全部)

滚轮事件-mousewheel(谷歌、IE)/ DOMMouseScroll(火狐)

jsx
wheelDelta:判断鼠标滚轮方向,+向上,-向下    ||   / detail:火狐判断鼠标滚轮方向,+向下,-向上;
wheelDelta:判断鼠标滚轮方向,+向上,-向下    ||   / detail:火狐判断鼠标滚轮方向,+向下,-向上;

orientation ​

监听用户手机设备的旋转方向变化;

js
window.addEventListener(
  'orientationchange',
  () => {
    document.body.innerHTML += `<p>屏幕旋转后的角度值:${window.orientation}</p>`
  },
  false,
)
window.addEventListener(
  'orientationchange',
  () => {
    document.body.innerHTML += `<p>屏幕旋转后的角度值:${window.orientation}</p>`
  },
  false,
)

也可以使用媒体查询

弹窗 ​

  1. alert(""); 警告框;
  2. confirm("");确认框,返回值布尔型,确认为 true,取消为 false;
  3. prompt("");可以输入信息,返回值输入的信息,第二个参数默认 value 值;
  4. print();打开打印机

浏览器位置信息 ​

可视距离 client ​

  • 元素可视区域:clientWidth/Height; width/height+padding 不包含边框

  • 元素的边框值:clientLeft/Top;

屏幕可视区域: document.documentElement.clientWidth/Height

元素的实际距离 offset ​

  • 元素的实际宽高:offsetWidth/Height; width/height+padding+border; 包含边框

  • 元素距离 body 的宽高:offsetLeft/Top 如果父元素有定位属性,那么就是离父元素边缘的宽高;

浏览器含滚动条的宽度:window.innerWidth 或者 outerWidth

卷起的距离 scroll ​

元素实际内容的宽高:scrollWidth/height;

元素被卷起的宽高:scrollLeft/Top;

元素.scrollIntoView() 可以滚动到该元素;往括号里面填写对象:{behavior: 'smooth'}可以平滑滚动;

屏幕的宽度 ​

window.screen.width

总结 ​

  • clientWidth ------ padding+content 可视宽
  • offsetWidth ------ content + padding + border 占位宽
  • scrollWidth ------ 页面内容的实际宽度
  • clientTop ------ border
  • offsetTop ------ 相对父元素的之间的距离
  • scrollTop ------ 被卷起的高度
  • document.body.scrollTop || document.documentElement.scrollTop (body)
  • document.documentElement.clientWidth ----- 屏幕宽
js
document.documentElement.scrollTop;  //不兼容其他浏览器
兼容办法:
document.documentElement || document.body.parentNode;   //两种方式;兼容

//老版本的谷歌认为滚动条是body,而其他浏览器认为是html,所以做兼容;
//用来获取页面中被卷起的高度、宽度;
document.documentElement.scrollTop;  //不兼容其他浏览器
兼容办法:
document.documentElement || document.body.parentNode;   //两种方式;兼容

//老版本的谷歌认为滚动条是body,而其他浏览器认为是html,所以做兼容;
//用来获取页面中被卷起的高度、宽度;

image-20240705103055727

getBoundingClientRect

js
元素.getBoundingClientRect()

{
    x: 604.875,
    y: 1312,
    width: 701.625,
    height: 31,
    top: 1312,
    right: 1306.5,
    bottom: 1343,  // 元素bottom到顶部document的值
    left: 604.875
}
元素.getBoundingClientRect()

{
    x: 604.875,
    y: 1312,
    width: 701.625,
    height: 31,
    top: 1312,
    right: 1306.5,
    bottom: 1343,  // 元素bottom到顶部document的值
    left: 604.875
}

注意:top 是距离文档顶部的距离,y 则是距离可视窗口(浏览器屏幕)的顶部距离,如果浏览器滚动,top 值不变,y 值会变 ✅

image-20240705103103956

浏览器滚动事件 ​

  • window.onscroll=function(){} 滚动浏览器;

  • window.scrollTo(x,y || options) 可以传入值也可以传入对象 滚动窗口到指定位置;

    options 支持的属性:

    • top:元素要移动的位置横坐标
    • left:元素要移动的位置纵坐标
    • behavior:元素的运动模式,smooth 平滑滚动;
  • el.scrollIntoView() 滚动到可视区;

    • scrollIntoView(true),如果是 true 则顶端对齐,如果是 false,则底端对齐;
    • scrollIntoView(options),包含以下属性对象:
      • behavior:运动模式,smooth,平滑滚动
      • block:垂直对齐方式,值可以是:start、center、end 或 nearest
      • inline:水平方向对齐方式,值可以是:start、center、end 或 nearest

即插即用的滚动代码

使用的是缓冲运动,算法是:A = A + (B - A) / 2

js
/**
 *@param {Number} A  起始位置
 *@param {Number} B  目标位置
 *@param {Number} rate  缓动速率
 *@param {Function} callback {value,boolean{true: 滚动完成,false: 正在滚动}} 变化位置回调,value变化值;
 */
Math.easeout = function (A, B, rate, callback) {
  if (A == B || typeof A != 'number') {
    return
  }
  B = B || 0
  rate = rate || 2

  var step = function () {
    A = A + (B - A) / rate
    if (A < B + 1) {
      // 当等于B时也不会触发;
      callback(B, true)
      return
    }
    callback(A, false)
    // 如果没有滚动完成则继续调用该函数
    requestAnimationFrame(step)
  }
  step()
}

var doc = document.body.scrollTop ? document.body : document.documentElement
Math.easeout(doc.scrollTop, 0, 4, function (value) {
  //实时更改位置, 位置变化的回调函数;
  doc.scrollTop = value
})
/**
 *@param {Number} A  起始位置
 *@param {Number} B  目标位置
 *@param {Number} rate  缓动速率
 *@param {Function} callback {value,boolean{true: 滚动完成,false: 正在滚动}} 变化位置回调,value变化值;
 */
Math.easeout = function (A, B, rate, callback) {
  if (A == B || typeof A != 'number') {
    return
  }
  B = B || 0
  rate = rate || 2

  var step = function () {
    A = A + (B - A) / rate
    if (A < B + 1) {
      // 当等于B时也不会触发;
      callback(B, true)
      return
    }
    callback(A, false)
    // 如果没有滚动完成则继续调用该函数
    requestAnimationFrame(step)
  }
  step()
}

var doc = document.body.scrollTop ? document.body : document.documentElement
Math.easeout(doc.scrollTop, 0, 4, function (value) {
  //实时更改位置, 位置变化的回调函数;
  doc.scrollTop = value
})

平滑滚动 ​

  1. scroll-behavior: smooth,平滑滚动,给 html 和 body 加,或者给滚动的父元素加;
  2. scroll-snap 属性:

滚动窗口使用的:scroll-snap-type、scroll-padding;

滚动子元素使用的:scroll-snap-align、scroll-snap-stop、scroll-margin;

(1)scroll-snap-type

属性指定能不能去捕捉当前滚动的窗口并让它对齐,以及所执行的方向跟严格程度;

对齐方向属性:

  • x :捕捉 X 轴上的位置
  • y :捕捉 Y 轴上的位置
  • block :捕捉块轴上的位置(逻辑意义上与 y 一样)
  • inline :捕捉内联轴上的位置(逻辑意义上与 x 一样)
  • both :捕捉两个方向上的位置

严格值:

  • none :默认值,Mmmm,啥也不干
  • proximity :一个感性的值,如果元素进入到了容器的捕捉位置范围内,则进行捕捉并滚动,否则就不管,至于这个范围是多少,约莫着 45%的位置吧(手动测的,W3C 没给出具体算法,瞎猜吧,哈哈哈)。
  • mandatory :经常使用的值,强制性的,滚动结束后,一定会强制停在我们指定的地方。

(2)scroll-snap-align 属性指定捕捉窗口要捕捉的子元素位置

  • none :默认值,啥也不干 0.0。
  • start :跟开始位置对齐。
  • end :跟结束位置对齐。
  • center :居中对齐。

(3)scroll-snap-stop 用来控制到达这些位置之后是否被捕获,还是到了指定的位置才被捕获;

  • normal :默认值,滚动的时候,可以忽略捕捉位置。
  • always :滚动的时候,不能忽略捕捉位置,还必须定位到第一个捕捉元素的位置。

(4)scroll-margin 简写属性,跟 margin 一样,可以设置元素跟滚动条之间的外边框大小,可用值四个,scroll-margin-top/bottom/left/right

(5)scroll-padding 跟 scroll-margin 类似;

onresize 自适应布局 ​

js
window.onresize = function () {} // 当页面窗口发生变化时触发;
window.onresize = function () {} // 当页面窗口发生变化时触发;

自适应布局使用;

js
window.onload = window.onresize = function () {
  console.log(111) // 通过判断不同的设备,执行不同的页面,通过navigate来判断;
}
window.onload = window.onresize = function () {
  console.log(111) // 通过判断不同的设备,执行不同的页面,通过navigate来判断;
}

IntersectionObserver 判断元素是否在可视区域 ​

判断元素是否在可视区域

  1. 用法

    js
    let io = new IntersectionObserver(callback[,option])
    // 开始观察
    io.observe(document.querySelector('.example'))
    // 停止观察
    io.unobserve(element)
    // 关闭观察
    io.disconnect()
    
    // 返回所有监听的目标元素集合
    io.takeRecords()
    let io = new IntersectionObserver(callback[,option])
    // 开始观察
    io.observe(document.querySelector('.example'))
    // 停止观察
    io.unobserve(element)
    // 关闭观察
    io.disconnect()
    
    // 返回所有监听的目标元素集合
    io.takeRecords()

    (1)callback 可见性变化时的回调函数,options 是参数配置对象,可选

    (2)如果需要观察多个节点,直接调用多次 observe 即可;

  2. callback 参数用法

    目标元素的可见性变化时就会立即调用该函数

    一般触发两次 callback,一次是目标元素进入视口,一次是完全离开视口

    js
    var io = new IntersectionObserver((entries) => {
      console.log(entries)
    })
    var io = new IntersectionObserver((entries) => {
      console.log(entries)
    })

    (1)监听一个

    js
    var io = new IntersectionObserver((entries) => {
      let item = entries[0] // 是一个数组, 只有一个元素
    
      // 添加最后一个元素
      if (item.isIntersecting) {
        console.log(滚动到底部了, 可以请求数据了)
      }
    }).observe(document.querySelector('.reference')) // 参照元素
    var io = new IntersectionObserver((entries) => {
      let item = entries[0] // 是一个数组, 只有一个元素
    
      // 添加最后一个元素
      if (item.isIntersecting) {
        console.log(滚动到底部了, 可以请求数据了)
      }
    }).observe(document.querySelector('.reference')) // 参照元素
  3. IntersectionObserverEntry对象属性

    • boundingClientRect 目标元素的矩形信息
    • intersectionRatio 相交区域和目标元素的比例值 intersectionRect/boundingClientRect 不可见时小于等于 0
    • intersectionRect 目标元素和视窗(根)相交的矩形信息 可以称为相交区域
    • isIntersecting 目标元素当前是否可见 Boolean 值 可见为 true
    • rootBounds 根元素的矩形信息,没有指定根元素就是当前视窗的矩形信息
    • target 观察的目标元素
    • time 返回一个记录从 IntersectionObserver 的时间到交叉被触发的时间的时间戳

    intersectionRatio和 isIntersecting 用来判断元素是否在可视区域

  4. options 对象的配置

    (1)root:null 观察根元素,默认浏览器视口,指定元素的时候用于观察元素必须是指定元素的子元素

    (2)threshold:[0,0.5,1] 一个数组,触发 callback 的时机

    (3)rootMargin: '30px 100px 20px'; 用来扩大或者缩小视察的大小,使用 css 的定义方法

  5. 兼容性

官方 polyfill: https://github.com/w3c/IntersectionObserver/tree/master/polyfill

MutationObserver 监视 DOM 变动 ​

作用 ​

  • 监视 dom 发生变动时,MutationObserver 将收到通知并触发事先设定好的回调函数;
  • MutationObserver 是异步触发的,为了避免 dom 频繁变动导致回调函数被频繁调用,造成浏览器卡顿;

MutationObserver ​

js
var observer = new MutationObserver(callback);
callback接收两个参数,第一个参数包含了所有mutationRecord对象的数组,第二个是MutationObserver实例本身;

var observer = new MutationObserver(function(mutations, observer){
    mutations.forEach(function(mutation){
        console.log(mutation, 'mutation')
    })
})
var observer = new MutationObserver(callback);
callback接收两个参数,第一个参数包含了所有mutationRecord对象的数组,第二个是MutationObserver实例本身;

var observer = new MutationObserver(function(mutations, observer){
    mutations.forEach(function(mutation){
        console.log(mutation, 'mutation')
    })
})

实例方法 ​

observe

  • 第一个参数:所要观察的 dom 节点

  • 第二个参数:一个配置对象,指定所要观察的特定变动

    • childList:子节点的变动(新增、删除或更改)
    • attributes:属性的变动;
    • characterData:节点内容或节点文本的变动;
    • subtree:是否监听该节点的所有后代节点
    • attributeOldValue:观察 attributes 变动时,是否需要记录变动前的值;
    • characterDataOldValue:观察 characterData 时,是否需要记录变动前的值;
    • attributeFilter:数组,表示需要观察特定的属性(如:['class', 'src'])
js
var article = document.querySelector('article')
var options = {
  childList: true,
  attributes: true,
}
observer.observe(article, options)
var article = document.querySelector('article')
var options = {
  childList: true,
  attributes: true,
}
observer.observe(article, options)

注意:childList、attributes、characterData 三者必须选其一或多个,否则报错;

对节点添加了 observe 就像添加了 addEventListener 一样,当添加不同的 options 时,可以触发多次;

  • disconnect:用来停止观察,调用该方法后,dom 再发生变动,也不会触发观察器;

  • takeRecords:用来清除变动记录,即不再处理未处理的变动,该方法返回变动记录的数组;

MutationRecord ​

dom 每次发生变化时,就会生成一条变动记录(MutationRecord 实例),该实例包含了与变动相关的所有信息,mutation observer 处理的就是一个个 mutationrecord 实例所组成的数组;

mutationRecord 对象包含了 dom 的相关信息:

  • type:观察的变动类型(attribute、characterData 或者 childList)。
  • target:发生变动的 DOM 节点。
  • addedNodes:新增的 DOM 节点。
  • removedNodes:删除的 DOM 节点。
  • previousSibling:前一个同级节点,如果没有则返回 null。
  • nextSibling:下一个同级节点,如果没有则返回 null。
  • attributeName:发生变动的属性。如果设置了 attributeFilter,则只返回预先指定的属性。
  • oldValue:变动前的值。这个属性只对 attribute 和 characterData 变动有效,如果发生 childList 变动,则返回 null。

DocumentFragment ​

  1. nodeType 值为 11;
  2. documentFragment 是一个文档片段,一种'轻量级节点';
  3. 通常作为仓库使用,不存在 DOM 树上,是一种游离态,主要是优化页面性能;
  4. 用途:当使用 js 创建很多 dom 节点时,在加入节点到 dom 树上时,节点需要一个个渲染,这样节点数较多时会影响浏览器的渲染效率,这个时候我们将创建的节点都放在 documentFragment 这样的节点上,然后把 documentFragment 加入到 DOM,只需要完成一次渲染就可以达到之前很多次渲染的效果;
js
var ul = document.createElement('ul')
var flag = document.createDocumentFragment()
for (var i = 1; i < 101; i++) {
  var li = document.createElement('li')
  var liText = document.createTextNode(i)
  li.appendChild(liText)
  flag.appendChild(li)
}
ul.appendChild(flag)
document.body.appendChild(ul)
var ul = document.createElement('ul')
var flag = document.createDocumentFragment()
for (var i = 1; i < 101; i++) {
  var li = document.createElement('li')
  var liText = document.createTextNode(i)
  li.appendChild(liText)
  flag.appendChild(li)
}
ul.appendChild(flag)
document.body.appendChild(ul)

requestAnimationFrame ​

用来调节重新渲染,大副提高网页性能;

  1. 类似定时器,与 setTimeout 相比,它的最大优势是由系统来决定回调函数的执行时机,不需要设置时间间隔,

  2. 刷新频率:如果屏幕刷新率是 60HZ,那么回调函数就每 16.7ms 被执行一次,如果是 75hz,就是 1000/75=13.3ms 执行一次,它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次, 这样不会引起丢帧现象, 也不会导致动画出现卡顿的问题;

  3. requestAnimationFrame 的基本思想是 让页面重绘的频率和刷新频率保持同步;

  4. 优势

(1)cpu 节能:如果使用 setTimeout 实现的动画,即使切换了窗口,后台仍在执行动画,而 requestAnimationFrame 则不会执行,当出现在视口内,则开始执行;

(2)函数节流: 在高频率事件(resize,scroll 等)中,为了防止在一个刷新间隔内发生多次函数执行,使用 requestAnimationFrame 可保证每个刷新间隔内,函数只被执行一次,这样既能保证流畅性,也能更好的节省函数执行的开销。一个刷新间隔内函数执行多次时没有意义的,因为显示器每 16.7ms 刷新一次,多次绘制并不会在屏幕上体现出来。

  1. 执行 requestAnimationFrame会返回一个定时器编号,传递给 cancelAnimationFrame用于取消这个函数;编号一般是 1;
js
let count = 0;
function requestAnimation(){
    if(count < 100){   // 作一下判断
        count++
        console.log(count)
        // 需要在函数里面调用该事件;
        requestAnimationFrame(requestAnimation);
    }
}
requestAnimationFrame(requestAnimation)
 // 页面打开加载这个函数
cancelAnimationFrame(id)   取消requestAnimationFrame
let count = 0;
function requestAnimation(){
    if(count < 100){   // 作一下判断
        count++
        console.log(count)
        // 需要在函数里面调用该事件;
        requestAnimationFrame(requestAnimation);
    }
}
requestAnimationFrame(requestAnimation)
 // 页面打开加载这个函数
cancelAnimationFrame(id)   取消requestAnimationFrame

requestIdleCallback ​

另一个用来调节重新渲染的函数,将任务放置后台处理

将在浏览器的空闲时段内调用函数排队,使开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件

当一帧的末尾有空闲时间,才会执行回调函数;

js
var handle = window.requestIdleCallback(callback[,options])
// 结束回调
window.cancelIdleCallback(handle)
var handle = window.requestIdleCallback(callback[,options])
// 结束回调
window.cancelIdleCallback(handle)

options 参数:timeout:指定毫秒数,将在指定的毫秒数执行函数;

参考地址: