前端路由
前端路由,指的是 URL 与内容间的映射关系
Hash 方式
通过 hashchange 事件监听 hash 变化,并进行网页内容更新。
<div>
<a href="#/">首页</a>
<a href="#/category">分类页</a>
<a href="#/user">用户页</a>
</div>
<div id="container">
这是首页功能
</div>
<script>
// 准备对象,用于封装 hash 功能。
var router = {
// 路由存储位置: 保存了 url 与 内容处理函数的对应关系。
routes: {},
// 定义路由规则的方法
route: function (path, callback) {
//将path作为key存储到routes对象,因为path是字符串所以必须用中括号的形式
this.routes[path] = callback;
},
// 初始化路由的方法
init: function () {
//因为window.onhashchange中的this指向的是window,需要访问对象中的其他内容可以将this提前赋值给一个变量
var that = this;
window.onhashchange = function () {
// 当 hash 改变,我们需要得到当前新的 hash
var hash = location.hash.replace('#', '');
// 根据 hash 触发 routes 中的对应 callback,通过&&运算符判断假如routes存在对应的函数则进行调用
that.routes[hash] && that.routes[hash]();
};
}
};
var container = document.getElementById('container');
// 定义路由规则
router.route('/', function () {
container.innerHTML = '这是首页功能';
});
router.route('/category', function () {
container.innerHTML = '这是分类功能';
});
router.route('/user', function () {
container.innerHTML = '这是用户功能';
});
// 初始化路由
router.init();
</script>
特点总结:
- Hash 方式兼容性好。
- 地址中具有 #,不太美观。
- 前进后退功能较为繁琐。
History 方式
-
History 方式采用 HTML5 提供的新功能实现前端路由
-
在操作时需要通过 history.pushState() 变更 URL并执行对应操作。
<div>
<a href="/">首页</a>
<a href="/category">分类</a>
<a href="/user">用户</a>
</div>
<div id="container">
这是首页功能
</div>
<script>
var router = {
// 存储路由的对象
routes: {},
// 定义路由的方法
route (path, callback) {
this.routes[path] = callback;
},
// 用于触发指定的路由操作
go (path) {
// 更改 url
history.pushState(null, null, path);
// 触发路由对应的回调函数
this.routes[path] && this.routes[path]();
}
};
// 设置 a 标签的功能
var links = document.querySelectorAll('a');
var container = document.querySelector('#container');
links.forEach(function (ele) {
ele.addEventListener('click', function (event) {
//通过getAttribute获取href的内容
router.go(this.getAttribute('href'));
//阻止跳转
event.preventDefault();
});
});
// 路由规则
router.route('/', function () {
container.innerHTML = '首页功能';
});
router.route('/category', function () {
container.innerHTML = '分类功能';
});
router.route('/user', function () {
container.innerHTML = '用户功能';
});
</script>
前进后退功能
- 首先需要在更改 url 时保存路由标记。
- 通过 popstate 事件监听前进后退按钮操作,并检测 state。
- 调用初始化方法监听前进后退操作并处理。
<div>
<a href="/">首页</a>
<a href="/category">分类</a>
<a href="/user">用户</a>
</div>
<div id="container">
这是首页功能
</div>
<script>
var router = {
// 存储路由的对象
routes: {},
// 定义路由的方法
route (path, callback) {
this.routes[path] = callback;
},
// 用于触发指定的路由操作
go (path) {
// 更改 url
history.pushState({ path: path }, null, path);
// 触发路由对应的回调函数
this.routes[path] && this.routes[path]();
},
// 设置初始化方法,用来检测前进后退按钮的功能
init () {
var that = this;
window.addEventListener('popstate', function (e) {
var path = e.state ? e.state.path : '/';
that.routes[path] && that.routes[path]();
});
}
};
router.init();
// 设置 a 标签的功能
var links = document.querySelectorAll('a');
var container = document.querySelector('#container');
links.forEach(function (ele) {
ele.addEventListener('click', function (event) {
router.go(this.getAttribute('href'));
event.preventDefault();
});
});
// 路由规则
router.route('/', function () {
container.innerHTML = '首页功能';
});
router.route('/category', function () {
container.innerHTML = '分类功能';
});
router.route('/user', function () {
container.innerHTML = '用户功能';
});
</script>
特点总结:
- 书写简答格式美观
- pushState可存储数据量更大
- 兼容性差
- 刷新页面时需要后端支持