單頁(yè)面應(yīng)用(SPA)
只有一張web頁(yè)面的應(yīng)用,跳轉(zhuǎn)的時(shí)候緊緊刷新局部資源,公共資源(js、css等)僅需加載一次,第一次進(jìn)入頁(yè)面時(shí)只會(huì)請(qǐng)求一個(gè)html,刷新的時(shí)候清除頁(yè)面上的組件,切換到其他的組件,這是路徑也會(huì)發(fā)生相應(yīng)的變化,但是不會(huì)有新的html文件請(qǐng)求.
vue-router是什么
vue-router是vue.js的官方路由插件,它依賴于vue.js,適用于單頁(yè)面應(yīng)用,在單頁(yè)面應(yīng)用中將路徑和組件映射起來,路由的本質(zhì)我感覺就是將url和組件之間建立映射關(guān)系.
剛剛開始接觸路由的時(shí)候,可能會(huì)奇怪為什么使用路由,為什么不直接使用a標(biāo)簽?zāi)?這是因?yàn)閂ue做的都是單頁(yè)面應(yīng)用,Vue的項(xiàng)目打包的時(shí)候只會(huì)生成一個(gè)index.html頁(yè)面,a標(biāo)簽的跳轉(zhuǎn)頁(yè)面會(huì)重新渲染,相當(dāng)于打開一個(gè)新的網(wǎng)頁(yè).
vue-router實(shí)現(xiàn)原理
spa的核心是更新視圖而不重新請(qǐng)求頁(yè)面,它提供了兩種方式來實(shí)現(xiàn)單頁(yè)面前端路由: Hash模式和History模式
1. Hash模式:
vue-router 默認(rèn) hash 模式 —— 使用 URL 的 hash 來模擬一個(gè)完整的 URL,于是當(dāng) URL 改變時(shí),頁(yè)面不會(huì)重新加載。hash(#)是URL 的錨點(diǎn),代表的是網(wǎng)頁(yè)中的一個(gè)位置,單單改變#后的部分,瀏覽器只會(huì)滾動(dòng)到相應(yīng)位置,不會(huì)重新加載網(wǎng)頁(yè),也就是說hash 出現(xiàn)在 URL 中,但不會(huì)被包含在 http 請(qǐng)求中,對(duì)后端完全沒有影響,因此改變 hash 不會(huì)重新加載頁(yè)面;同時(shí)每一次改變#后的部分,都會(huì)在瀏覽器的訪問歷史中增加一個(gè)記錄,使用”后退”按鈕,就可以回到上一個(gè)位置;所以說Hash模式通過錨點(diǎn)值的改變,根據(jù)不同的值,渲染指定DOM位置的不同數(shù)據(jù)。hash 模式的原理是 onhashchange 事件(監(jiān)測(cè)hash值變化),可以在 window 對(duì)象上監(jiān)聽這個(gè)事件。
2.History模式:
由于hash模式會(huì)在url中自帶#,如果不想要很丑的 hash,我們可以用路由的 history 模式,只需要在配置路由規(guī)則時(shí),加入"mode: 'history'",這種模式充分利用了html5 history interface 中新增的 pushState() 和 replaceState() 方法。這兩個(gè)方法應(yīng)用于瀏覽器記錄棧,在當(dāng)前已有的 back、forward、go 基礎(chǔ)之上,它們提供了對(duì)歷史記錄修改的功能。只是當(dāng)它們執(zhí)行修改時(shí),雖然改變了當(dāng)前的 URL ,但瀏覽器不會(huì)立即向后端發(fā)送請(qǐng)求。
//main.js文件中
const router = new VueRouter({
mode: 'history',
routes: [...]
})
當(dāng)你使用 history 模式時(shí),URL 就像正常的 url,例如 yoursite.com/user/id,比較好… 不過這種模式要玩好,還需要后臺(tái)配置支持。因?yàn)槲覀兊膽?yīng)用是個(gè)單頁(yè)客戶端應(yīng)用,如果后臺(tái)沒有正確的配置,當(dāng)用戶在瀏覽器直接訪問 oursite.com/user/id 就會(huì)返回 404,這就不好看了。 所以呢,你要在服務(wù)端增加一個(gè)覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態(tài)資源,則應(yīng)該返回同一個(gè) index.html 頁(yè)面,這個(gè)頁(yè)面就是你 app 依賴的頁(yè)面。
export const routes = [
{path: "/", name: "homeLink", component:Home}
{path: "/register", name: "registerLink", component: Register},
{path: "/login", name: "loginLink", component: Login},
{path: "*", redirect: "/"}]
此處就設(shè)置如果URL輸入錯(cuò)誤或者是URL 匹配不到任何靜態(tài)資源,就自動(dòng)跳到到Home頁(yè)面
3. 使用模塊路由來實(shí)現(xiàn)頁(yè)面的跳轉(zhuǎn)
- 直接修地址欄
- This.$router.push('路由地址')
<router-link to="路由地址"></router-link>
Vue-router的使用方式:
-
通過npm安裝vue-router
npm i vue-router -S 引入vue-router到main.js中
import VueRouter from 'vue-router'
- 安裝插件
Vue.use(VueRouter)
- 創(chuàng)建路由對(duì)象并配置路由規(guī)則
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// 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: "about" */ '../views/About.vue')
}
]
const router = new VueRouter({
routes
})
- 將路由對(duì)象傳遞給Vue的實(shí)例
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
- 在app.vue放置router-view
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view/>
</div>
</template>
Vue的核心要點(diǎn)
1. vue-router傳遞參數(shù)的方式
- 使用name傳遞參數(shù)
在路由文件src/router/index.js配置name屬性
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// 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: "about" */ '../views/About.vue')
}
]
-
通過
<router-link>標(biāo)簽中的to來傳遞參數(shù)基本語(yǔ)法
<router-link :to="{name:xxx,params:{key:value}}">valueString</router-link>使用:
在src/App.vue中添加一下代碼:
<router-link :*to*="{name:'About',params:{username: '李廣義'}}">About</router-link>在About組件中使用$route.params.username進(jìn)行接收
<h2>{{$route.params.username}}</h2>
-
通過url傳遞參數(shù) (在路由配置的時(shí)候以冒號(hào)的形式設(shè)置參數(shù))
const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/about/:urlName', name: 'About', // 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: "about" */ '../views/About.vue') } ]
通過<router-link>來傳值
<router-link to="/about/測(cè)試">About</router-link>
在About組件中通過$route.params.urlName來獲取
<h2>{{$route.params.urlName}}</h2>
單頁(yè)面多路由區(qū)域操作
有時(shí)候一個(gè)頁(yè)面同時(shí)展示多個(gè)視圖,而不是嵌套顯示,比如在寫后臺(tái)管理系統(tǒng)的時(shí)候有側(cè)導(dǎo)航欄和主內(nèi)容區(qū)域兩個(gè)視圖,這時(shí)候就要用命名視圖了,可以在一個(gè)vue頁(yè)面中擁有多個(gè)單獨(dú)命名的視圖(router-view),如果沒有設(shè)置名字,那么name的值為default.
<template>
<div id="app">
<router-link :to="{name:'HelloWord'}">H1</router-link>|
<router-link :to="{name:'H1'}">H2</router-link>|
<router-view />
<router-view name="left" style="float:left;width:50%;background-color:#ccc;height:300px;" />
<router-view
name="right"
style="float:right;width:50%;background-color:yellowgreen;height:300px;"
/>
</div>
</template>
上面的第一個(gè)router-view因?yàn)闆]有設(shè)置name,所以他的默認(rèn)值是default,第二個(gè)router-view的name的值是left,第三個(gè)是right,
當(dāng)點(diǎn)擊第一個(gè)<router-link>的時(shí)候會(huì)根據(jù)HelloWord對(duì)應(yīng)的路由,尋找其對(duì)應(yīng)的組件即下面:
{
path: '/',
name: 'HelloWord',
components: {
default: HelloWorld,
left: H1,
right: H2
}
}
HelloWord組件替換第一個(gè)router-view,H1組件替換name為left的router-view...
Vue-router二級(jí)路由的配置
項(xiàng)目開發(fā)中,組件往往是多層嵌套的,URL中各段的動(dòng)態(tài)路徑也按照某種結(jié)構(gòu)對(duì)應(yīng)嵌套的各層組件
在app.vue中寫入一下代碼
<template>
<div id="app">
<router-link :to="{name:'HelloWord'}">主頁(yè)面</router-link>|
<router-link :to="{name:'H1'}">H1頁(yè)面</router-link>|
<router-link :to="{name:'H2'}">H2頁(yè)面</router-link>
<router-view></router-view>
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
</style>
在router/index.js配置嵌套路由
const routes = [
{
path: '/',
name: 'HelloWord',
component: HelloWorld,
children: [{
path: '/h1',
name: 'H1',
component: H1
},{
path: '/h2',
component: H2,
name: 'H2'
}]
}
]
當(dāng)啟動(dòng)服務(wù)的時(shí)候回默認(rèn)會(huì)加載主頁(yè)面,點(diǎn)擊H1會(huì)去匹配子路由,我個(gè)人的理解是url被路由配置,層層匹配,將匹配到的路由組件渲染出來.
vue-router跳轉(zhuǎn)的方法
<button @click="goToMenu" class="btn btn-success">Let's order!</button>
.....
<script>
export default{
methods:{
goToMenu(){
this.$router.go(-1)//跳轉(zhuǎn)到上一次瀏覽的頁(yè)面
this.$router.replace('/menu')//指定跳轉(zhuǎn)的地址
this.$router.replace({name:'menuLink'})// 指定跳轉(zhuǎn)路由的名字下
this.$router.push('/menu')通過push進(jìn)行跳轉(zhuǎn)
this.$router.push({name:'menuLink'})通過push進(jìn)行跳轉(zhuǎn)路由的名字下
}
}
}
</script>
其中replace和push的區(qū)別是:
push會(huì)留下訪問記錄,會(huì)向history中添加記錄,但是replace不會(huì)添加新的記錄
錯(cuò)誤頁(yè)面的設(shè)置
當(dāng)url輸入錯(cuò)誤的時(shí)候,應(yīng)該友好的給一個(gè)頁(yè)面,這個(gè)頁(yè)面就是404頁(yè)面,可以在路由配置頁(yè)面中這樣配置
{
path: '*',
component: Error
}