【紫書總結】第四章 ---函式和遞迴
技術標籤:vue-routervue
vue-router
在研究vue的路由前,先說說什麼是路由
路由是指 當地址欄的改變時頁面做出改變
路由分為前端路由 和 後端路由
- 後端路由就是指訪問和相應了,位址列是百度,當前的路由就是百度,如果跳轉到淘寶,路由就是淘寶,後端路由會帶來頁面重新整理
- 前端路由是自己通過API改變位址列的內容,再判斷位址列的值修改頁面的內容,最重要的是前端路由是可以被瀏覽器的
history
記錄,history記錄的意思就是點選返回是返回上一個路由,到了最後一個路由關閉頁面,完美的模擬後端路由的效果
為什麼要用前端路由,前端路由帶來了什麼
- 漂亮的路由地址,去看看網易雲音樂的網頁版地址和嗶哩嗶哩的網站地址
- 減少頁面請求,只需要ajax修改資料,只需要第一次進入請求一次頁面資料就行,稱為單頁面應用,簡稱
SPA
起步
如果沒有安裝vue-router
自己去看開發文件
- 先npm下載
- 然後在建立配置檔案和基礎配置檔案的模板
- 最後在main.js引入
vue的路由是用什麼APIhistory
和hash
window.history
// 方法有
history.pushState
history.replaceState
window.hash
// 方法有
window.hashchange = function(){ ... }
這兩個路由對應的就是vue-router的配置的引數mode
,預設是hash
new Router({ mode: 'history', // history 和 hash routes: [{ path: '/', component: () => import('page/home'), children: [{ path: 'list', component: () => import('page/list'), }] },{ path: '/404', component: () => import('page/error') }] })
mode的引數有什麼區別
history模式,這是個新API,所以相容性不好,位址列沒有【#】,嗶哩嗶哩就是沒帶【#】號的,更好看,而且在微信的分享等地方是禁止用【#】的
hash模式,位址列帶有【#】,網易雲音樂就是帶【#】號的,我不喜歡這個模式
routes引數是一個數組,這個陣列需要學的有子路由的配置和引數路由的配置
在配置之前瞭解一下vue怎麼把路由進行顯示出來的,看路由的component
引數,這個是指當有人訪問這個路由,我就給他看哪個頁面的傳參,引數是一個頁面的地址,首先找到這個路徑下的地址,是.vue字尾檔案,開啟後是這樣的
<template> <div> <div>HOME</div> <div>{{ msg }}</div> </div> </template> <script> export default { // 這個name是無意義的,只是為了好看,是程式碼規範,但不是程式碼規定 name: 'HOME', data(){ return { msg:"helloword" } } } </script> <style scoped> // 這是寫樣式的 // scoped屬性的意思是這裡的樣式只服務這個vue檔案 </style>
那這個檔案被顯示到哪裡了呢
vue格式檔案顯示在<router-view />
標籤裡,這也是子路由的配置理解,比如上面的路由配置,當路由是【/】時,頁面顯示的是home.vue這個檔案,如果路由是【/404】就顯示的是error.vue檔案,home和error是展示在同一個<router-view />
裡的,因為他們屬於同一級,把這個<router-view />
理解成div的innerHTML也行,所以當我們要給路由【/】新增子路由時,就需要在home.vue檔案裡放置一個<router-view />
標籤,如下
<div>我是HOME.vue</div>
<router-view />
當路由是【/】時,我們會看到我是HOME.vue,看不到<router-view />
,當我們訪問【/list】時,<router-view />
會繪製上list.vue檔案的程式碼,就能看到頁面顯示,我是HOME.vue,我是List.vue,應該很好理解吧
那麼問題來了,一級配置,也就是上面的【/】和【/404】是顯示在哪個<router-view />
裡的,在檔案列表有個APP.vue
檔案,這個才是一級路由顯示的地方,這個檔案又顯示在哪呢,顯示在public資料夾的index.html,開啟index.html,會看見一個id為app的div,跟srcipt引入外掛的方式一樣,vue腳手架最後也只是把vue給new一下,顯示到#app裡而已,檢視main.js
import App from './App'
import store from './store'
import router from './router'
new Vue({
// 這個就是路由
router,
// 這個是vuex
store,
// render渲染,$mount是代表index.html的id
// 即我把App.vue渲染到id為app的div裡
render: h => h(App)
}).$mount('#app')
現在應該知道怎麼配子路由了吧,接下來引數路由【/:】
new Router({
mode: 'history', // history 和 hash
routes: [{
path: '/:type/:id',
component: () => import('page/type'),
},{
path: '/home/test',
component: () => import('page/ceshi'),
}]
})
上面的路由是要幹什麼呢,是想實現根據型別和id去返回頁面的功能,比如【/book/0001】,是指找一個編號是0001的書,【/movie/123】是找一部編號123的電影,所以我才說前段路由是那麼的好看,如果是後端路由應該是【xxx.com/index.html?type=movie&id=123】
在上面有個【/home/test】的配置,如果有人訪問這個,會跳轉到上面去嗎,這是不會的,引數路由是最後被判斷的,這個外掛是非常智慧的,先把固定的判斷完,沒合適的再去找引數路由
問題來了,我怎麼去知道當前的type是什麼,id是什麼,去到type.vue這個檔案裡
mounted(){
// 把當前頁面的路由打印出來
console.log(this.$route)
// 裡面有個params屬性,是個物件
// 把這個物件取值判斷就行
console.log(this.$route.params)
}
除了params
物件,路由還有一個query
物件,就是正常的問號傳參,試一下在位址列上路由的最後面加上【?name=name&age=age】,就會在路由裡看到query物件,很好理解,不寫栗子了
總結下路由的配置
路由的配置就是複製黏貼,沒什麼可玩性,按照文件設定好就行
路由的監控
如果我想根據路由的整體的變化做一些判斷呢,如果我想控制一些許可權呢
在路由的配置頁面加上這個方法
new Router({
mode: 'history', // history 和 hash
routes: [{
path: '/:type/:id',
// 先配置一個title屬性,你想寫什麼屬性都行
title: "我是title",
component: () => import('page/type'),
}]
})
下面這個監聽的程式碼可以寫在router.js裡,最好還是單獨拆一個檔案出來
router.beforeEach((to, from, next) => {
// 這個to就是當前頁面的路由的物件,也就是this.$route
console.log(to)
if(to.title){ document.title = to.title }
else{ document.title = "pdt-1997" }
if(user=="pdt"){
console.log("沒資格訪問")
// 重定向到主頁
next({path:'/'})
}else{
// next一定要有,不然路由不執行
next()
}
})
router.afterEach(() => {
})
怎麼跳轉
上面的測試都是手動去改路由,再重新整理頁面
首先就是用標籤去跳轉,理解為a標籤,一般不用標籤跳轉
<router-link to="/">去到主頁</router-link>
<router-link :to="{path:'/index',query:{id:'xxx',name:'xxx'}}">
push和replace
push是把當前路由A存起來,然後跳轉B,如果點選返回會到A
replace是跳轉B,然後把B替換A,如果點選返回A之前的路由或者關閉頁面
this.$router.push({ path:"/it/"+data.id ,query:{ page:this.pageNo }})
this.$router.replace({ path:"/it/"+data.id ,query:{ page:this.pageNo }})
應該注意的點
vue檔案的template標籤的子標籤只能有一個
<template>
<div>
<div>HOME</div>
<div>{{ msg }}</div>
</div>
<div> 如果再加上這個會報錯 </div>
</template>
hash的實現原理
<a href="#/home">首頁</a>
<a href="#/about">關於</a>
<div id="html"></div>
<script>
window.addEventListener('load',()=>{
html.innerHTML = location.hash.slice(1);
});
window.addEventListener('hashchange',()=>{
html.innerHTML = location.hash.slice(1)
})
</script>
history的實現原理
<a onclick="go(/home)">首頁</a>
<a onclick="go(/about)">關於</a>
<div id="html"></div>
<script >
function go(pathname) {
history.pushState({},null,pathname)
html.innerHTML = pathname;
}
window.addEventListener('popstate',()=>{
go(location.pathname);
})
</script>