Реализация внешней маршрутизации (история)
К пониманию:
История HTML5 добавляет два новых API: history.pushState и history.replaceState.
Оба API принимают три параметра
-
объект состояния: объект JavaScript, связанный с новой записью в истории, созданной с помощью метода pushState(). Всякий раз, когда пользователь переходит к вновь созданному состоянию, запускается событие popstate, а свойство состояния объекта события содержит копию объекта состояния записи истории.
-
Заголовок: в настоящее время этот параметр игнорируется браузером FireFox, хотя он может использоваться в будущем. Учитывая, что этот метод может быть изменен в будущем, безопаснее передавать пустую строку. В качестве альтернативы вы можете передать короткий заголовок, указывающий состояние, в которое нужно войти.
-
Адрес (URL): адрес новой записи истории. Браузер не будет загружать адрес после вызова метода pushState(), но может попытаться загрузить его позже, например, если пользователь перезапустит браузер. Новый URL-адрес не обязательно должен быть абсолютным путем; если это относительный путь, он будет основан на текущем URL-адресе; входящий URL-адрес и текущий URL-адрес должны иметь одно и то же происхождение, в противном случае pushState() выдаст ошибку исключение. Этот параметр является необязательным, если он не указан, это текущий URL-адрес документа.
То же самое и в том, что оба API работают с историей браузера, не вызывая обновления страницы. Разница в том, что pushState добавляет новую запись истории, а replaceState заменяет текущую запись истории.
Вы можете сначала попробовать это в консоли и посмотреть, что изменилось в адресной строке.
window.history.pushState(null, null, "test");
window.history.pushState(null, null, "/test");
window.history.pushState(null, null, "#/hello");
window.history.pushState(null, null, "?name=");
</code></pre>
Пример демонстрации
Создайте html-файл index.html.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>前端路由实现</title>
<style>
.warp{
width:400px;
height:400px;
border:1px solid grey;
margin:0 auto;
}
.nav{
border-bottom:1px solid grey;
}
.nav li{
display:inline-block;
list-style:none;
}
.nav li a{
display:inline-block;
text-decoration: none;
padding:10px 15px;
}
.router{
padding:20px;
}
a{
cursor: pointer;
}
</style>
</head>
<body>
<section class="warp">
<div class="nav">
<ul>
<li><a href="javascript:void(0)" data-path="index">首页</a></li>
<li><a href="javascript:void(0)" data-path="news">新闻</a></li>
<li><a href="javascript:void(0)" data-path="about">关于</a></li>
</ul>
</div>
<div id="router" class="router">
<!-- 内容加载区域 -->
</div>
</section>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="./router.js"></script>
</body>
</html>
Страница на данный момент:
Представьте файл js router.js
(function(){
history.replaceState(null,null,'');//最开始的状态,采用replace直接替换
$('#router').html('<p>显示内容区域</p>')
$('a').on('click',function(){
console.log(this.text)
var text = this.text;
$('#router').html('<p>'+ text +'</p>')
history.pushState(null,null,'#/'+text);
})
})()
Когда кнопка навигации нажата в этой точке
- В это время, когда щелкают различные элементы навигации, маршруты в адресной строке соответственно изменяются, а также изменяется отображаемая область содержимого. Но на самом деле это не реализует настоящего смысла маршрутизации. Потому что изменение части контента основано на срабатывании события для получения текущего контента.
- В настоящее время, если вы нажмете кнопки просмотра вперед и назад, содержимое не может быть изменено путем отслеживания изменения адресной строки.
Исходя из этого, измените метод реализации и измените router.js на:
// 状态版
(function(){
var count = [0,0,0]
$('#router').html('<p>首页</p>'+count[0]+'<p>新闻</p>'+count[1]+'<p>关于</p>'+count[2])
// history.replaceState(count,null,'');//最开始的状态,采用replace直接替换
for(var i = 0 ; i<$('a').length; i++){
$('a')[i].index = i
$('a').eq(i).on('click',function(){
console.log(this.index);
var index = this.index;
count[index]++;
$('#router').html('<p>首页</p>'+count[0]+'<p>新闻</p>'+count[1]+'<p>关于</p>'+count[2])
console.log(count)
history.pushState(count,null,'#/count'+count[index]);//之后的状态,需要进行保存
})
}
//监听history其他api导致地址栏url改变事件
window.addEventListener('popstate',function(e){
console.log(e.state);
var state = e.state;
$('#router').html('<p>首页</p>'+state[0]+'<p>新闻</p>'+state[1]+'<p>关于</p>'+state[2])
})
})()
Идея в настоящее время состоит в том, чтобы сделать запись состояния, записав количество нажатий каждой кнопки навигации. Когда переключатель панели навигации щелчка выполняется каждый раз, объект состояния передается через API history.pushState(count, null, '#/count'+count[index]), а текущий объект состояния передается в третьем параметр Количество кликов используется в качестве отображаемых данных в адресной строке. Пример выглядит следующим образом:
- !!Событие popstate запускается при изменении записи истории активности. Если активированная запись истории была создана вызовом history.pushState() или на нее повлиял вызов history.replaceState(), свойство состояния события popstate содержит копию объекта состояния записи истории.
- Следует отметить, что вызов history.pushState() или history.ReplaceState() не вызывает событие popState. Это событие запускается только при выполнении действия браузера, например, когда пользователь нажимает кнопку отката браузера (или вызывает history.back()) в коде JavaScript)
Здесь использование и параметры pushState объясняются записью количества кликов каждый раз Фактически, простой метод записи может быть выражен как:
(function(){
var url = '内容展示';
history.replaceState(url,null,'');//最开始的状态,采用replace直接替换
$('#router').html('<p>'+url+'</p>')
$('a').on('click',function(){
console.log(this.text)
url = this.text;
$('#router').html('<p>'+ url +'</p>')
history.pushState(url,null,'#/'+url);
})
window.addEventListener('popstate',function(e){
console.log(e.state);
url = e.state
$('#router').html('<p>'+ url +'</p>')
});
})()