一.vueRouter实现方式:
vue-router是通过hash和History interface两种方式实现前端路由,更新视图但不重新请求页面,在vue-router中,mode参数决定采用哪一种方式来实现路由跳转。
mode参数:
- 默认hash
- history(注:如果浏览器不支持history新特性,则采用hash方式)
- 如果不在浏览器环境中则使用abstract(node环境下)
当你选择了mode类型之后,程序会根据你选择的mode类型创建不同的history对象(HashHistory或HTML5History或AbstractHistory)
hash模式:
1. vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。
2. hash虽然出现在URL中,但不会被包括在HTTP请求中。它是用来指导浏览器动作的,对服务器端完全无用,因此,改变hash不会重新加载页面
3. 每一次改变hash(window.location.hash),都会在浏览器的访问历史中增加一个记录
4. hash 模式的原理是 onhashchange 事件(监测hash值变化)
hash 路由模式的实现主要是基于下面几个特性:
- URL 中 hash 值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送;
- hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换;
- 可以通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用 JavaScript 来对 loaction.hash 进行赋值,改变 URL 的 hash 值;
- 我们可以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。
HashHistory替换路由有两种方式:HashHistory.push() 和 HashHistory.replace():
- HashHistory.push() 将新路由添加到浏览器访问历史的栈项
$router.push() // 调用方法 push()等方法只是一个代理实际是调用的具体history对象的对应方法
HashHistory.push() // 根据Hash模式调用,设置hash并添加到浏览器历史记录(添加到栈项)(window.location.hash = xxx)
History.transitonTo() //transitionTo()方法是父类中定义的是用来处理路由变化中的基础逻辑的, 监测更新,更新则调用History.updateRoute()
History.updateRoute() // 更新路由
{app._route = route} // 替换当前app路由
vm.render() // 更新视图
- HashHistory.replace
replace() 方法与push()方法不同之处在于,它并不是将新路由添加到浏览器访问历史的栈项,而是替换当前路由
history
- 分利用了html5 history interface 中新增的 pushState() 和 replaceState() 方法
- 这两个方法应用于浏览器记录栈,在当前已有的 back、forward、go 基础之上,它们提供了对历史记录修改的功能。
- 只是当它们执行修改时,虽然改变了当前的 URL ,但浏览器不会立即向后端发送请求。
HTML5History替换路由两种方式:pushState()和replaceState()
-
window.history.pushState(stateObject, title, URL)
-
window.history.replaceState(stateObject, title, URL)
hash模式基本类似,只不过将对window.location.hash直接进行赋值和window.location.replace()分别改为了调用history.pushState()和history.replaceState()方法。
history 路由模式的实现主要基于存在下面几个特性:
- pushState 和 repalceState 两个 API 来操作实现 URL 的变化 ;
- 我们可以使用 popstate 事件来监听 url 的变化,从而对页面进行跳转(渲染);
- history.pushState() 或 history.replaceState() 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)。
异同:
- pushState设置新的URL可以是与当前URL同源的任意URL;而hash只能修改#后面的部分,故只可以设置与当前同文档的URL
- pushState设置的新URL可以与当前URL一模一样,这样也会把记录添加到栈中;而hash设置的新值必须与原来不一样才会触发记录添加到栈中
- pushState通过stateObject可以添加任意类型的数据到记录中,而hash只可添加短字符串
- pushState可以额外设置title属性供后续使用
- 比如用户直接在地址栏中输入并回车,浏览器重启重新加载应用等。hash模式仅改变hash部分的内容,而hash部分是不会包含在HTTP请求中的。history模式会将url修改的和正常请求后端的url一样,如果后端没有配置对应的(/user/id)路由处理,则会返回404错误
当你使用 history 模式时,URL 就像正常的 url,例如 http://yoursite.com/user/id,也好看!
不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就不好看了。
所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '*', component: NotFoundComponent }
]
})
vue项目实现路由按需加载(路由懒加载)的3种方式
- vue-router配置路由,使用vue的异步组件技术,可以实现按需加载。
{
path: '/promisedemo',
name: 'PromiseDemo',
component: resolve => require(['../components/PromiseDemo'], resolve)
}
- es提案的import()
// 下面2行代码,没有指定webpackChunkName,每个组件打包成一个js文件。
const ImportFuncDemo1 = () => import('../components/ImportFuncDemo1')
const ImportFuncDemo2 = () => import('../components/ImportFuncDemo2')
// 下面2行代码,指定了相同的webpackChunkName,会合并打包成一个js文件。
// const ImportFuncDemo = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/ImportFuncDemo')
// const ImportFuncDemo2 = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/ImportFuncDemo2')
export default new Router({
routes: [
{
path: '/importfuncdemo1',
name: 'ImportFuncDemo1',
component: ImportFuncDemo1
},
{
path: '/importfuncdemo2',
name: 'ImportFuncDemo2',
component: ImportFuncDemo2
}
]
})
- webpack提供的require.ensure()
{
path: '/promisedemo',
name: 'PromiseDemo',
component: resolve => require.ensure([], () => resolve(require('../components/PromiseDemo')), 'demo')
},
{
path: '/hello',
name: 'Hello',
// component: Hello
component: resolve => require.ensure([], () => resolve(require('../components/Hello')), 'demo')
}
参考:
【源码拾遗】从vue-router看前端路由的两种实现
vue项目实现按需加载的3种方式:vue异步组件、es提案的import()、webpack的require.ensure()