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 有以下特点:
- 通过
postMessage
和onmessage
进行信息的传递和接收,不支持跨域。 - Worker 线程不能直接操作 DOM,但可以通过
postMessage
与主线程通信,在主线程中操作 DOM。 - Worker 不能访问
window
对象,但可以访问navigator
对象的部分属性,如onLine
,appName
,platform
,userAgent
等。 - Worker 可以发起 AJAX 请求。
- 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,但在使用时还是要做好降级处理。