JavaScript基础--BOM部分01--李南江

目录

一、BOM概述

二、BOM对象

1.navigator

2.location

3.history

三、获取元素的宽高

1.getComputedStyle

2.currentStyle

3.style

4.offsetWidth和offsetHeight

四、javascript 三大家族

1.offset 相关属性

2.client 相关属性

3.scroll 相关属性

五、获取网页的宽高

六、获取网页的滚动距离

七、函数防抖

八、函数节流


一、BOM概述

  • 1.什么是BOM?
    • DOM 就是一套操作HTML标签的API(接口/方法/属性)
    • BOM 就是一套操作浏览器的API(接口/方法/属性)
  • 2.BOM中常见的对象
    • window:代表整个浏览器窗口
      • 注意点:window是BOM中的一个对象, 并且是一个顶级的对象(全局)
    • navigator:代表当前浏览器的信息, 通过 navigator 我们就能判断用户当前是什么浏览器(浏览器类型
    • location:代表浏览器地址栏的信息, 通过 location 我们就能设置或者获取当前地址信息
    • history:代表浏览器的历史信息, 通过 history 来实现 刷新 / 上一步 / 下一步
      • 注意点:出于隐私考虑, 我们并不能拿到用户所有的历史记录, 只能拿到当前的历史记录
    • screen:代表用户的屏幕信息

二、BOM对象

1.navigator

  • navigator:代表当前浏览器的信息;可以通过 navigator 判断用户当前使用的是什么浏览器 
        // console.log(window.navigator);   // userAgent:  ... Chrome ...

        // 1.获取浏览器信息中userAgent信息
        let agent = window.navigator["userAgent"];
        console.log(agent);
        // /chrome/i 正则表达式,i:不区分大小写
        // console.log(/chrome/i.test(agent));

        // 2.利用正则表达式,判断浏览器的类型
        if(/chrome/i.test(agent)){
            alert("当前是谷歌浏览器");
        }
        else if(/firefox/i.test(agent)){
            alert("当前是火狐浏览器");
        }
        else if(/msie/i.test(agent)) {
            alert("当前是低级IE浏览器");
        }
        else if("ActiveXObject" in window){
            alert("当前是高级IE浏览器");
        }

2.location 

  • location:代表浏览器地址栏的信息;通过 location 我们就能 设置或者获取当前地址信息
    <button id="btn1">获取</button>
    <button id="btn2">设置</button>
    <button id="btn3">刷新</button>
    <button id="btn4">强制刷新</button>

    <script>
        let oBtn1 = document.querySelector("#btn1");
        let oBtn2 = document.querySelector("#btn2");
        let oBtn3 = document.querySelector("#btn3");
        let oBtn4 = document.querySelector("#btn4");

        // console.log(window.location);

        oBtn1.onclick = function () {
            // 获取当前url地址
            console.log(window.location.href);
        };
        oBtn2.onclick = function () {
            // 设置url地址
            window.location.href = "http://it666.com";
        };
        oBtn3.onclick = function () {
            // 刷新
            window.location.reload();
        };
        oBtn4.onclick = function () {
            // 强制刷新
            window.location.reload(true);
        }
    </script>

3.history 

  • history:代表浏览器的历史信息, 通过 history 来实现 刷新 / 前进 / 后退
    • window.history.go(0)                # 刷新
    • window.history.go(1)                # 前进
    • window.history.forward()
    • window.history.go(-1)               # 后退
    • window.history.back()
  • 注意点:出于隐私考虑, 我们并不能拿到用户所有的历史记录, 只能拿到当前的历史记录
    <h1>我是第一个界面</h1>
    <button id="btn1">前进</button>
    <button id="btn2">刷新</button>
    <a href="04-BOM对象-history02.html">新的界面222</a>

    <script>

        let oBtn1 = document.querySelector("#btn1");
        let oBtn2 = document.querySelector("#btn2");

        oBtn1.onclick = function () {
            // 前进
            // window.history.forward();
            window.history.go(1);
        };
        // 注意点:
        // 只有当前访问过其它的界面, 才能通过forward/go方法前进
        // 如果给go方法传递1, 就代表前进1个界面, 传递2就代表进行2个界面

        oBtn2.onclick = function () {
            // 刷新
            window.history.go(0);
        }

    </script>
    <h2>我是第2222个界面</h2>
    <button id="btn1">后退</button>

    <script>
        let oBtn1 = document.querySelector("#btn1");
        oBtn1.onclick = function(){
            // 后退
            // window.history.back();
            window.history.go(-1);
        };
        // 注意点:
        // 只有当前访问过其它的界面, back/go方法后退
        // 如果给go方法传递-1, 就代表后退1个界面, 传递-2就代表后退2个界面
    </script>

三、获取元素的宽高

        <style>
        *{
            margin: 0;
            padding: 0;
        }
        div{
            width: 100px;
            height: 100px;
            padding: 50px;
            border: 50px solid #000;
            background: red;
            background-clip: content-box;
        }
    </style>

    <div id="box"></div>

1.getComputedStyle

  • 1.1 获取的宽高不包括 边框和内边距
  • 1.2 既可以获取行内(js)设置的宽高,也可以获取CSS设置的宽高
  • 1.3 只支持获取, 不支持设置
  • 1.4 只支持IE9及以上浏览器
        let oDiv = document.querySelector("#box");
        // oDiv.style.width = "200px";
        // oDiv.style.height = "200px";
        // 通过getComputedStyle获取宽高,既可以获取到js设置的宽高,也可以获取到CSS设置的宽高
        let style = getComputedStyle(oDiv);
        // 报错:getComputedStyle 不支持设置宽高
        // style.width = "166px";
        // style.height = "166px";
        console.log(style.width);
        console.log(style.height);

2.currentStyle

  • 2.1 获取的宽高不包括 边框和内边距
  • 2.2 既可以获取行内设置的宽高,也可以获取CSS设置的宽高
  • 2.3 只支持获取, 不支持设置
  • 2.4 只支持IE9以下浏览器
        let oDiv = document.getElementById("box");
        // oDiv.style.width = "166px";
        // oDiv.style.height = "166px";
        let style = oDiv.currentStyle;
        // style.width = "166px";
        // style.height = "166px";
        // console.log(style);
        console.log(style.width);
        console.log(style.height);

3.style

  • 3.1 获取的宽高不包括 边框和内边距
  • 3.2 只能获取行内设置的宽高,不能获取CSS设置的宽高
  • 3.3 可以获取,也可以设置
  • 3.4 高级低级浏览器都支持
        let oDiv = document.getElementById("box");
        // style:只能获取js设置的宽高,不能获取CSS设置的宽高!
        oDiv.style.width = "166px";
        oDiv.style.height = "166px";
        console.log(oDiv.style.width);
        console.log(oDiv.style.height);

4.offsetWidth和offsetHeight

  • 4.1 获取的宽高包含 边框 + 内边距 + 元素宽高
  • 4.2 既可以获取行内设置的宽高,也可以获取CSS设置的宽高
  • 4.3 只支持获取, 不支持设置
  • 4.4 高级低级浏览器都支持
        var oDiv = document.getElementById("box");
        oDiv.style.width = "166px";
        oDiv.style.height = "166px";
        // offsetWidth和offsetHeight:只支持获取, 不支持设置
        // oDiv.offsetWidth = "166px";
        // oDiv.offsetHeight = "166px";
        console.log(oDiv.offsetWidth);
        console.log(oDiv.offsetHeight);

总结:

  • 1.getComputedStyle/currentStyle/style
    • 获取的宽高不包括 边框和内边距
  • 2.offsetWidth/offsetHeight
    • 获取的宽高包括 边框和内边距
  • 3.getComputedStyle/currentStyle/offsetXXX
    • 只支持获取, 不支持设置
  • 4.style
    • 可以获取, 也可以设置
  • 5.getComputedStyle/currentStyle/offsetXXX
    • 既可以获取行内,也可以获取外链和内联样式
  • 6.style
    • 只能获取行内样式

四、javascript 三大家族

1.offset 相关属性

(1).offsetLeft 和 offsetTop 作用

  • offsetLeft offsetTop:获取元素到第一个定位祖先元素之间的偏移位
  • 如果没有祖先元素是定位的, 那么就是获取到body的偏移位
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .father{
            width: 200px;
            height: 200px;
            margin-top: 100px;
            margin-left: 100px;
            background: blue;
            overflow: hidden;
            position: relative;
        }
        .son{
            width: 100px;
            height: 100px;
            margin-top: 100px;
            margin-left: 100px;
            background: red;
        }
    </style>

    <div class="father">
        <div class="son"></div>
    </div>

    <script>
        let oSDiv = document.querySelector(".son");
        oSDiv.onclick = function () {
            // 获取元素到第一个定位祖先元素之间的偏移位
            console.log(oSDiv.offsetLeft);
            console.log(oSDiv.offsetTop);
        }
        }
    </script>

(2).offsetParent 作用

  • offsetParent:获取元素的第一个定位的祖先元素
  • 如果没有祖先元素是定位的, 那么就是获取到的就是body
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .grand-father{
            width: 300px;
            height: 300px;
            margin-top: 100px;
            margin-left: 100px;
            background: deeppink;
            overflow: hidden;
            position: relative;
        }
        .father{
            width: 200px;
            height: 200px;
            margin-top: 100px;
            margin-left: 100px;
            background: blue;
            overflow: hidden;
            position: relative;
        }
        .son{
            width: 100px;
            height: 100px;
            margin-top: 100px;
            margin-left: 100px;
            background: red;
        }
    </style>

   <div class="grand-father">
        <div class="father">
            <div class="son"></div>
        </div>
    </div>

    <script>
        let oSDiv = document.querySelector(".son");
        oSDiv.onclick = function () {
            // 获取第一个定位的祖先元素
            console.log(oSDiv.offsetParent);
        }
    </script>

2.client 相关属性

  • offset 相关属性
    • offsetWidth = 宽度 + 内边距 + 边框
    • offsetHeight = 高度 + 内边距 + 边框
  • client 相关属性
    • clientWidth   =  宽度 + 内边距
    • clientHeight  =  高度 + 内边距
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        div {
            width: 100px;
            height: 100px;
            padding: 30px;
            border: 60px solid #000;
            background: red;
            background-clip: content-box;
        }
    </style>

    <div id="box"></div>
        let oDiv = document.querySelector("#box");
        console.log(oDiv.clientHeight);   // 160 = 100 + 30*2
        console.log(oDiv.clientWidth);    // 160 = 100 + 30*2
  • offsetLeft / offsetTop:距离 第一个定位祖先元素(如果没有即为body)的偏移位
  • clientLeft clientTop:左边框 和 顶部边框
        console.log(oDiv.clientLeft);    // 60
        console.log(oDiv.clientTop);     // 60

3.scroll 相关属性

(1).scrollWidth 与 scrollHeight  作用

1.1 内容没有超出元素范围时

  • scrollWidth   =  元素宽度 + 内边距宽度 == clientWidth
  • scrollHeight  =  元素高度 + 内边距的高度 == clientHeight
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    
        div {
            width: 100px;
            height: 100px;
            padding: 30px;
            border: 60px solid #000;
            background: red;
            background-clip: content-box;
            color: deepskyblue;
            
            overflow: auto;
        }
    </style>

    <div id="box">
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
        我是内容<br />
    </div>
        let oDiv = document.querySelector("div");
        console.log(oDiv.scrollWidth);    // 160
        console.log(oDiv.scrollHeight);   // 160

1.2 内容超出元素范围时

  • scrollWidth   =  元素宽度 + 内边距宽度 + 超出的宽度
  • scrollHeight  =  元素高度 + 内边距的高度 + 超出的高度
        let oDiv = document.querySelector("div");
        console.log(oDiv.scrollWidth);    
        console.log(oDiv.scrollHeight);

(2).scrollTop 和 scrollLeft 作用

  • scrollTop:超出元素内边距顶部的距离
  • scrollLeft:超出元素内边距左边的距离
        let oDiv = document.querySelector("div");
        oDiv.onscroll = function () {
            console.log(oDiv.scrollTop);   
        }

    

    

五、获取网页的宽高

(1).只能在IE9以及IE9以上的浏览器中才能获取

  • innerWidth / innerHeight
        console.log(window.innerWidth);
        console.log(window.innerHeight);

(2).可以用于在IE9以下的浏览器的标准模式中获取

        // documentElement:整个html文件内容
        // console.log(document.documentElement);
  • 浏览器在渲染网页的时候有两种模式"标准模式"/"混杂模式/怪异模式"
  • 默认情况下都是以标准模式来进行渲染的(CSS1Compat),如果网页没有书写文档声明, 那么就会按照"混杂模式/怪异模式"来进行渲染的(BackCompat)
  • 2.1 在标准模式中,获取可视区域的宽高
    • document.documentElement.clientWidth
    • document.documentElement.clientHeight
        console.log(document.compatMode);       // CSS1Compat
        console.log(document.documentElement.clientWidth);
        console.log(document.documentElement.clientHeight);
  • 2.2 在混杂模式中,获取可视区域的宽高
    • document.body.clientWidth

    • document.body.clientHeight

        console.log(document.compatMode);       // BackCompat
        console.log(document.body.clientWidth);
        console.log(document.body.clientHeight);

兼容性写法:

        let { width, height } = getScreen();

        console.log(width);
        console.log(height);

        // 获取网页的宽高
        function getScreen() {
            let width, height;
            if (window.innerWidth) {
                width = window.innerWidth;
                height = window.innerHeight;
            } else if (document.compatMode === "BackCompat") {
                width = document.body.clientWidth;
                height = document.body.clientHeight;
            } else {
                width = document.documentElement.clientWidth;
                height = document.documentElement.clientHeight;
            }
            return {
                width: width,
                height: height
            }
        }

六、获取网页的滚动距离

  • IE9以及IE9以上的浏览器
    • window.pageXOffset / window.pageYOffset 

  • 标准模式下浏览器

    • document.documentElement.scrollTop

    • document.documentElement.scrollLeft

  • 混杂(怪异)模式下浏览器

    • document.body.scrollTop

    • document.body.scrollLeft

    <style>
        * {
            margin: 0;
            padding: 0;
        }

        p {
            line-height: 50px;
            width: 200%;
        }
    </style>

    <p>我是正文1</p>
        ...
    <p>我是正文2</p>
    <script>
        window.onscroll = function () {
            // 1.IE9以及IE9以上的浏览器
            // console.log(window.pageXOffset);
            // console.log(window.pageYOffset);

            // 2.标准模式下浏览器
            // console.log(document.documentElement.scrollTop);
            // console.log(document.documentElement.scrollLeft);

            // 3.混杂(怪异)模式下浏览器
            // console.log(document.body.scrollTop);
            // console.log(document.body.scrollLeft);
        }
    </script>

兼容性写法:

            let { x, y } = getPageScroll();
            console.log(x, y);

            // 获取网页的滚动距离
            function getPageScroll() {
                let x, y;
                if (window.pageXOffset) {
                    x = window.pageXOffset;
                    y = window.pageYOffset;
                } else if (document.compatMode === "BackCompat") {
                    x = document.body.scrollLeft;
                    y = document.body.scrollTop;
                } else {
                    x = document.documentElement.scrollLeft;
                    y = document.documentElement.scrollTop;
                }
                return {
                    x: x,
                    y: y
                }
            }

七、函数防抖

(1).什么是函数防抖  [ debounce ] 

  • 函数防抖:是优化高频率执行js代码的一种手段
  • 可以让被调用的函数,在一次连续的高频操作过程中,只被调用一次

(2).函数防抖作用

  • 减少代码执行次数, 提升网页性能

(3).函数防抖应用场景

  • oninput / onmousemove / onscroll / onresize 等事件
    <input type="text">

    <script>
        let oInput = document.querySelector("input");

        let timerId = null;
        // 实时监听用户输入
        oInput.oninput = function () {
            // 默认每输入一个字符便发送一次网络请求,这样很消耗性能
            // console.log(this.value);
            // console.log("发送网络请求");

            // 如果是连续输入的(假设不超过1s),就只发送一次网络请求,提高性能
            // && 当timerId存在(定时器已经开启),才会执行clearTimeout(timerId)(关闭定时器)
            timerId && clearTimeout(timerId);
            // 等待1000毫秒=1秒后,再执行函数
            timerId = setTimeout(function () {
                console.log("发送网络请求");
            }, 1000);
        }
    </script>

(4).封装防抖函数

  • 将防抖函数,单独封装到一个js文件中
(function (){
    // 防抖函数
    function debounce(fn, delay) {   
        let timerId = null;
        return function () {
            // 保存当前函数的this
            let self = this;
            // arguments:所有参数
            // 如果有event,就是保存保存当前函数的event事件对象
            let args = arguments;
            timerId && clearTimeout(timerId);
            timerId = setTimeout(function () {
                // console.log("发送网络请求");
                // fn();
                // 修改fn中的this与event
                fn.apply(self, args);
            }, delay || 1000);
        }
    }
    window.debounce = debounce;
})();
  • 调用防抖函数
    <input type="text">
    
    <script src="js/tools.js"></script>

    <script>    
    let oInput = document.querySelector("input");

    function test(event) {
        // console.log("发送网络请求");
        console.log(this);
        console.log(event);
    }
    
    // 调用防抖函数
    oInput.oninput = debounce(test);
    // oInput.oninput = debounce(test, 5000);
    </script>

(5).防抖函数-练习

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>防抖函数-练习</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        div{
            width: 200px;
            height: 200px;
            background: red;
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
        }
    </style>
</head>
<body>
    <div></div>

    <script src="js/tools.js"></script>

    <script>
        /* 需求: 让div的宽高永远是可视区域宽高的一半 */
        let oDiv = document.querySelector("div");
        function resetSize(){
            let { width, height } = getScreen();
            oDiv.style.width = width / 2 + "px";
            oDiv.style.height = height / 2 + "px";
        }

        // // 监听可视区域尺寸变化事件
        // window.onresize = function(){
        //     resetSize();
        //     console.log("尺寸的变化");
        // }
        // 只要可视区域(浏览器)尺寸发生变化,就会调用resetSize函数,尺寸频繁发生变动,就会频繁调用resetSize函数,进而产生性能问题,此时便可利用防抖函数进行优化代码

        // 调用封装好的防抖函数
        window.onresize = debounce(resetSize, 1000)
    </script>
</body>
</html>

八、函数节流

(1).什么是函数节流   [ throttle ] 

  • 函数节流也是优化高频率执行js代码的一种手段
  • 可以减少高频调用函数的执行次数

(2).函数节流作用

  • 减少代码执行次数, 提升网页性能

(3).函数节流应用场景

  • oninput / onmousemove / onscroll / onresize 等事件

(4).函数节流和函数防抖区别

  • 函数节流减少连续的高频操作函数执行次数     (例如连续调用10次, 可能只执行3 - 4次)
  • 函数防抖是让连续的高频操作时函数只执行一次  (例如连续调用10次, 但是只会执行1次)
    let timerId = null;
    let flag = true;
    window.onresize = function () {
        if (!flag) {  
            return;
        }
        flag = false;
        timerId && clearTimeout(timerId);
        timerId = setTimeout(function () {
            flag = true;
            resetSize();
            // console.log("尺寸的变化");
        }, 500);
    }

(5).封装节流函数

(function (){
    // 节流函数
    function throttle(fn, delay) {
        let flag = true;
        let timerId = null;
        return function () {
            if (!flag) {
                return;
            }
            flag = false;
            let self = this;
            let args = arguments;
            timerId && clearTimeout(timerId);
            timerId = setTimeout(function () {
                flag = true;
                fn.apply(self, args);
            }, delay || 1000);
        }
    }
    window.throttle = throttle;
})();

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值