历史
前后端未分离时路由都由服务端控制。 前端/客⼾端 -> http 请求 -> 服务端 -> 根据 url 路径的不同,返回不同的 html/数据
这种⽅式的缺点和优点都⾮常明显
优点:SEO 效果好,直接返回一个HTML,⾸屏的耗时⼩(浏览器地址输入一个UR离开时--->页面上任意元素展示)
缺点:服务器压⼒⼤,构建HTML过程放在服务器上,前后端代码融合在⼀起不好维护,协作麻烦
单页应用
前后端未分离时路由都由服务端控制。 前端/客⼾端 -> http 请求 -> 服务端 -> 根据 url 路径的不同,返回不同的 html/数据
这种⽅式的缺点和优点都⾮常明显
优点:SEO 效果好,直接返回一个HTML,⾸屏的耗时⼩(浏览器地址输入一个UR离开时--->页面上任意元素展示)
缺点:服务器压⼒⼤,构建HTML过程放在服务器上,前后端代码融合在⼀起不好维护,协作麻烦
前端路由 router 原理及表现
vue -> hash, history react -> hash, history
要求:页面间的交互不刷新页面;不同 Url 会渲染不同的内容
Hash 和 History有什么区别
- hash 有#,history 没有
- hash 的#部分内容不会给服务端, history 的所有内容都会给服务端
- hash 通过 hashchange 监听变化,history 通过 popstate 监听变化
- histudy路由在应用部署的时候需要注意html文件访问(nginx指向)
1、Hash
特性
- url 中带有一个#符号,但是#只是浏览器端/客户端的状态,不会传递给服务端。
www.baidu.com/#/user -> http -> www.baidu.com/
www.baidu.com/#/list/deta… -> http -> www.baidu.com/
- hash 值的更改,不会导致页面的刷新
location.hash = '#aaa';
location.hash = '#bbb';
从#aaa 到#bbb,页面是不会刷新的
-
hash 值的更改,会在浏览器的访问历史中添加一条记录。所以我们才可以通过浏览器的返回、前进按钮来控制 hash 的切换
-
hash 值的更改,会触发 hashchange 事件
location.hash = '#aaa';
location.hash = '#bbb';
window.addEventLisenter('hashchange', () => {})
- 如何更改 hash
①. location.hash
location.hash = '#aaa'
②. html 标签的方式
<a href="#user"> 点击跳转到 user </a>
2、History
hash 有个#符号,不美观,服务端无法接受到 hash 路径和参数,histudy没有
html5 history api
window.history.back(); // 后退
window.history.forward(); // 前进
window.history.go(-3); // 接收number参数,后退三个页面
window.history.pushState(null, null, path);
window.history.replaceState(null, null, path);
pushState/replaceState 的参数
- state, 是一个对象,是一个与指定网址相关的对象,当 popstate 事件触发的时候,该对象会传入回调函数
- title, 新页面的标题,浏览器支持不一,null
- url, 页面的新地址
pushState, 页面的浏览记录里添加一个历史记录 replaceState, 替换当前历史记录
相关问题
问:pushState 时,会触发 popstate 吗?
答:pushState/replaceState 并不会触发 popstate 事件, 这时我们需要手动触发页面的重新渲染。
问:popstate 到底什么时候才能触发。
答:点击浏览器后退按钮;点击浏览器前进按钮;js 调用 back 方法;js 调用 forward 方法;js 调用 go 方法
nginx配置
1、index.html存在服务器本地(nginx部署不在A服务器,index文件也在A服务器)
www.baidu.com/index
www.baidu.com/index/a
location /index/ {
tey_files $uri $uri /home/dist/index.html
}
2、index.html存在远程服务器,oss/cdn
www.baidu.com/index
www.baidu-cdn.com/file/index.html 文件位置
location /index/ {
rewrite ^ /file/index/html break;
proxy_pass https://www.baidu-cdn.com;
}
3、实现基本的hash和histudy路由
//hash路由
class BaseRouter {
constructor() {
this.routes = {}; // 存储path以及callback的对应关系
this.refresh = this.refresh.bind(this);
window.addEventListener('load', this.refresh); // 处理页面首次加载
window.addEventListener('hashchange', this.refresh); // 处理页面hash的变化
}
/**
* route
* @param {string} path 路由路径
* @param {function} callback 回调函数
*/
route(path, callback) {
// 向this.routes存储path以及callback的对应关系
this.routes[path] = callback || function () {};
}
refresh() {
// 刷新页面
const path = `/${location.hash.slice(1) || ''}`;
console.log(location.hash);
this.routes[path]();
}
}
// 期望看到的是,点击三个不同的a标签,页面的背景色会随之改变
const body = document.querySelector('body');
function changeBgColor(color) {
body.style.backgroundColor = color;
}
const Router = new BaseRouter();
Router.route('/', function () {
changeBgColor('white');
});
Router.route('/green', function () {
changeBgColor('green');
});
Router.route('/gray', function () {
changeBgColor('gray');
});
//histudy路由
class BaseRouter {
constructor() {
this.routes = {};
// location.hash; hash的方式
this.init(location.pathname);
this._bindPopState();
}
init(path) {
window.history.replaceState({
path
}, null, path);
const cb = this.routes[path];
// cb && cb();
if (cb) {
cb();
}
}
route(path, callback) {
this.routes[path] = callback || function () {};
}
go(path) {
// 跳转并执行对应的callback
window.history.pushState({
path
}, null, path);
const cb = this.routes[path];
// cb && cb();
if (cb) {
cb();
}
}
_bindPopState() {
// 演示一下popstate事件触发后,会发生什么
window.addEventListener('popstate', (e) => {
const path = e.state && e.state.path;
console.log(`in popstate listener path=${path}`);
this.routes[path] && this.routes[path]();
})
}
}
const Router = new BaseRouter();
const body = document.querySelector('body');
function changeBgColor(color) {
body.style.backgroundColor = color;
}
Router.route('/', function () {
changeBgColor('white');
});
Router.route('/gray', function () {
changeBgColor('gray');
});
Router.route('/green', function () {
changeBgColor('green');
});