h5-history

一、history模式 刷新会404

history.pushState(state, title, url)

  • state: 可以放任意你想放的数据,指向pushState和replaceState方法为当前URL所提供的状态对象。

  • title: 顾名思义,就是document.title。不过这个参数目前并无作用,浏览器目前会选择忽略它。

  • url: 新url,也就是你要显示在地址栏上的url。

history.replaceState(state, title, url)

replaceState方法与pushState大同小异,区别只在于pushState会将当前url添加到历史记录,之后再修改url,而replaceState只是修改url,不添加历史记录。

window.onpopstate 事件

一般来说,每当url变动时,popstate事件都会被触发。但若是调用pushState来修改url,该事件则不会触发,因此,我们可以把它用作浏览器的前进后退事件。该事件有一个参数,就是上文pushState方法的第一个参数state。

注意:

这里的 url 是受到同源策略限制的,防止恶意脚本模仿其他网站 url 用来欺骗用户。所以当违背同源策略时将会报错;

用户点击浏览器倒退按钮和前进按钮,或者使用JavaScript调用back、forward、go方法时才会触发。

另外,该事件只针对同一个文档,如果浏览历史的切换,导致加载不同的文档,该事件也不会触发。

html:

1
2
3
4
5
6
7
8
9

<div id="app">
<ul>
<li><a data-href="/" href="javascript:;">home</a></li>
<li><a data-href="/about" href="javascript:;">about</a></li>
<li><a data-href="/topics" href="javascript:;">topics</a></li>
</ul>
<div id="content"></div>
</div>

js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
var router = {
routes: {},
currentUrl: '',

// 对应的路由绑定一个回调函数,处理要渲染的组件。
route: function (path, callback) {
this.routes[path] = callback || function() {}
},

// 执行路由绑定的函数,进行渲染
update: function (url) {
this.currentUrl = url
this.routes[this.currentUrl] && this.routes[this.currentUrl](url)
},

// 绑定事件,点击时更新路由和视图
bindLink: function () {
var app = document.getElementById('app')
var that = this
app.addEventListener('click', function (e) {
e.preventDefault()
var target = e.target
if (target.nodeName === 'A') {
var url = target.getAttribute('data-href')
history.pushState({}, null, url)
that.update(url)
}
}, false)
},

init: function () {
this.bindLink()
var that = this
// 可以为popstate事件指定回调函数。这个回调函数的参数是一个event事件对象
// 它的state属性指向pushState和replaceState方法为当前URL所提供的状态对象。
window.addEventListener('popstate', e => {
// 可以访问到state里面内容
console.log(e.state)
that.update(window.location.pathname)
})
window.addEventListener('load', () => this.update('/'), false)
}
}
router.init()

使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var components = {
'/': '<div>组件A</div>',
'/about': '<div>组件B</div>',
'/topics': '<div>组件C</div>'
}

var getItem = document.getElementById('content')
router.route('/', function(url) {
getItem.innerHTML = components[url]
})
router.route('/about', function(url) {
getItem.innerHTML = components[url]
})
router.route('/topics', function(url) {
getItem.innerHTML = components[url]
})

二、hash 模式 刷新不会丢失

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

<ul id="list" >
<li><a href="#first" data-url="first">first</a></li>
<li><a href="#second" data-url="second">second</a></li>
<li><a href="#third" data-url="third">third</a></li>
</ul>
<div id="content-main"></div>

<script type="text/javascript">
// hash 值模式
window.addEventListener('hashchange', function (e) {
document.getElementById('content-main').innerText = location.hash
})

document.getElementById('list').addEventListener('click', function (e) {
let target = e.target
if (target.nodeName === 'SPAN') {
location.hash = target.textContent
}
})
</script>
返回
顶部