路由使用
- 靜態路由
// 路由規則
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 參數
// <!-- 方式2:路由規則中開啟 props 傳參 -->
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')
}
]
// 頁面
<template>
<div>
<!-- 方式1: 通過當前路由規則,獲取數據 -->
通過當前路由規則獲取:{{ $route.params.id }}
<br>
<!-- 方式2:路由規則中開啟 props 傳參 -->
通過開啟 props 獲取:{{ id }}
</div>
</template>
<script>
export default {
name: 'Detail',
// <!-- 方式2:路由規則中開啟 props 傳參 -->
props: ['id']
}
</script>
<style>
</style>
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
<script>
export default {
name: 'Index',
methods: {
replace () {
// replace沒有歷史記錄
this.$router.replace('/login')
},
goDetail () {
// 支持路由和name跳轉
// this.$router.push({ path: '/detail/1' })
this.$router.push({ name: 'Detail', params: { id: 1 } })
},
go () {
// 返回上面二層頁面, 正數代表next, 負數代表previous
this.$router.go(-2)
}
}
}
</script>
- 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: "<a :href='to'><slot></slot><>"
})
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