Vue全家桶--10 Vue-Router路由
Vue全家桶--10 Vue-Router路由
10.1 什麼是路由
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度整合,讓構建單頁面應用變得非常簡單。
通過根據不同的請求路徑,切換顯示不同元件進行渲染頁面。
10.2 基本路由使用
10.2.1 安裝路由
npm install vue-router
10.2.2引入 vue-router.js
<script src="./node_modules/vue/dist/vue.js"></script> <script src="./node_modules/vue-router/dist/vue-router.js"></script>
10.2.3HTML 路由切換
<div id="app"> <div class="header"> <h1>header</h1> </div> <div class="left"> <ul> <!-- 方式1:傳統方式! --> <li><a href="#/foo">foo</a></li> <li><a href="#/bar">bar</a></li> <!-- 方式2:官方推薦! --> <!-- <router-link> 預設會被渲染成一個 `<a>` 標籤, --> <!-- 通過傳入 `to` 屬性指定跳轉連結,不用像上面加 `#` 號 --> <li><router-linkto="/foo">Go to Foo</router-link></li> <li><router-link to="/bar">Go to Bar</router-link></li> </ul> </div> <div class="main"> <!-- 路由出口: 路由匹配到的元件將渲染在這裡 --> <router-view></router-view> </div> </div>
10.2.4JS 配置路由
<script src="./node_modules/vue/dist/vue.js"></script> <script src="./node_modules/vue-router/dist/vue-router.js"></script> <script> //1.定義元件 const Foo = { template:`<div>hello Foo</div>` }; const Bar ={ template:`<div>hello Bar</div>` } // 2. 配置路由表:當點選特定的 url 時,顯示對應的那個元件。 const router = new VueRouter({ routes:[ //配置每個路由對映一個元件 {path:'/foo',component:Foo}, {path:'/bar',component:Bar} ] }); // 3. 注入路由到例項中 new Vue({ el:'#app', router //router:router }); </script>
10.3 路由案例實戰
10.3.1 修改模板
安裝路由/axios
npm install vue-router
npm install axios
10.3.2 News元件
**js函式自呼叫 ;(function(){})()
**windows 全域性屬性 window.News={} ,這樣就可以全域性呼叫元件,否則在該作用域內,外面無法呼叫到
;(function(){ // const template=`<!--右邊主頁面區域--> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <div class="header clearfix"> <nav> <ul class="nav nav-pills"> <li class="active"><a href="#">體育</a></li> <li ><a href="#">科技</a></li> </ul> </nav> <hr> </div> <!--體育欄目--> <div> <ul> <li> <a href="#">世界盃開賽啦</a> </li> <li> <a href="#">NBA開賽倒計時</a> </li> </ul> <!--詳情--> <div class="jumbotron"> <h2>世界盃開賽啦</h2> <p>世界盃於明晚8點舉行開幕式.....</p> </div> </div> <!--科技欄目--> <div> <ul > <li> <span>5G時代到來了 </span> <button class="btn btn-default btn-xs">檢視(Push)</button> <button class="btn btn-default btn-xs">檢視(replace)</button> </li> <li> <span>網際網路大洗牌</span> <button class="btn btn-default btn-xs">檢視(Push)</button> <button class="btn btn-default btn-xs">檢視(replace)</button> </li> </ul> <!--詳情--> <div class="jumbotron"> <h2>世界盃開賽啦</h2> <p>世界盃於明晚8點舉行開幕式.....</p> </div> </div> </div>`; window.News={ template } })()
10.3.3 About元件
; (function () { const template = `<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <h1>夢學谷-陪你學習,伴你夢想!</h1> <input /> </div>`; window.About={ template } })()
10.3.4 配置路由
新建router.js檔案
; (function () { window.router = new VueRouter({ linkActiveClass: 'active', routes: [ { path: '/', component: AppHome }, { path: '/news', component: News }, { path: '/about', component: About } ] }) })()
10.3.5 注入路由到例項中
在 main.js 中的 Vue 例項中引入 router
var vm = new Vue({ el: '#app', // Vue例項中的template選項中引用了元件後,會將這個元件的渲染結果替換掉 #app 標籤的元素 // template: '<app> </app>', template:'<app></app>', router, // 引用路由配置 components:{ App, } });
10.3.6 配置路由渲染元件出口
在 App.js 中配置
; (function () { // 元件模板中,必須包含有且只有一個根元素 const template = ` <div> <!--頭部導航區域--> <app-navbar></app-navbar> <!--核心區域:分左右兩邊--> <div class="container-fluid"> <div class="row"> <!--左邊選單欄區域--> <app-left></app-left> <!--右邊主頁面區域: 分上下兩個區域 <app-home> <h1 slot="dashboard" class="page-header">{{title}}</h1> </app-home> --> <!-- 配置路由渲染元件出口,也就是右邊主頁面區域 --> <router-view> <h1 slot="dashboard" class="page-header">{{title}}</h1> </router-view> </div> </div> </div> `; window.App = { template, components: { AppNavbar, AppLeft, AppHome }, data() { return { title: '儀表盤', }; }, } })()
10.3.7 修改跳轉連結
在 AppLeft.js 中修改跳轉連結
; (function () { window.AppLeaf = { template: `<div class="col-sm-3 col-md-2 sidebar"> <ul class="nav nav-sidebar"> <li class="active"> <router-link to="/">首頁</router-link> </li> <li> <router-link to="/news">新聞管理</router-link> </li> <li> <router-link to="/about">關於我們</router-link> </li> </ul> </div>` } })()
10.3.8 引入js檔案
注意先後順序
<script src="../node_modules/vue/dist/vue.js"></script>
<!-- vue-router.js要引入在 vue.js 下方--->
<script src="../node_modules/vue-router/dist/vue-router.js"></script> <script src="../node_modules/axios/dist/axios.js"></script> <script src="./components/AppNavbar.js"></script> <script src="./components/AppLeft.js"></script> <script src="./components/Home/DashBoard.js"></script> <script src="./components/Item.js"></script> <script src="./components/Home/HomeList.js"></script> <script src="./components/Home/AppHome.js"></script> <script src="./components/Home/News.js"></script> <script src="./components/Home/About.js"></script> <script src="./router.js"></script> <script src="./App.js"></script> <script src="./main.js"></script>
10.3.9 啟動測試
http://127.0.0.1:5500/vue-08-router/02-bootstrap-ajax-router/index.html#/
10.4 樣式匹配--高亮顯示導航
10.4.1 tag
<router-link> 預設渲染後生成 <a> 標籤。
可在 <router-link> 上使用 tag 屬性,指定渲染後生成其他標籤。
10.4.2 active-class
<router-link> 渲染後生成標籤上預設有 CSS 類名: router-link-active 。
可在 <router-link> 上使用 active-class 屬性,指定渲染後生成其他類名。
可以通過路由的構造選項 linkActiveClass 來全域性配置,不用在每個<router-link> 使用 active-class 指定生成
的類名
10.4.3 exact
預設情況 下,路由地址 / 、/foo 、/bar 都以 / 開頭,它們都會去匹配 / 地址的 CSS 類名。
可在 <router-link> 上使用 exact 屬性開啟 CSS 類名精確匹配。
<!-- 這個連結只會在地址為 / 的時候被啟用, --> <router-link to="/" exact>
10.4.4 實現高亮顯示導航連結
AppLeft.js
;(function(){ const template=`<div class="col-sm-3 col-md-2 sidebar"> <ul class="nav nav-sidebar"> <!-- router-link 預設渲染出來的是 a 標籤, 如果需要讓它渲染出來的 是別的標籤,則可以使用 tag 屬性指定渲染後的標籤 2. 可以在每個 router-link 上使用 active-class 來啟用 CSS 類名 或者在 VueRouter 例項中,使用 linkActiveClass 全域性配置 CSS 類名 3. exact 是精確匹配, 指定在哪個標籤上,則這個標籤的路徑就不會被其他路徑模糊匹配 --> <router-link to="/" tag="li" exact><a>首頁</a></router-link> <router-link to="/news" tag="li"><a>新聞管理</a></router-link> <router-link to="/about" tag="li"><a>關於我們</a></router-link> </ul> </div>`; window.AppLeft={ template } })()
router.js
; (function () { window.router = new VueRouter({ // 全域性配置 router-link 標籤生成的 CSS 類名 linkActiveClass: 'active', routes: [ { path: '/', component: AppHome }, { path: '/news', component: News }, { path: '/about', component: About } ] }) })()
10.5 巢狀路由
10.5.1 子路由元件
10.5.2 配置巢狀路由
{ path: '/news', component: News, children: [ // 當匹配到 /news/sport 請求時, // 元件 Sport 會被渲染在 News 元件中的 <router-view> 中 { path: '/news/sport', component: Sport }, // 簡寫方式,等價於 /news/tech 路徑,注意前面沒有 / ,有 / 就是根目錄了 { path: 'tech', component: Tech }, //點選新聞管理預設選中 新聞, // 就是/news後面沒有子路徑時, redirect 重定向到 體育 { path: '', redirect: '/news/sport' } ] },
10.5.3 路由跳轉連結
<ul class="nav nav-pills"> <router-link to="/news/sport" tag="li"> <a >體育</a> </router-link> <router-link to="/news/tech" tag="li"> <a >科技</a> </router-link> </ul> <!--定義路由出口--> <router-view></router-view>
10.6 巢狀路由案例--新聞管理
10.6.1 封裝路由需要的元件 New元件中的Sport和Tech
Sport.js
; (function () { // const template = ` <div> <ul> <li v-for="(sport,index) in sportArr" :key="sport.id"> <a href="#" >{{ sport.title }}</a> </li> </ul> <!--詳情--> <div class="jumbotron"> <h2>世界盃開賽啦</h2> <p>世界盃於明晚8點舉行開幕式.....</p> </div> </div> `; window.Sport = { template, data() { return { sportArr: [], }; }, created() { this.getSportArr(); }, methods:{ getSportArr(){ axios.get('http://127.0.0.1:5500/vue-08-router/02-bootstrap-ajax-router/db/sport.json').then(response => { console.log(response.data) // 得到返回結果資料 this.sportArr = response.data }).catch(error => { console.log(error.message) }) } } } })()
Tech.js
; (function () { // const template = ` <div> <ul > <li v-for="(tech, index) in techArr" :key="tech.id"> <span> {{tech.title}} </span> <button class="btn btn-default btn-xs">檢視(Push)</button> <button class="btn btn-default btn-xs">檢視(replace)</button> </li> </ul> <!--詳情--> <div class="jumbotron"> <h2>世界盃開賽啦</h2> <p>世界盃於明晚8點舉行開幕式.....</p> </div> </div> `; window.Tech = { template, data() { return { techArr: [], }; }, created() { this.getTechArr(); }, methods: { getTechArr() { axios.get('http://127.0.0.1:5500/vue-08-router/02-bootstrap-ajax-router/db/tech.json').then(response => { console.log(response.data) // 得到返回結果資料 this.techArr = response.data }).catch(error => { console.log(error.message) }) } } } })()
10.6.2 配置巢狀路由
; (function () { window.router = new VueRouter({ // 全域性配置 router-link 標籤生成的 CSS 類名 linkActiveClass: 'active', routes: [ { path: '/', component: AppHome }, { path: '/news', component: News, children: [ { path: '/news/sport', component: Sport }, { // 簡寫方式,等價於 /news/tech 路徑,注意前面沒有 / ,有 / 就是根目錄了 path: 'tech', component: Tech }, { //點選新聞管理預設選中 新聞, //就是/news後面沒有子路徑時, redirect 重定向到 體育 path: '', redirect: '/news/sport' } ] }, { path: '/about', component: About } ] }) })()
10.6.3跳轉連結和路由渲染出口
;(function(){ // const template=`<!--右邊主頁面區域--> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <div class="header clearfix"> <nav> <ul class="nav nav-pills"> <router-link to="/news/sport" tag="li" exact><a>體育</a></router-link> <router-link to="/news/tech" tag="li" exact><a>科技</a></router-link> </ul> </nav> <hr> </div> <!--定義路由出口--> <router-view></router-view> </div>`; window.News={ template } })()
10.6.4 引入JS
<script src="./components/Home/Sport.js"></script> <script src="./components/Home/Tech.js"></script>
10.7 快取路由元件與案例
10.7.1 場景與作用
1. 預設情況下,當路由元件被切換後元件例項會銷燬,當切換回來時例項會重新建立。
2. 如果可以快取路由元件例項,切換後不用重新載入資料,可以提高使用者體驗。
10.7.2 實現快取路由元件
<keep-alive> 可快取渲染的路由元件例項
<keep-alive> <router-view></router-view> </keep-alive>
10.7.3 demo
上訴的demo中在App.js中新增快取路由元件
<!-- 配置路由渲染元件出口,也就是右邊主頁面區域 --> <keep-alive> <router-view> <h1 slot="dashboard" class="page-header">{{title}}</h1> </router-view> </keep-alive>
10.8 路由元件傳遞資料
10.8.1 路由傳遞資料步驟
(1)路由配置
{ path: '/news/sport', component: Sport, children: [ { path: '/news/sport/detail/:id', // :id 路徑變數佔位符 component: SportDetail } ] }
(2)路由跳轉路徑
<!-- 要動態拼接值, 則 to 屬性值是 JS 表示式, 要寫 JS 表示式, 則要使用 v-bind 方式繫結屬性 注意 + 前面有單引號 '' --> <router-link :to="'/news/sport/detail/' + sport.id"> {{sport.title}} </router-link>
(3)在路由元件中讀取請求引數
this.$route.params.id
10.8.2 DEMO
配置路由
; (function () { window.router = new VueRouter({ // 全域性配置 router-link 標籤生成的 CSS 類名 linkActiveClass: 'active', routes: [ { path: '/', component: AppHome }, { path: '/news', component: News, children: [ { path: '/news/sport', component: Sport, children: [ // :id 路徑變數佔位符 { path: '/news/sport/detail/:id', component: SportDetail } ] }, { // 簡寫方式,等價於 /news/tech 路徑,注意前面沒有 / ,有 / 就是根目錄了 path: 'tech', component: Tech, children:[ {path: '/news/tech/detail/:id', component: TechDetail } ] }, { //點選新聞管理預設選中 新聞, //就是/news後面沒有子路徑時, redirect 重定向到 體育 path: '', redirect: '/news/sport' } ] }, { path: '/about', component: About } ] }) })()
元件指定路徑和渲染出口
; (function () { // const template = ` <div> <ul> <li v-for="(sport,index) in sportArr" :key="sport.id"> <router-link :to="'/news/sport/detail/'+ sport.id" > {{sport.title}} </router-link> </li> </ul> <!--詳情--> <!--定義路由出口--> <router-view></router-view> </div> `; window.Sport = { template, data() { return { sportArr: [], }; }, created() { this.getSportArr(); }, methods:{ getSportArr(){ axios.get('http://127.0.0.1:5500/vue-08-router/02-bootstrap-ajax-router/db/sport.json').then(response => { console.log(response.data) // 得到返回結果資料 this.sportArr = response.data }).catch(error => { console.log(error.message) }) } } } })()
詳情元件
; (function () { const template = ` <div class="jumbotron"> <h2>{{ sportDetail.title }}</h2> <p>{{ sportDetail.content }}</p> </div> `; window.SportDetail = { template, data() { return { id: null, sportDetail: {} }; }, created() { // 注意: // 1. 是 $route , 最後沒有 r 字母 // 2. created 鉤子只會呼叫1次,當切換標題列表的路由時,此鉤子不會再次呼叫, // 所以對應 ID 不會被更新, 可以使用 watch 監聽 $route 路由的變化。 this.getItemById(); }, methods: { getItemById() { //將路由路徑的變數賦值給本地變數 this.id = this.$route.params.id - 0; var sportItem = []; axios.get('http://127.0.0.1:5500/vue-08-router/02-bootstrap-ajax-router/db/sport.json').then(response => { //console.log(response.data) // 得到返回結果資料 sportItem = response.data; this.sportDetail = sportItem.find(arr => { return arr.id == this.id; }) console.log(this.sportDetail); }).catch(error => { console.log(error.message); }) } }, watch: { // watch 是物件,用於監聽屬性使用 // 使用 watch 監聽 $route 路由的變化,獲取 ID 值 '$route': function () { //console.log('$route'); if ((this.$route.params.id - 0) > 0) { //判斷是否是詳情頁路由 this.getItemById() } } } } })()
10.9 程式設計式路由導航
10.9.1宣告式與程式設計式路由
**宣告式( 直接通過 <a> 標籤href指定連結跳轉)
<router-link :to="...">
**程式設計式(採用 js 程式碼連結跳轉,如 localhost.href)
router.push(...)
10.9.2程式設計式路由導航 API
this.$router.push(path) 相當於點選路由連結(後退1步,會返回當前路由介面) this.$router.replace(path) 用新路由替換當前路由(後退1步,不可返回到當前路由介面) this.$router.back() 後退回上一個記錄路由 this.$router.go(n) 引數 n 指定步數 this.$router.go(-1) 後退回上一個記錄路由 this.$router.go(1) 向前進下一個記錄路由You are never too old to set another goal or to dream a new dream!!!