跳到主要内容

History 对象与 Web Worker

History 对象

window.history属性指向History对象,表示当前窗口的浏览历史。例如:

window.history.length; // 3

History对象主要有两个属性:

History.length:当前窗口访问过的网址数量(包括当前网页) History.state:History 堆栈最上层的状态值

后退

可以通过以下两种方式实现后退到前一个网址:

history.back();

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

History.pushState()

History.pushState()方法用于在历史中添加一条记录,语法如下:

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

popstate 事件

在每一次活动的历史条目发生改变时,就会有一个popstate事件派发给window对象。

下面是一个通过popstate事件实现历史记录的示例

<style>
div {
box-sizing: border-box;
}

.container {
width: 800px;
height: 200px;
}

.box {
float: left;
margin: 20px;
color: #fff;
font-size: 30px;
font-weight: bold;
line-height: 150px;
text-align: center;
cursor: pointer;
width: 150px;
height: 150px;
transition: all 0.2s ease-out;
}

.box:hover {
background-color: #fff;
color: #000;
}

.red {
background-color: red;
border: 5px solid red;
}

.green {
background-color: green;
border: 5px solid green;
}

.blue {
background-color: blue;
border: 5px solid blue;
}

.black {
background-color: black;
border: 5px solid black;
}

.box.selected {
transform: scale(1.2);
}
</style>

<body>
<div class="container">
<div class="box red" id="box-1">1</div>
<div class="box green" id="box-2">2</div>
<div class="box blue" id="box-3">3</div>
<div class="box black" id="box-4">4</div>
</div>
<script>
let boxes = Array.from(document.getElementsByClassName('box'));
function selectBox(id) {
boxes.forEach((item) => {
item.classList.toggle('selected', item.id === id);
});
}
boxes.forEach((item) => {
item.addEventListener('click', (e) => {
let id = item.id;
history.pushState({ id }, null, `selected=${id}`);
selectBox(id);
});
});
window.addEventListener('popstate', (e) => {
let id = e.state.id;
selectBox(id);
});
</script>
</body>

另一个通过popstate事件实现过滤功能的示例

<body>
<input type="text" id="inputKwd" />
<button id="btn">查询</button>
<div class="output"></div>
<script>
var data = [{ name: 'VueJS0' }, { name: 'VueJS1' }, { name: 'VueJS2' }, { name: 'VueJS3' }, { name: 'VueJS4' }, { name: 'VueJS5' }];
var outputArea = document.getElementsByClassName('output')[0],
btn = document.getElementById('btn'),
inputKwd = document.getElementById('inputKwd');

btn.addEventListener('click', function () {
var keyword = inputKwd.value;
var filteredData = data.filter(function (item) {
return item.name.indexOf(keyword) !== -1;
});
renderDom(filteredData);
history.pushState({ keyword }, null, '#' + keyword);
});

function renderDom(data) {
var html = data.map((item) => `<p>${item.name}</p>`).join('');
outputArea.innerHTML = html;
}

renderDom(data);

window.addEventListener(
'popstate',
function (e) {
var keyword = e.state ? e.state.keyword : '';
var filteredData = data.filter(function (item) {
return item.name.indexOf(keyword) !== -1;
});

inputKwd.value = keyword;
renderDom(filteredData);
},
false
);
</script>
</body>

HashChangeEvent

HashChangeEvent接口表示一个变化事件,当 URL 中的片段标识符(即#号后面的部分)发生改变时,会触发此事件。

Web Worker

Worker 是一个可以在后台运行脚本而不影响页面性能的 JavaScript 接口。

Web Worker 有以下特点:

  1. 通过postMessageonmessage进行信息的传递和接收,不支持跨域。
  2. Worker 线程不能直接操作 DOM,但可以通过postMessage与主线程通信,在主线程中操作 DOM。
  3. Worker 不能访问window对象,但可以访问navigator对象的部分属性,如onLine,appName,platform,userAgent等。
  4. Worker 可以发起 AJAX 请求。
  5. Worker 的运行不会影响主线程,但是也不是完全独立的,它们之间通过postMessage进行通信。

基本用法

下面是一个简单的 Web Worker 示例

<body>
<script>
if (window.Worker) {
var myWorker = new Worker('worker.js');
var message = {
addThis: { num1: 1, num2: 1 },
};
myWorker.postMessage(message);
myWorker.onmessage = function (e) {
console.log(e.data); // {result: 2}
};
}
</script>
</body>

worker.js:

onmessage = function (e) {
if (e.data.addThis !== undefined) {
var result = e.data.addThis.num1 + e.data.addThis.num2;
postMessage({ result });
}
};

多个 Worker

一个 Worker 可以启动多个 Worker,通过importScripts()方法加载其他 Worker 脚本:

importScripts('worker1.js', 'worker2.js');

可以使用terminate()方法终止一个 Worker 的执行:

// 终止当前 worker
self.close();

// 终止其他 worker
worker.terminate();

在实际开发中,我们可以利用 Web Worker 实现一些耗时的计算或者数据处理,从而避免阻塞主线程,提高页面性能。但也要注意 Worker 的兼容性问题,目前主流浏览器都已经支持 Web Worker,但在使用时还是要做好降级处理。