js高级程序设计学习-BOM

690 阅读5分钟

导言

本文内容如下:

  • 理解window对象
  • 控制窗口, 框架和弹出窗口
  • 利用location 对象中的页面信息
  • 使用 navigator 对象了解浏览器

window对象

BOM的核心对象是 window ,它表示浏览器的一个实例。

全局作用域

由于 window 对象同时扮演着 ES 中 Global 对象的角色。
因此所有在全局作用域中声明的变量, 函数都会变成 window 对象的属性和方法。

当然,这里说的是 使用 var在全局作用域中声明变量。

抛开全局变量会成为 window对象的属性不谈,定义全局变量与在 window对象上直接定义属性还是有一点差别:

  • 全局变量不能通过 delete 操作符删除, 而直接在window对象上定义的属性可以。
var age = 26;
window.color = 'red';

delete window.age; // 不能删除
delete window.color; // 可以删除

使用var 语句添加到 window的属性有一个名为[[Configurable]]的特性,这个特性的值被设置为false,因此这样定义的属性不可以通过delete操作符删除

导航和打开窗口

额,这个API好像不怎么用到呀,就简单看看吧

window.open('https://www.baidu.com','_blank')

location 对象

location 它提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能。
事实上,window.location 与 document.location 引用的是同一个对象。
location将 URL解析成独立的片段,让开发人员可以通过不同的属性访问这些片段:

属性名 例子 说明
hash "#contents" 返回URL中的 hash值, 如果URL中不包含散列,则返回空字符串
host "www.baidu.com:80" 返回服务器名称和端口号(如果有)
hostname "www.baidu.com" 返回不带端口号的服务器名称
href "www.baidu.com" 返回当前加载页面的完整的URL.而lacation.toString()也是
pathname "/s" 返回 URL中的目录和文件名
port "8080" 返回URL的指定的端口号。如果URL中不包含端口号,则返回空字符串
protocol "http:" 返回页面使用的协议。通常是http或https
search "q=javascript" 返回URL的查询字符串。这个字符串以问号开头

查询字符串参数

let search = "?query=hello&period=2&ka=sel-scale-2";
function Parse(search) {
    let obj = {};
    let s = search.slice(1);
    let s_arr = s.split('&');
    s_arr.forEach((para) => {
        let arr_para = para.split('=');
        obj[arr_para.shift()] = arr_para.pop();
    })
    return obj;
    let search_o = Parse(search);
    console.log(search_o); 
    /**
    {
      query: 'hello',
      period: '2',
      ka: 'sel-scale-2'
    }
    /
}

URLSearchParams

额,貌似,js自己带了一个可以解析 location.search的 API

  • has():返回一个布尔值,表示是否具有某个参数
  • get():返回指定参数的第一个值
  • getAll():返回一个数组,成员是指定参数的所有值
  • set():设置指定参数
  • delete():删除指定参数
  • append():在查询字符串之中,追加一个键值对
  • toString():返回整个查询字符串
var paramsString = 'q=URLUtils.searchParams&topic=api';
var searchParams = new URLSearchParams(paramsString);

searchParams.has('topic') // true
searchParams.get('topic') // "api"
searchParams.getAll('topic') // ["api"]

searchParams.get('foo') // null,注意Firefox返回空字符串
searchParams.set('foo', 2);
searchParams.get('foo') // 2

searchParams.append('topic', 'webdev');
searchParams.toString() // "q=URLUtils.searchParams&topic=api&foo=2&topic=webdev"

searchParams.append('foo', 3);
searchParams.getAll('foo') // [2, 3]

searchParams.delete('topic');
searchParams.toString() // "q=URLUtils.searchParams&foo=2&foo=3"

history 对象

history 对象保存着用户上网的历史记录,从窗口被打开的那一刻算起。
因为 history是 window对象的属性,因此每个浏览器窗口,每个标签页乃至每个框架,都有自己的history对象与特定的window对象关联。

使用go()方法可以实现历史记录中跳转

// 后退一页
history.go(-1);
// 前进一页
history.go(1);
// 前进两页
history.go(2);

当然,也可以给 go()方法传递一个字符串参数

history.go('baidu.com')

另外,还可以使用 back()和forward()来替代go

// 后退一页
history.back()
// 前进一页
history.forward()

1.概述

window.history 属性指向 history 对象 , 它表示当前窗口的浏览历史

当前窗口一共访问3个网址

window.history.length // 3
// 后退到前一个网址
history.back()

// 等同于
history.go(-1)

2.方法

History.pushState()

History.pushState() 方法用于在历史中添加一条记录

window.history.pushState(state, title, url)

该方法接收三个参数:

  • state: 一个添加记录状态的对象, 主要用于 popstate 事件
  • title : 忽略
  • url : 新的网址, 必须与当前页面处于同一域中。

假定当前网址是 example.com/1.html,使用pushState()方法在浏览记录(History 对象)中添加一个新记录。

var stateObj = {foo : 'bar'};
history.pushState(stateObj, 'page 2', '2.html');

总之,pushState()方法不会触发页面刷新,只是导致 History 对象发生变化,地址栏会有反应。

如果pushState()方法设置了一个跨域网址,则会报错。

History.replaceState()

History.replaceState()方法用来修改 History 对象的当前记录,其他都与pushState()方法一模一样。

popstate 事件

每当同一个文档的浏览历史(即history对象)出现变化时,就会触发popstate事件。

注意,仅仅调用pushState()方法或replaceState()方法 ,并不会触发该事件,只有用户点击浏览器倒退按钮和前进按钮,或者使用 JavaScript 调用History.back()、History.forward()、History.go()方法时才会触发。

vue 中 history原理

我们知道 vue 的路由模式有:

  • hash路由
  • history路由

而history路由的原理如下

class Routers {
    constructor() {
        this.routes = {};
        // 在初始化时监听popstate事件
        this._bindPopState();
    }
    // 初始化路由
    init(path) {
        history.replaceState({ path: path }, null, path);
        this.routes[path] && this.routes[path]();
    }
    // 将路径和对应回调函数加入hashMap储存
    route(path, callback) {
        this.routes[path] = callback || function () { };
    }

    // 触发路由对应回调
    go(path) {
        history.pushState({ path: path }, null, path);
        this.routes[path] && this.routes[path]();
    }
    // 监听popstate事件
    _bindPopState() {
        window.addEventListener('popstate', e => {
            const path = e.state && e.state.path;
            this.routes[path] && this.routes[path]();
        });
    }
}


let Route = new Routers();

Route.route('/hello', function () {
    console.log('hello')
})


function change() {
    Route.go('/hello')
}