一、什么是SPA
释义:SPA(singgle-page application),单页面应用。
SPA是一种网络应用程序或网站模型,它通过动态重写当前页面来与用户交互,这种方法避免了页面之间切换打断用户体验。
在单页面应用中,所有必要代码(HTML、JavaScript和CSS)都通过单个页面的加载而检索,或者根据需要(通常是为了响应用户操作)动态装载适当的的资源并添加到页面中。
页面在任何时间点都不会重新加载,也不会控制转移到其他页面。
举个栗子:SPA== 保温杯,而上面的 数据图片等内容 == 枸杞跟茶,保温杯的经常换茶跟枸杞,而程序员的保温杯还是原来那个。
我们熟知的js框架如react,vue,angular,ember都属于SPA。
二、什么是MPA
释义:MAP(Multi-page application),多页面应用。
在MPA中,每个页面都是一个主页面,都是独立的。
当我们访问另一个页面的时候,都需要重新加载html、css、js文件,公共文件则根据需求加载。
举个栗子:MPA==多个保温杯,对应的数据内容放在对应的单独页面中,枸杞单独放进“枸杞-保温杯”,茶单独放进“茶-保温杯”,如果你想换种东西喝就要换个保温杯。
三、SPA与MPA的区别
1.SPA(单页面应用)的优缺点
①优点:
· 具有桌面应用的即时性、网站的可移植性和可访问性。
· 用户体验好、快、内容的改变不需要重新加载整个页面。
· 良好的前后端分离,分工更加明显。
· 维护成本相对较底。
②缺点:
· 不利于搜索引擎的捉取。
· 首次渲染速度相对较慢。
· 开发成本相对较高。
2.MPA(多页面应用)的优缺点
①优点:
· 利于搜索引擎的捉取,搜索引擎优化实现方法简易。
· 首次渲染速度相对较快。
· 开发成本相对较低。
②缺点:
· 页面间切换加载慢,不流畅,用户体验差,尤其在移动端。
· 页面重复代码较多。
· 维护成本相对较高。
三、实现一个SPA
1.hash 模式
核心通过监听url中的hash来进行路由跳转。
// 定义 Router
class Router {
constructor () {
this.routes = {}; // 存放路由path及callback
this.currentUrl = '';
// 监听路由change调用相对应的路由回调
window.addEventListener('load', this.refresh, false);
window.addEventListener('hashchange', this.refresh, false);
}
route(path, callback){
this.routes[path] = callback;
}
push(path) {
this.routes[path] && this.routes[path]()
}
}
// 使用 router
window.miniRouter = new Router();
miniRouter.route('/', () => console.log('page1'))
miniRouter.route('/page2', () => console.log('page2'))
miniRouter.push('/') // page1
miniRouter.push('/page2') // page2
2.history模式
history 模式核心借用 HTML5 history api,api 提供了丰富的 router 相关属性
先了解一个几个相关的api
· history.pushState 浏览器历史纪录添加记录。
· history.replaceState修改浏览器历史纪录中当前纪录。
· history.popState 当 history 发生变化时触发。
// 定义 Router
class Router {
constructor () {
this.routes = {};
this.listerPopState()
}
init(path) {
history.replaceState({path: path}, null, path);
this.routes[path] && this.routes[path]();
}
route(path, callback){
this.routes[path] = callback;
}
push(path) {
history.pushState({path: path}, null, path);
this.routes[path] && this.routes[path]();
}
listerPopState () {
window.addEventListener('popstate' , e => {
const path = e.state && e.state.path;
this.routers[path] && this.routers[path]()
})
}
}
// 使用 Router
window.miniRouter = new Router();
miniRouter.route('/', ()=> console.log('page1'))
miniRouter.route('/page2', ()=> console.log('page2'))
// 跳转
miniRouter.push('/page2') // page2
参考:JS每日一题(作者灰灰)