路由使用
- 静态路由
// 路由规则
const routes = [
{
path: '/',
name: 'Index',
component: Index
},
{
path: '/blog',
name: 'Blog',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "blog" */ '../views/Blog.vue')
}
]
- 动态路由
通过当前路由规则获取 或者 通过开启 props 获取, 建议通过props来解耦
// 路由规则
const routes = [
{
path: '/',
name: 'Index',
component: Index
},
{
path: '/detail/:id',
name: 'Detail',
// 开启 props,会把 URL 中的参数传递给组件
// 在组件中通过 props 来接收 URL 参数
//
props: true,
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "detail" */ '../views/Detail.vue')
}
]
// 页面
通过当前路由规则获取:{{ $route.params.id }}
通过开启 props 获取:{{ id }}
3.嵌套路由
const routes = [
{
name: 'login',
path: '/login',
component: Login
},
// 嵌套路由
{
path: '/',
component: Layout,
children: [
{
name: 'index',
// 外面的path 和 这里path拼接起来
// 可以加/,也可以不加
path: '',
// 外面的Layout 和 这里Index拼接起来
component: Index
},
{
name: 'detail',
path: 'detail/:id',
props: true,
component: () => import('@/views/Detail.vue')
}
]
}
]
- 路由跳转replace、push、go
- hash VS History
- hash 模式
Vue Router 默认使用的是 hash 模式,使用 hash 来模拟一个完整的 URL,通过onhashchange 监听路径的变化。 有一个#
号。 - History 模式
基于 History API ,没有#
号
// 改变地址栏,同时记录,但是不会跳转指定路径, IE10后支持
// 可以实现客户端路由
history.pushState()
// 会发起服务端请求
history.replaceState()
history.go()
需要开启 History 模式
const router = new VueRouter({
// mode: 'hash',
mode: 'history', routes
})
History 需要服务器的支持
单页应用中,服务端不存在 http://www.testurl.com/login 这样的地址会返回找不到该页面
在服务端应该除了静态资源外都返回单页应用的 index.html
服务端开启history,刷新的时候。 其实是先给前端返回index页面,然后再跳转到对应login页面
路由基础实现
let _Vue = null
class JerryVueRouter {
// 接收一个参数,也就是Vue类
// Vue.use(你的插件)自动调用
static install(Vue){
console.log('Srs==>', Vue)
//1 判断当前插件是否被安装
if(JerryVueRouter.install.installed){
return;
}
JerryVueRouter.install.installed = true
//2 把Vue的构造函数记录在全局
_Vue = Vue
//3 把创建Vue的实例传入的router对象注入到Vue实例
// _Vue.prototype.$router = this.$options.router
_Vue.mixin({
beforeCreate(){
// 实例化为Vue 类时,会将 VueRouter 的实例传入,这个变量放在this.$options.router中
// 判断是Vue实例才设置
if(this.$options.router){
_Vue.prototype.$router = this.$options.router
}
}
})
}
constructor(options){
// 包含路由规则
this.options = options
// 路由规则对下
this.routeMap = {}
// observable
this.data = _Vue.observable({
current:"/"
})
this.init()
}
init(){
this.createRouteMap()
this.initComponent(_Vue)
this.initEvent()
}
createRouteMap(){
//遍历所有的路由规则 吧路由规则解析成键值对的形式存储到routeMap中
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
});
}
initComponent(Vue){
Vue.component("router-link",{
props:{
to:String
},
render(h){
return h("a",{
attrs:{
href: this.to
},
on:{
click:this.clickhander
}
}, [this.$slots.default])
},
methods:{
// 重置点击事件, 默认会请求后台数据
clickhander(e){
history.pushState({}, "", this.to)
// 响应事件,会重复view刷新
this.$router.data.current = this.to
e.preventDefault()
}
},
// slot是插槽
// 使用template需要完整版编译
// 需要配置vue.config.js里面的runtimeCompiler
// module.exports = {
// // 完整版view,默认是false。完整版带编译器,多10K
// runtimeCompiler: true
// }
// template: " <>"
})
const self = this
Vue.component("router-view",{
render(h){
// self.data.current
const cm = self.routeMap[self.data.current]
return h(cm)
}
})
}
initEvent(){
// 处理浏览器上返回 前进按钮
window.addEventListener("popstate",()=>{
this.data.current = window.location.pathname
})
}
}
export default JerryVueRouter