Vue前端路由
七、Vue前端路由
1. 路由的基本概念與原理
路由是一個比較廣義和抽象的概念,路由的本質就是對應關係。
後端路由
- 概念:根據不同的用戶URL請求,返回不同的內容
- 本質:URL請求地址與服務器資源之間的對應關係
在早期的web開發中一般均採用後端路由的形式
- 後端渲染(存在性能問題)
- Ajax前端渲染(前端渲染提高性能,但是不支持瀏覽器的前進後退操作)
- SPA單頁面應用程序:整個網站只有一個頁面,內容的變化通過Ajax局部更新實現,同時支持瀏覽器地址的前進和後退操作
- SPA原理之一:基於URL地址的hash(hash的變化會導致瀏覽器記錄訪問歷史的變化,但是hash的變化不會觸發新的URL請求)
- 在實現SPA過程中,最核心的技術點就是前端路由
前端路由
- 概念:根據不同的用戶事件,顯示不同的頁面內容。
- 本質:用戶事件與時間處理函數之間的對應關係。
實現簡單的前端路由
demo
<div id="app">
<!-- 切換組件的超鏈接 -->
<a href="#/zhuye">主頁</a>
<a href="#/keji">科技</a>
<a href="#/caijing">財經</a>
<a href="#/yule">娛樂</a>
<!-- 根據 :is 屬性指定的組件名稱,把對應的組件渲染到 component 標籤所在的位置 -->
<!-- 可以把 component 標籤當做是【組件的佔位符】 -->
<component :is="comName"></component>
</div>
<script>
//定義4個組件
const zhuye = {
template:'<h1>主頁信息</h1>'
}
const keji = {
template:'<h1>科技信息</h1>'
}
const caijing = {
template:'<h1>財經信息</h1>'
}
const yule = {
template:'<h1>娛樂信息</h1>'
}
var vm = new Vue({
el:"#app",
data:{
comName:'zhuye'
},
components:{
zhuye,
keji,
caijing,
yule,
}
})
// 監聽 window 的 onhashchange 事件,根據獲取到的最新的 hash 值,切換要顯示的組件的名稱
window.onhashchange=function () {
switch (location.hash.slice(1)) {
case '/zhuye':
vm.comName = 'zhuye'
break
case '/keji':
vm.comName = 'keji'
break
case '/caijing':
vm.comName = 'caijing'
break
case '/yule':
vm.comName = 'yule'
break
}
}
</script>
vue-router基本概念
vue-router是vue.js官方的路由管理器
它和vue.js的核心深度集成,可以非常方便的用於SPA應用程序的開發
vue-router包含的功能有
- 支持HTML5歷史模式或hash模式(常見)
- 支持嵌套路由
- 支持路由參數
- 支持編程式路由
- 支持命名路由
2. vue-router的基本使用
基本使用步驟
- 引入庫文件
//注意順序vue-router依賴vue
<script src="vue.js"></script>
<script src="vue-router.js"></script>
- 添加路由鏈接
<!-- 使用 router-link 組件來導航. -->
<!-- 通過傳入 `to` 屬性指定鏈接.會被渲染爲href屬性 -->
<!-- `to`屬性的值會被渲染爲#開頭的hash地址 -->
<!-- <router-link> 默認會被渲染成一個 `<a>` 標籤 -->
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
- 添加路由填充位
<!-- 路由填充位(也叫作路由佔位符)路由出口 -->
<!-- 路由匹配到的組件將渲染在這裏 -->
<router-view></router-view>
- 定義路由組件
const User ={
template:'<h1>User 組件</h1>'
}
const Register ={
template:'<h1>Register 組件</h1>'
}
- 配置路由規則並創建路由實例
//創建路由實例對象
var router = new VueRouter({
//router 是路由規則數組
routes:[
//每個路由規則都是一個配置對象,其中至少包含path和component兩個屬性
//path表示當前路由規則匹配的hash地址
//component表示當前路由規則對應要展示的組件
{path:'/user',component:User},
{path:'/register',component:Register}
]
})
- 把路由掛載到Vue實例中
var vm = new Vue({
el:"#app",
data:{
},
//掛載路由實例對象,es6中屬性和值相同可以簡寫成一個;
//router:router,
router,
})
完整demo
<script src="vue.js"></script>
<script src="vue-router.js"></script>
<div id="app">
<h1>Hello App!</h1>
<p>
<!-- 使用 router-link 組件來導航. -->
<!-- 通過傳入 `to` 屬性指定鏈接.會被渲染爲href屬性 -->
<!-- `to`屬性的值會被渲染爲#開頭的hash地址 -->
<!-- <router-link> 默認會被渲染成一個 `<a>` 標籤 -->
<router-link to="/user">Go to User</router-link>
<router-link to="/register">Go to Register</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的組件將渲染在這裏 -->
<router-view></router-view>
</div>
<script>
const User ={
template:'<h1>User 組件</h1>'
}
const Register ={
template:'<h1>Register 組件</h1>'
}
//創建路由實例對象
var router = new VueRouter({
//router 是路由規則數組
routes:[
//每個路由規則都是一個配置對象,其中至少包含path和component兩個屬性
//path表示當前路由規則匹配的hash地址
//component表示當前路由規則對應要展示的組件
{path:'/user',component:User},
{path:'/register',component:Register}
]
})
var vm = new Vue({
el:"#app",
data:{
},
component:{
User,
Register
},
//掛載路由實例對象,es6中屬性和值相同可以簡寫成一個;
//router:router,
router,
})
</script>
路由重定向
路由重定向指的是:用戶訪問地址A的時候,強制用戶跳轉到地址C,從而顯示特定的組件頁面
通過路由規則的redirect屬性,指定一個新的路由地址,可以很方便的設置路由的重定向
//router對象中router數組中添以下規則
//其中,path表示需要被重定向的原地址,redirect表示要被重定向的新地址
{path: '/',redirect:'/user'},
3. vue-router嵌套路由
嵌套路由功能分析
- 點擊父級路由鏈接顯示模板內容
- 模板內容中又有子級路由鏈接
- 點擊子級路由鏈接顯示子級模板內容
實例demo
在組件register的template中添加router-link等
在router中register路由規則中添加children子路由規則
<script src="vue.js"></script>
<script src="vue-router.js"></script>
<div id="app">
<h1>Hello App!</h1>
<p>
<!-- 使用 router-link 組件來導航. -->
<!-- 通過傳入 `to` 屬性指定鏈接.會被渲染爲href屬性 -->
<!-- `to`屬性的值會被渲染爲#開頭的hash地址 -->
<!-- <router-link> 默認會被渲染成一個 `<a>` 標籤 -->
<router-link to="/user">Go to User</router-link>
<router-link to="/register">Go to Register</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的組件將渲染在這裏 -->
<router-view></router-view>
</div>
<script>
const User ={
template:'<h1>User 組件</h1>'
}
const Register ={
template:`
<div>
<h1>Register 組件</h1>
<router-link to="/register/tab1">Go to tab1</router-link>
<router-link to="/register/tab2">Go to tab2</router-link>
<router-view></router-view>
</div>
`
}
const tab1={
template:'<h2>tab1</h2>'
}
const tab2={
template:'<h2>tab2</h2>'
}
//創建路由實例對象
var router = new VueRouter({
//router 是路由規則數組
routes:[
//每個路由規則都是一個配置對象,其中至少包含path和component兩個屬性
//path表示當前路由規則匹配的hash地址
//component表示當前路由規則對應要展示的組件
{path: '/',redirect:'/user'},
{path:'/user',component:User},
//children數組表示子路由規則
{path:'/register',component:Register,children:[
{path:'/register/tab1',component:tab1},
{path:'/register/tab2',component:tab2}
]},
]
})
var vm = new Vue({
el:"#app",
data:{
},
component:{
User,
Register
},
//掛載路由實例對象,es6中屬性和值相同可以簡寫成一個;
//router:router,
router,
})
4. vue-router動態路由匹配
通過動態路由參數的模式進行路由匹配
//創建路由實例對象
var router = new VueRouter({
routes:[
//動態路徑參數 以冒號開頭
{path:'/user/:id',component:User},
]
})
const User ={
//路由組件中通過$route.params獲取路由參數
template:'<h1>User 組件{{$route.params.id}}</h1>'
}
demo
<script src="vue.js"></script>
<script src="vue-router.js"></script>
<div id="app">
<h1>Hello App!</h1>
<p>
<router-link to="/user/1">Go to User1</router-link>
<router-link to="/user/10">Go to User2</router-link>
<router-link to="/register">Go to Register</router-link>
</p>
<router-view></router-view>
</div>
<script>
const User ={
//路由組件中通過$route.params獲取路由參數
template:'<h1>User 組件{{$route.params.id}}</h1>'
}
const Register ={
template:'<h1>Register 組件</h1>'
}
//創建路由實例對象
var router = new VueRouter({
routes:[
{path: '/',redirect:'/user'},
{path:'/user/:id',component:User},
{path:'/register',component:Register},
]
})
var vm = new Vue({
el:"#app",
data:{
},
component:{
User,
Register
},
//掛載路由實例對象,es6中屬性和值相同可以簡寫成一個;
//router:router,
router,
})
</script>
路由組件傳遞參數
$route與對應路由形成高度耦合,不夠靈活,所以可以使用props將組件和路由耦合
- props的值爲布爾類型
var router = new VueRouter({
routes:[
//如果props被設置爲true,參數將會被設置爲組件屬性
{path:'/user/:id',component:User,props:true},
]
})
const User ={
props: ['id'],//使用props接收路由參數
template:'<h1>User 組件{{id}}</h1>'
}
demo
<div id="app">
<h1>Hello App!</h1>
<p>
<router-link to="/user/1">Go to User1</router-link>
<router-link to="/user/10">Go to User2</router-link>
<router-link to="/register">Go to Register</router-link>
</p>
<router-view></router-view>
</div>
<script>
const User ={
props: ['id'],//使用props接收路由參數
template:'<h1>User 組件{{id}}</h1>'
}
const Register ={
template:'<h1>Register 組件</h1>'
}
//創建路由實例對象
var router = new VueRouter({
routes:[
{path: '/',redirect:'/user'},
//如果props被設置爲true,參數將會被設置爲組件屬性
{path:'/user/:id',component:User,props:true},
{path:'/register',component:Register},
]
})
var vm = new Vue({
el:"#app",
data:{
},
component:{
User,
Register
},
//掛載路由實例對象,es6中屬性和值相同可以簡寫成一個;
//router:router,
router,
})
</script>
- props的值爲對象類型
此時props接收就接收不到id了,可以使用第一種$route.params.id訪問
//如果props被設置爲一個對象,它會被按原樣設置爲組件屬性
{path:'/user/:id',component:User,props:{name:'莫逸風',age:22}},
const User ={
props: ['name','age'],//使用props接收路由參數
template:'<h1>User 組件{{name+age+$route.params.id}}</h1>'
}
- props的值爲函數類型
//如果props是一個函數,則這個函數接收route對象爲自己的形參
{path:'/user/:id',component:User,props:route=>({name:'莫逸風',age:22,id:route.params.id})},
const User ={
props: ['name','age','id'],//使用props接收路由參數
template:'<h1>User 組件{{name+age+id}}</h1>'
}
demo
<div id="app">
<h1>Hello App!</h1>
<p>
<router-link to="/user/1">Go to User1</router-link>
<router-link to="/user/10">Go to User2</router-link>
<router-link to="/register">Go to Register</router-link>
</p>
<router-view></router-view>
</div>
<script>
const User ={
props: ['name','age','id'],//使用props接收路由參數
template:'<h1>User 組件{{name+age+id}}</h1>'
}
const Register ={
template:'<h1>Register 組件</h1>'
}
//創建路由實例對象
var router = new VueRouter({
routes:[
{path: '/',redirect:'/user'},
//如果props被設置爲一個對象,它會被按原樣設置爲組件屬性
{path:'/user/:id',component:User,props:route=>({name:'莫逸風',age:22,id:route.params.id})},
{path:'/register',component:Register},
]
})
var vm = new Vue({
el:"#app",
data:{
},
component:{
User,
Register
},
//掛載路由實例對象,es6中屬性和值相同可以簡寫成一個;
//router:router,
router,
})
</script>
5. vue-router命名路由
爲了更加方便的表示路由的路徑,可以給路由規則起一個別名,即爲“命名路由”
{path:'/user/:id',name:'user',component:User,props:route=>({name:'莫逸風',age:22,id:route.params.id})},
<router-link :to="{name:'user',params:{id:1}}">Go to User1</router-link>
demo
<div id="app">
<h1>Hello App!</h1>
<p>
<router-link :to="{name:'user',params:{id:1}}">Go to User1</router-link>
<router-link to="/user/2">Go to User2</router-link>
<router-link to="/register">Go to Register</router-link>
</p>
<router-view></router-view>
</div>
<script>
const User ={
props: ['id'],
//路由組件中通過$route.params獲取路由參數
template:'<h1>User 組件{{id}}</h1>'
}
const Register ={
template:'<h1>Register 組件</h1>'
}
//創建路由實例對象
var router = new VueRouter({
routes:[
{path: '/',redirect:'/user'},
//命名路由
{path:'/user/:id',name:'user',component:User,props:route=>({name:'莫逸風',age:22,id:route.params.id})},
{path:'/register',component:Register},
]
})
var vm = new Vue({
el:"#app",
data:{
},
component:{
User,
Register
},
//掛載路由實例對象,es6中屬性和值相同可以簡寫成一個;
//router:router,
router,
})
</script>
6. vue-router編程式導航
- 聲明式導航:通過點擊鏈接實現導航的方式,叫做聲明式導航
- 例如:普通網頁中
<a></a>
鏈接或vue中的<router-link></router-link>
- 例如:普通網頁中
- 編程式導航:通過調用JavaScript形式的API實現導航的方式,叫做編程式導航
- 例如:普通網頁中的location.href
常用的編程式導航API如下:
this.$router.push('hash地址')
this.$router.go(n)//實現前進或後對
demo
<script src="vue.js"></script>
<script src="vue-router.js"></script>
<div id="app">
<h1>Hello App!</h1>
<router-link to="/user">Go to User</router-link>
<router-link to="/register">Go to Register</router-link>
<router-view></router-view>
</div>
<script>
const User ={
template:`
<div>
<h1>User 組件</h1>
<button @click="handel">跳轉</button>
</div>
`,
methods:{
handel:function () {
this.$router.push('/register')
}
}
}
const Register ={
template:`
<div>
<h1>Register 組件</h1>
<button @click="handel">後退</button>
</div>
`,
methods:{
handel:function () {
this.$router.go(-1);
}
}
}
var router = new VueRouter({
routes:[
{path:'/register',component:Register},
{path:'/user',component:User},
]
})
var vm = new Vue({
el:"#app",
data:{
},
component:{
User
},
//掛載路由實例對象,es6中屬性和值相同可以簡寫成一個;
//router:router,
router,
})
</script>
router.push()方法的參數規則
//字符串(路徑名稱)
router.push('/home')
//對象
router.push({path:'/home'})
//命名的路由(傳遞參數)
router.push({name:'/user',params:{userId:123}})
//帶查詢參數,編程/register?name=lisi
router.push({path:'/register',query:{name:'lisi'}})
.$router.go(-1);
}
}
}
var router = new VueRouter({
routes:[
{path:’/register’,component:Register},
{path:’/user’,component:User},
]
})
var vm = new Vue({
el:"#app",
data:{
},
component:{
User
},
//掛載路由實例對象,es6中屬性和值相同可以簡寫成一個;
//router:router,
router,
})
```
router.push()方法的參數規則
//字符串(路徑名稱)
router.push('/home')
//對象
router.push({path:'/home'})
//命名的路由(傳遞參數)
router.push({name:'/user',params:{userId:123}})
//帶查詢參數,編程/register?name=lisi
router.push({path:'/register',query:{name:'lisi'}})