前端 - JS BOM

JS文档

BOM简介

JS通过浏览器对象模型 (Browser Object Model, DOM) 来操作浏览器,DOM对象参考下表:

BOM对象 描述
Window 整个浏览器窗口,同时window也是网页中的全局对象
Navigator 代表当前浏览器的信息,通过该对象可以来识别不同的浏览器
Location 当前浏览器的地址栏,可获取地址栏信息,或操作浏览器跳转界面
History 浏览器历史记录,由于隐私原因,只能操作浏览器向前或者向后翻页,且该操作只在当次访问时有效
Screen 代表用户屏幕信息,通过该对象获取到用户显示器的相关信息

除了window外的BOM对象在浏览器中都是作为window对象的属性来保存的,所以可以作为全局对象直接使用。

Navigator

Navigator代表当前浏览器的信息,由于历史原因,其大部分属性已经不能用来识别浏览器,一般使用userAgent来判断浏览器的信息:

console.log(navigator.userAgent);

Safari:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Safari/605.1.15

Chrome:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36

History

操作浏览器向前/向后翻页。属性和方法如下:

属性/方法 描述
length 当前访问链接的数量
back() 回退到上一个界面,等同于浏览器回退按钮
forward() 跳转到下一个界面,等同于浏览器前进按钮
go() 跳转到指定页面,整数作为参数,history.go(1)等价于history.forward()history.go(-1)等价于history.back()

Location

直接打印location可以获取地址栏信息,如果直接修改,则会跳转到对应页面,并生成相应的历史记录。

location='https://www.baidu.com';

Location对象属性:

属性 描述
hash 设置或返回从井号(#)开始的URL
host 设置或返回主机名和当前URL的端口号
hostname 设置或返回当前URL的主机名
href 设置或返回完整的URL
pathname 设置或返回当前URL的路径部分
port 设置或返回当前URL的端口号
protocol 设置或返回当前URL的协议
search 设置或返回从问号(?)开始的URL,查询部分

Location对象方法:

方法 描述
assign() 跳转到其他界面,和直接修改location一样
reload() 重新加载页面,和刷新按钮一样,如果传入true作为参数,则会强制清空缓存刷新界面
replace() 使用一个新页面替换当前页面,调用后也会跳转,但不会生成历史记录,不能使用回退按钮回退

Window

webStorage

浏览器通过window.localStoragewindow.sessionStorage来实现本地存储,存储内容大小一般支持5MB左右。二者API通用:

  • setItem('key', 'value'):添加/更新存储
  • getItem('key'):根据键名获取存储
  • removeItem('key'):根据键名删除存储
  • clear():清空存储中的数据

注意

  1. SessionStorage存储的内容会随着浏览器关闭而消失,但LocalStorage的内存则不会
  2. getItem('key')如果获取失败会返回null
  3. JSON.parse(null)的结果仍然是null

window.localStorage为例:

let p = {name: 'Lee', age: 20};
function saveData() {
    localStorage.setItem('hello', 'Hello storage!');
    localStorage.setItem('person', JSON.stringify(p));
}
function readData() {
    console.log(localStorage.getItem('hello'));
    const p = localStorage.getItem('person')
    console.log(JSON.parse(p));
}
function delData() {
    localStorage.removeItem('person');
}
function delAllData() {
    localStorage.clear();
}

定时调用

Window对象的setInterval()方法:

  • 定时调用,将一个函数每隔一段时间执行一次
  • 参数:
    • 回调函数
    • 每次调用间隔时间,单位毫秒
  • 返回值:
    • Number类型数据,用来作为定时器唯一标识
    • 通过clearInterval()方法,关闭对应定时器

倒数应用:

var count = document.getElementById('count');

// 倒计时
var num = 10;
var timer = setInterval(function(){
    count.innerHTML = num;
    num--;
	
    // 倒数到0时,结束计时器
    if(num < 0) {
        clearInterval(timer);
    }
}, 1000);

延时调用

延时调用方法setTimeout()与定时器用法类似,间隔一定时间之后执行指定的回调函数一次。使用clearTimeout()方法来关闭一个延时调用。

定时器动画应用

控制标签的动画,可以控制标签移动、标签大小:

var box = document.getElementById('box');

/* 控制目标标签移动, 以及大小等变化 */
function move(obj, target, speed, attr) {
    clearInterval(obj.timer);  // 关闭上一个定时器
    
    // 根据标签当前位置判断速度的正负值
    speed = Math.abs(speed);
    var currPos = parseInt(getComputedStyle(obj)[attr]);
    if(currPos > target) {
        speed = -speed;
    }

    // 新建定时器
    obj.timer = setInterval(function() {
        var oldPos = parseInt(getComputedStyle(obj)[attr]);
        var newPos = oldPos + speed;

        if((speed > 0 && newPos > target) || (speed < 0 && newPos < target)) {
            newPos = target;
        }

        obj.style[attr] = newPos + 'px';
		
        // 到达终点后关闭定时器
        if (newPos == target) {
            clearInterval(obj.timer);
        }
    }, 30);
}

轮播图

<div id="outer">
    <ul id="img-list">
        <li><img src="images/1.jpg" alt="1"></li>
        <li><img src="images/2.jpeg" alt=""></li>
        <li><img src="images/3.jpeg" alt=""></li>
        <li><img src="images/4.jpeg" alt=""></li>
        <li><img src="images/5.jpeg" alt=""></li>
    </ul>

    <div id="nav">
        <a class="nav-index" href="javascript:;"></a>
        <a class="nav-index" href="javascript:;"></a>
        <a class="nav-index" href="javascript:;"></a>
        <a class="nav-index" href="javascript:;"></a>
        <a class="nav-index" href="javascript:;"></a>
    </div> 
</div>
* {
    margin: 0;
    padding: 0;
}

li {
    list-style: none;
}

#outer {
    position: relative;
    width: 200px;
    height: 200px;
    padding: 10px;
    background-color: skyblue;
    margin: 200px auto;   
    overflow: hidden;
}

#img-list {
    position: absolute;
    width: 1050px;
}

#img-list img {
    float: left;
    width: 200px;
    height: 200px;
    margin-right: 10px;
}

#nav {
    position: absolute;
    bottom: 20px;
    left: 60px;
}

#nav a {
    float: left;
    display: block;
    width: 10px;
    height: 10px;
    margin: 0 5px;
    background-color: orange;
}

#nav a:hover {
    background-color: orangered;
}
var navA = document.getElementsByClassName('nav-index');
var imgList = document.getElementById('img-list');

var imgIndex = 0;  // 全局索引
setA();
autoChange();

/* 点击a标签切换到指定的图片 */
for(var i = 0; i < navA.length; i++) {
    navA[i].index = i;

    navA[i].onclick = function() {
        imgIndex = this.index;  // 修改全局索引

        // imgList.style.left = - imgIndex * 210 + 10 + 'px';  // 切换图片
        move(imgList, -imgIndex * 210 + 10, 10, 'left');

        setA();
    };
}

/* 根据当前的全局索引imgIndex, 设置nav中a标签的颜色 */
function setA() {
    for(var i = 0; i < navA.length; i++) {
        if(i == imgIndex) {
            navA[i].style.backgroundColor = 'orangered';
        }
        else {
            navA[i].style.backgroundColor = '';
        }
    }
}

/* 定时切换图片 */
function autoChange() {
    setInterval(function() {
        imgIndex = (imgIndex + 1) % navA.length;  // 修改全局索引

        move(imgList, -imgIndex * 210 + 10, 10, 'left');

        setA();
    }, 3000);
}

class的操作

通过style属性来修改元素的样式,每修改一个样式,浏览器就要重新渲染一次页面。这样执行性能较差,而且这种形式要修改多个样式时也不方便。

  • 使用一行代码修改多个样式,可以直接修改class属性:
.box1 {
    width: 100px;
    height: 100px;
    background-color: skyblue;
}

.box2 {
    /* width: 200px; */
    height: 200px;
    background-color: orangered;
}
var box = document.getElementById('box');
box.className += ' box2';  // 注意空格

class的切换功能

<button id="btn">Change</button>
<div id="outer" class="box1"></div>
.box1 {
    width: 100px;
    height: 100px;
    background-color: skyblue;
}

.box2 {
    /* width: 200px; */
    height: 200px;
    background-color: orangered;
}
var btn = document.getElementById('btn');
btn.onclick = function() {
    var outer = document.getElementById('outer');
    toggleClass(outer, 'box2');
};

/* 切换样式, 如果有目标样式, 则删除, 没有则添加 */
function toggleClass(obj, cls) {
    if(hasClass(obj, cls)) {
        removeClass(obj, cls);
    }
    else {
        addClass(obj, cls);
    }
}

/* 检查目标标签是否有指定class */
function hasClass(obj, cls) {
    var reg = new RegExp('\\b' + cls + '\\b');  // 单词边界\b
    return reg.test(obj.className);
}

/* 向目标标签添加指定class */
function addClass(obj, cls) {
    if(!hasClass(obj, cls)) {
        obj.className += ' ' + cls;  // 注意空格
    }
}

/* 在目标标签中删除指定class */
function removeClass(obj, cls) {
    var reg = new RegExp('\\b' + cls + '\\b', 'g');  // 单词边界\b, 替换所有的cls, 所以是全局的
    obj.className = obj.className.replace(reg, '');
}

二级菜单

<div id="menu">
    <div class="">
        <span>Page1</span>
        <a href="#">1</a>
        <a href="#">2</a>
        <a href="#">3</a>
    </div>
    <div class="collapsed">
        <span>Page2</span>
        <a href="#">4</a>
        <a href="#">5</a>
        <a href="#">6</a>
        <a href="#">7</a>
    </div>
    <div class="collapsed">
        <span>Page3</span>
        <a href="#">8</a>
        <a href="#">9</a>
    </div>
</div>
* {
    margin: 0;
    padding: 0;
}

.collapsed {
    height: 35px;
}

#menu div {
    overflow: hidden;
}

#menu {
    width: 100px;
    margin: 200px auto;
}

#menu span {
    display: block;
    height: 34px;
    line-height: 34px;
    border-bottom: 1px solid #f7f7f7;
    background-color: gray;
    color: #f4f4f4;
    padding-left: 10px;
}

#menu span:hover {
    cursor: pointer;
}

#menu div a {
    display: block;
    height: 35px;
    text-decoration: none;
    color: cadetblue;
    line-height: 35px;
    background-color: #f4f4f4;
    border-bottom: 1px solid #a9a9a9;
    padding-left: 10px;
}

#menu div a:hover {
    background-color: cadetblue;
    color: #f4f4f4;
}
var menuSpan = document.querySelectorAll('#menu span');

var currPage = menuSpan[0].parentNode;
for(var i = 0; i < menuSpan.length; i++) {
    menuSpan[i].onclick = function() {
        // 打开/关闭当前菜单
        toggleMenu(this.parentNode);

        // 关闭其他菜单
        if(currPage != this.parentNode && !hasClass(currPage, 'collapsed')) {
            toggleMenu(currPage);
        }
        currPage = this.parentNode;
        
    }
}

/* 切换菜单, 增加过渡动画 */
function toggleMenu(obj) {
    var begin = obj.offsetHeight;  // 获取切换前高度
    toggleClass(obj, 'collapsed');  // 切换样式
    var end = obj.offsetHeight;  // 获取切换后高度

    obj.style.height = begin + 'px';  // 修改为切换前的高度

    // 动画结束后, 清除内联样式
    move(obj, end, 10, 'height', function() {
        obj.style.height = '';
    });
}

JSON

JSON (JavaScript Object Notation) 是一种轻量级的数据交换方式。JSON和JS对象的格式相同,但是JSON字符串中的属性名必须加双引号

JSON分类:

  1. 对象
  2. 数组
var obj = '{"name": "Lee", "age": 18}';  // JSON对象
var arr = '[1, 2, true]';  // JSON数组

JSON中允许的值:

  1. 字符串
  2. 数值
  3. 布尔值
  4. null
  5. 对象
  6. 数组

JS中的JSON转换

JS提供了JSON工具类,用来转换JS对象。

  • JSON字符串转JS对象或数组:
var jsonObj = '{"name": "Lee", "age": 18}';  // JSON对象
var jsonArr = '[1, 2, true]';  // JSON数组

var obj = JSON.parse(jsonObj);  // 将JSON字符串转化为JS对象
console.log(obj.age);  // 18

var arr = JSON.parse(jsonArr);  // 将JSON字符串转化为JS数组
console.log(arr[1]);  // 2
  • JS对象或数组转JS字符串:
var obj = '{"name": "ABC", "age": 20}';
var jsonObj = JSON.stringify(obj);
console.log(jsonObj);  // "{\"name\": \"ABC\", \"age\": 20}"
posted @ 2022-03-03 17:14  lv6laserlotus  阅读(82)  评论(0)    收藏  举报