路由
前端路由的實現原理
使用Vue-Router實現前端路由
實現嵌套路由,動態路由
實現命名路由以及編程式導航
並實現後臺管理案例javascript
路由的本質就是一種對應關係,好比說咱們在url地址中輸入咱們要訪問的url地址以後,瀏覽器要去請求這個url地址對應的資源。
那麼url地址和真實的資源之間就有一種對應的關係,就是路由。html
路由分爲前端路由和後端路由前端
後端路由性能相對前端路由來講較低,因此,咱們接下來主要學習的是前端路由
前端路由的基本概念:根據不一樣的事件來顯示不一樣的頁面內容,即事件與事件處理函數之間的對應關係
前端路由主要作的事情就是監聽事件並分發執行事件處理函數vue
SPA(Single Page Application)java
前端路由web
後端路由vue-router
前端路由是基於hash值的變化進行實現的(好比點擊頁面中的菜單或者按鈕改變URL的hash值,根據hash值的變化來控制組件的切換)
核心實現依靠一個事件,即監聽hash值變化的事件編程
window.onhashchange = function(){ //location.hash能夠獲取到最新的hash值 location.hash }
前端路由實現tab欄切換:segmentfault
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> <!-- 導入 vue 文件 --> <script src="./lib/vue_2.5.22.js"></script> </head> <body> <!-- 被 vue 實例控制的 div 區域 --> <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> // #region 定義須要被切換的 4 個組件 // 主頁組件 const zhuye = { template: '<h1>主頁信息</h1>' } // 科技組件 const keji = { template: '<h1>科技信息</h1>' } // 財經組件 const caijing = { template: '<h1>財經信息</h1>' } // 娛樂組件 const yule = { template: '<h1>娛樂信息</h1>' } // #endregion // #region vue 實例對象 const vm = new Vue({ el: '#app', data: { comName: 'zhuye' }, // 註冊私有組件 components: { zhuye, keji, caijing, yule } }) // #endregion // 監聽 window 的 onhashchange 事件,根據獲取到的最新的 hash 值,切換要顯示的組件的名稱 window.onhashchange = function() { // 經過 location.hash 獲取到最新的 hash 值 console.log(location.hash); 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> </body> </html>
案例效果圖:後端
點擊每一個超連接以後,會進行相應的內容切換,以下:
核心思路:
在頁面中有一個vue實例對象,vue實例對象中有四個組件,分別是tab欄切換須要顯示的組件內容
在頁面中有四個超連接,以下:
<a href="#/zhuye">主頁</a> <a href="#/keji">科技</a> <a href="#/caijing">財經</a> <a href="#/yule">娛樂</a>
當咱們點擊這些超連接的時候,就會改變url地址中的hash值,當hash值被改變時,就會觸發onhashchange事件
在觸發onhashchange事件的時候,咱們根據hash值來讓不一樣的組件進行顯示:
window.onhashchange = function() { // 經過 location.hash 獲取到最新的 hash 值 console.log(location.hash); switch(location.hash.slice(1)){ case '/zhuye': //經過更改數據comName來指定顯示的組件 //由於 <component :is="comName"></component> ,組件已經綁定了comName vm.comName = 'zhuye' break case '/keji': vm.comName = 'keji' break case '/caijing': vm.comName = 'caijing' break case '/yule': vm.comName = 'yule' break } }
Vue Router
Vue Router官網:地址
Vue.js 官方的路由管理器。
它是一個Vue.js官方提供的路由管理器。是一個功能更增強大的前端路由器,推薦使用。
Vue Router官網:地址
Vue Router和Vue.js很是契合,能夠一塊兒方便的實現SPA(single page web application,單頁應用程序)應用程序的開發。
Vue Router依賴於Vue,因此須要先引入Vue,再引入Vue Router
Vue Router的特性:
A.導入js文件
<script src="lib/vue_2.5.22.js"></script> <script src="lib/vue-router_3.0.2.js"></script>
B.添加路由連接:<router-link>
是路由中提供的標籤,默認會被渲染爲a標籤,to屬性默認被渲染爲href屬性,
to屬性的值會被渲染爲#開頭的hash地址
<router-link to="/user">User</router-link> <router-link to="/login">Login</router-link>
C.添加路由填充位(路由佔位符)
<router-view></router-view>
D.定義路由組件
var User = { template:"<div>This is User</div>" } var Login = { template:"<div>This is Login</div>" }
E.配置路由規則並建立路由實例
var myRouter = new VueRouter({ //routes是路由規則數組 routes:[ //每個路由規則都是一個對象,對象中至少包含path和component兩個屬性 //path表示 路由匹配的hash地址,component表示路由規則對應要展現的組件對象 {path:"/user",component:User}, {path:"/login",component:Login} ] })
F.將路由掛載到Vue實例中
new Vue({ el:"#app", //經過router屬性掛載路由對象 router:myRouter })
小結:
Vue Router的使用步驟仍是比較清晰的,按照步驟一步一步就能完成路由操做
補充:
路由重定向:能夠經過路由重定向爲頁面設置默認展現的組件
在路由規則中添加一條路由規則便可,以下:
var myRouter = new VueRouter({ //routes是路由規則數組 routes: [ //path設置爲/表示頁面最初始的地址 / ,redirect表示要被重定向的新地址,設置爲一個路由便可 { path:"/",redirect:"/user"}, { path: "/user", component: User }, { path: "/login", component: Login } ] })
當咱們進行路由的時候顯示的組件中還有新的子級路由連接以及內容。
嵌套路由最關鍵的代碼在於理解子級路由的概念:
好比咱們有一個/login
的路由
那麼/login
下面還能夠添加子級路由,如:/login/account
/login/phone
<p> <router-link to="/user">User</router-link> <router-link to="/register">Register</router-link> </p> <div> <!-- 控制組件的顯示位置 --> <router-view></router-view> </div>
const Register = { template: `<div> <h1>Register 組件</h1> <hr/> <router-link to="/register/tab1">Tab1</router-link> <router-link to="/register/tab2">Tab2</router-link> <!-- 子路由填充位置 --> <router-view/> </div>` }
const router = new VueRouter({ routes: [ { path: '/user', component: User }, { path: '/register', component: Register, // 經過 children 屬性,爲 /register 添加子路由規則 children: [ { path: '/register/tab1', component: Tab1 }, { path: '/register/tab2', component: Tab2 } ] } ] })
參考代碼以下:
var User = { template: "<div>This is User</div>" } //Login組件中的模板代碼裏面包含了子級路由連接以及子級路由的佔位符 var Login = { template: `<div> <h1>This is Login</h1> <hr> <router-link to="/login/account">帳號密碼登陸</router-link> <router-link to="/login/phone">掃碼登陸</router-link> <!-- 子路由組件將會在router-view中顯示 --> <router-view></router-view> </div>` } //定義兩個子級路由組件 var account = { template:"<div>帳號:<input><br>密碼:<input></div>"}; var phone = { template:"<h1>掃我二維碼</h1>"}; var myRouter = new VueRouter({ //routes是路由規則數組 routes: [ { path:"/",redirect:"/user"}, { path: "/user", component: User }, { path: "/login", component: Login, //經過children屬性爲/login添加子路由規則 children:[ { path: "/login/account", component: account }, { path: "/login/phone", component: phone }, ] } ] }) var vm = new Vue({ el: '#app', data: {}, methods: {}, router:myRouter });
頁面效果大體以下:
var User = { template:"<div>用戶:{{$route.params.id}}</div>"} // 路由組件中經過$route.params獲取路由參數 var myRouter = new VueRouter({ //routes是路由規則數組 routes: [ //經過/:參數名 的形式傳遞參數 { path: "/user/:id", component: User }, ] })
補充:
若是使用$route.params.id
來獲取路徑傳參的數據不夠靈活。
1.咱們能夠經過props來接收參數
var User = { props:["id"], template:"<div>用戶:{{id}}</div>" } var myRouter = new VueRouter({ //routes是路由規則數組 routes: [ //經過/:參數名 的形式傳遞參數 //若是props設置爲true,route.params將會被設置爲組件屬性 { path: "/user/:id", component: User,props:true }, ] })
2.還有一種狀況,咱們能夠將props設置爲對象,那麼就直接將對象的數據傳遞給
組件進行使用
var User = { props:["username","pwd"], template:"<div>用戶:{{username}}---{{pwd}}</div>" } var myRouter = new VueRouter({ //routes是路由規則數組 routes: [ //經過/:參數名 的形式傳遞參數 //若是props設置爲對象,則傳遞的是對象中的數據給組件 { path: "/user/:id", component: User,props:{username:"jack",pwd:123} }, ] })
3.若是想要獲取傳遞的參數值還想要獲取傳遞的對象數據,那麼props應該設置爲
函數形式。
var User = { props:["username","pwd","id"], template:"<div>用戶:{{id}} -> {{username}}---{{pwd}}</div>" } var myRouter = new VueRouter({ //routes是路由規則數組 routes: [ //經過/:參數名 的形式傳遞參數 //若是props設置爲函數,則這個函數接收 route 對象爲本身的形參 //經過函數的第一個參數獲取路由對象 //並能夠經過路由對象的params屬性獲取傳遞的參數 { path: "/user/:id", component: User, props:(route)=>{ return {username:"jack",pwd:123,id:route.params.id} } }, ] })
案例:
var myRouter = new VueRouter({ //routes是路由規則數組 routes: [ //經過name屬性爲路由添加一個別名 { path: "/user/:id", component: User, name:"user"}, ] })
添加了別名以後,可使用別名進行跳轉
<router-link to="/user">User</router-link> <router-link :to="{ name:'user' , params: {id:123} }">User</router-link>
還能夠編程式導航
myRouter.push( { name:'user' , params: {id:123} } )
頁面導航的兩種方式:
A.聲明式導航:經過點擊連接的方式實現的導航
B.編程式導航:調用js的api方法實現導航
Vue-Router中常見的導航方式:
this.$router.push("hash地址"); this.$router.push("/login"); this.$router.push({ name:'user' , params: {id:123} }); this.$router.push({ path:"/login" }); this.$router.push({ path:"/login",query:{username:"jack"} }); this.$router.go( n );//n爲數字,參考history.go this.$router.go( -1 );
案例效果:
點擊左側的"用戶管理","權限管理","商品管理","訂單管理","系統設置"都會出現對應的組件並展現內容
其中"用戶管理"組件展現的效果如上圖所示,在用戶管理區域中的詳情連接也是能夠點擊的,點擊以後將會顯示用戶詳情信息。
案例思路:
1).先將素材文件夾中的11.基於vue-router的案例.html複製到咱們本身的文件夾中。
看一下這個文件中的代碼編寫了一些什麼內容,
這個頁面已經把後臺管理頁面的基本佈局實現了
2).在頁面中引入vue,vue-router
3).建立Vue實例對象,準備開始編寫代碼實現功能
4).但願是經過組件的形式展現頁面的主體內容,而不是寫死頁面結構,因此咱們能夠定義一個根組件:
//只須要把本來頁面中的html代碼設置爲組件中的模板內容便可 const app = { template:`<div> <!-- 頭部區域 --> <header class="header">傳智後臺管理系統</header> <!-- 中間主體區域 --> <div class="main"> <!-- 左側菜單欄 --> <div class="content left"> <ul> <li>用戶管理</li> <li>權限管理</li> <li>商品管理</li> <li>訂單管理</li> <li>系統設置</li> </ul> </div> <!-- 右側內容區域 --> <div class="content right"> <div class="main-content">添加用戶表單</div> </div> </div> <!-- 尾部區域 --> <footer class="footer">版權信息</footer> </div>` }
5).當咱們訪問頁面的時候,默認須要展現剛剛建立的app根組件,咱們能夠
建立一個路由對象來完成這個事情,而後將路由掛載到Vue實例對象中便可
const myRouter = new VueRouter({ routes:[ {path:"/",component:app} ] }) const vm = new Vue({ el:"#app", data:{}, methods:{}, router:myRouter })
補充:到此爲止,基本的js代碼都處理完畢了,咱們還須要設置一個路由佔位符
<body> <div id="app"> <router-view></router-view> </div> </body>
6).此時咱們打開頁面應該就能夠獲得一個VueRouter路由出來的根組件了
咱們須要在這個根組件中繼續路由實現其餘的功能子組件
先讓咱們更改根組件中的模板:更改左側li爲子級路由連接,並在右側內容區域添加子級組件佔位符
const app = { template:`<div> ........ <div class="main"> <!-- 左側菜單欄 --> <div class="content left"> <ul> <!-- 注意:咱們把全部li都修改成了路由連接 --> <li><router-link to="/users">用戶管理</router-link></li> <li><router-link to="/accesses">權限管理</router-link></li> <li><router-link to="/goods">商品管理</router-link></li> <li><router-link to="/orders">訂單管理</router-link></li> <li><router-link to="/systems">系統設置</router-link></li> </ul> </div> <!-- 右側內容區域 --> <div class="content right"> <div class="main-content"> <!-- 在 --> <router-view></router-view> </div> </div> </div> ....... </div>` }
而後,咱們要爲子級路由建立並設置須要顯示的子級組件
//建議建立的組件首字母大寫,和其餘內容區分 const Users = {template:`<div> <h3>用戶管理</h3> </div>`} const Access = {template:`<div> <h3>權限管理</h3> </div>`} const Goods = {template:`<div> <h3>商品管理</h3> </div>`} const Orders = {template:`<div> <h3>訂單管理</h3> </div>`} const Systems = {template:`<div> <h3>系統管理</h3> </div>`} //添加子組件的路由規則 const myRouter = new VueRouter({ routes:[ {path:"/",component:app , children:[ { path:"/users",component:Users }, { path:"/accesses",component:Access }, { path:"/goods",component:Goods }, { path:"/orders",component:Orders }, { path:"/systems",component:Systems }, ]} ] }) const vm = new Vue({ el:"#app", data:{}, methods:{}, router:myRouter })
7).展現用戶信息列表:
A.爲Users組件添加私有數據,並在模板中循環展現私有數據
const Users = { data(){ return { userList:[ {id:1,name:"zs",age:18}, {id:2,name:"ls",age:19}, {id:3,name:"wang",age:20}, {id:4,name:"jack",age:21}, ] } }, template:`<div> <h3>用戶管理</h3> <table> <thead> <tr> <th>編號</th> <th>姓名</th> <th>年齡</th> <th>操做</th> </tr> </thead> <tbody> <tr :key="item.id" v-for="item in userList"> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.age}}</td> <td><a href="javascript:;">詳情</a></td> </tr> </tbody> </table> </div>`}
8.當用戶列表展現完畢以後,咱們能夠點擊列表中的詳情來顯示用戶詳情信息,首先咱們須要建立一個組件,用來展現詳情信息
const UserInfo = { props:["id"], template:`<div> <h5>用戶詳情</h5> <p>查看 {{id}} 號用戶信息</p> <button @click="goBack">返回用戶詳情頁</button> </div> `, methods:{ goBack(){ //當用戶點擊按鈕,後退一頁 this.$router.go(-1); } } }
而後咱們須要設置這個組件的路由規則
const myRouter = new VueRouter({ routes:[ {path:"/",component:app , children:[ { path:"/users",component:Users }, //添加一個/userinfo的路由規則 { path:"/userinfo/:id",component:UserInfo,props:true}, { path:"/accesses",component:Access }, { path:"/goods",component:Goods }, { path:"/orders",component:Orders }, { path:"/systems",component:Systems }, ]} ] }) const vm = new Vue({ el:"#app", data:{}, methods:{}, router:myRouter })
再接着給用戶列表中的詳情a鏈接添加事件
const Users = { data(){ return { userList:[ {id:1,name:"zs",age:18}, {id:2,name:"ls",age:19}, {id:3,name:"wang",age:20}, {id:4,name:"jack",age:21}, ] } }, template:`<div> <h3>用戶管理</h3> <table> <thead> <tr> <th>編號</th> <th>姓名</th> <th>年齡</th> <th>操做</th> </tr> </thead> <tbody> <tr :key="item.id" v-for="item in userList"> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.age}}</td> <td><a href="javascript:;" @click="goDetail(item.id)">詳情</a></td> </tr> </tbody> </table> </div>`, methods:{ goDetail(id){ this.$router.push("/userinfo/"+id); } } }
this.$router 至關於一個全局的路由器對象,包含了不少屬性和對象(好比 history 對象),任何頁面均可以調用其 push(), replace(), go() 等方法。
this.$route 表示當前路由對象,每個路由都會有一個 route 對象,是一個局部的對象,能夠獲取對應的 name, path, params, query 等屬性。