VueRouter爬坑第三篇-巢狀路由
VueRouter系列的文章示例編寫時,專案是使用vue-cli腳手架搭建。
專案搭建的步驟和專案目錄專門寫了一篇文章:點選這裡進行傳送
後續VueRouter系列的文章的示例編寫均基於該專案環境。
VueRouter系列文章連結
《VueRouter爬坑第一篇》-簡單實踐
《VueRouter爬坑第二篇》-動態路由
《VueRouter爬坑第三篇》-巢狀路由
閱讀目錄
一.前言-從需求出發
二.需求實現
1.選單
2.產品列表
3.產品詳情
三.主角-巢狀路由
四.總結
一.前言-從需求出發
假設我們有這樣一個需求和介面佈局:
左邊是選單區域,點選選單欄的【產品】,右邊內容區上面顯示產品列表,點選某個產品名稱下面顯示產品詳情。
emmmm,突然想想這個需求造的有點雞肋,但是也是為了從一個問題出發好去理解接下來的內容。
仔細想一想,大致的思路如下:
1.選單是公共內容,我們放入App.vue元件中實現邏輯和頁面佈局,點選選單欄的選單名稱使用<router-link>和<router-view>去顯示產品列表。
2.產品列表需要新建元件:Content.vue。該元件中編寫產品列表的程式碼,點選產品名稱展示產品詳情使用<router-link>和<router-view>去顯示產品詳情。
3.產品詳情需要新建元件:ProductDetail.vue元件。該元件中,展示相應的產品詳情。
前面兩篇VueRouter文章中的主要知識點就是url對映元件和動態路由,接下來我們結合前兩篇VueRouter文章的知識點,按照這個思路去實現需求。
感覺已經摩拳擦掌迫不及待想去實現這個小需求了 let's go go go
二.需求實現
1.選單實現-App元件
E:\MyStudy\test\VueDemo\src\App.vue
<template> <div id="app"> <!-- 選單 --> <ul> <li v-for='(item,index) in menuList' v-bind:key='index' > <router-link v-bind:to='item.url'>{{item.name}}</router-link> </li> </ul> <!-- 內容區 --> <router-view /> </div> </template> <script> export default { name: 'App', data() { return { menuList: [ { url: 'index', name: '首頁' },{ url: 'products', name: '產品' } ] } } } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; color: #2c3e50; } ul { display: inline-block; width: 100px; border: 1px solid #ddd; padding: 100px 0px 100px 20px; position: fixed; top: -10px; bottom: 0px; } a{ text-decoration: none; } </style>
App元件主要就是三點:
1.迴圈資料menuList展示選單列表,並且每個選單需要使用<router-link>新增連結
2.使用<router-view>告訴vue-router把菜單鏈接匹配到的元件渲染到那個位置
3.選單的佈局:使用fiex定位將選單固定在瀏覽器左邊,同時設定top和bottom使選單垂直方向上鋪滿瀏覽器
我們看下App元件的效果:
2.產品列表-Content元件
我們需要新建一個元件來編寫產品列表的程式碼:Content.vue
E:\MyStudy\test\VueDemo\src\components\Content.vue
<template> <div class='productContent'> <div class="productList"> <!-- 產品列表 --> <h1>產品列表</h1> <p v-for="(item,index) in productsList" v-bind:key='index'> <router-link v-bind:to="item.url">{{item.name}}</router-link> </p> </div> <!-- 產品詳情 --> <router-view /> </div> </template> <script> export default { name: 'Content', data() { return { productsList: [ { url: '/productDetail/1', name: '產品1' },{ url: '/productDetail/2', name: '產品2' } ] } } } </script> <style scoped> .productContent{ margin-left: 150px; } .productList{ border:1px solid #ddd; margin: 10px; } </style>
Content元件主要就是三點:
1.迴圈資料productsList展示產品列表,並且每個產品名稱使用<router-link>新增連結
2.使用<router-view>告訴vue-router把產品名稱匹配到的元件渲染到哪個位置
3.內容頁的佈局:需要設定左邊距 margin-left:150px,這樣就不會和選單產生覆蓋。
接著我們配置選單中的【產品】連結渲染到產品列表的路由。
E:\MyStudy\test\VueDemo\src\router\router.js
import Vue from "vue" import Router from "vue-router" Vue.use(Router) // 引入路由需要對映的元件 import Content from '@/components/Content.vue' const routes = [ { path: '/products', // 具體的路由 component: Content // 路由對映的元件 }, ] const router = new Router({ routes: routes }) export default router
現在在看下效果:
可以看到點選選單欄的【產品】已經可以成功的渲染出Content.vue元件並展示產品列表了。
3.產品詳情-ProductDetail元件
新建元件:ProductDetail.vue
E:\MyStudy\test\VueDemo\src\components\Content.vue
<template> <div class='productDetail'> <p> 名稱:產品{{$route.params.id}} </p> <p> 詳細資訊:這是產品{{$route.params.id}}的詳細資訊...... </p> </div> </template> <script> export default { name: 'ProductDetail', } </script> <style scoped> .productDetail{ border:1px solid #ddd; margin-left: 150px; } </style>
產品詳情元件比較簡單,主要有下面幾點:
1.點選不同的產品名稱需要渲染到產品詳情元件,因此產品名稱到產品詳情的路由會採用動態路由去實現。
2.使用了$route.parmas獲取了動態路由中的引數並在模板中展示。
接著就需要配置從產品名稱到產品詳情的動態路由了
E:\MyStudy\test\VueDemo\src\router\router.js
import Vue from "vue" import Router from "vue-router" Vue.use(Router) // 引入路由需要對映的元件 import Content from '@/components/Content.vue' import ProductDetail from '@/components/ProductDetail.vue' const routes = [ { path: '/products', // 具體的路由 component: Content, // 路由對映的元件 }, { path: '/productDetail/:id', //這裡使用了動態路由 component: ProductDetail // 路由對映的元件 } ] const router = new Router({ routes: routes }) export default router
程式碼完成,大概能想到的結果就是:當點選產品名稱時,產品列表下方就會出現產品詳情。
那麼我懷著雞凍的心情看下了結果:
emmmmmm,跟我們想要的效果咋不一樣:產品詳情覆蓋了產品列表。但是在Content.vue頁面,我們明明使用<router-view>已經告知了產品詳情元件應該渲染的位置。
到這裡呢,我們這節的主角巢狀路由就要登場了。
三.主角-巢狀路由
在回到我們的需求和我們前面實現的程式碼,App元件、Content元件和ProductDetail元件這三者的關係是一層一層往下巢狀並且結合vue-router、router-view顯示的:
因為元件之間是這樣巢狀的關係,所以對應路由也需要按照這個結構去巢狀。
那路由巢狀呢,就是在單條路由配置中新增children選項,children選項就是和routes一樣的路由配置陣列,同時還支援多次的巢狀。
話不多少,我們將產品詳情這條路由巢狀到產品列表路由配置下。
備註:App元件是根元件,所有的元件都是巢狀在該元件下的,預設路由也都是巢狀在根元件下。
E:\MyStudy\test\VueDemo\src\router\router.js
import Vue from "vue" import Router from "vue-router" Vue.use(Router) // 引入路由需要對映的元件 import Content from '@/components/Content.vue' import ProductDetail from '@/components/ProductDetail.vue' const routes = [ { path: '/products', // 具體的路由 component: Content, // 路由對映的元件 // 產品詳情需要使用路由巢狀才能實現 children:[ { path: '/productDetail/:id', //這裡使用了動態路由 component: ProductDetail // 路由對映的元件 } ] } ] const router = new Router({ routes: routes }) export default router
這裡還需要把ProductDetail.vue元件中的介面佈局修改一下:
.productDetail{ border:1px solid #ddd; margin: 10px; }
現在就沒啥問題了,我們在看下效果:
現在這個效果就是我們想要的效果了。是不是也很簡單呢 hahahahaha
四.總結
1.是否需要使用巢狀路由是要根據元件之前是否存在巢狀關係。
2.路由巢狀就是在單條路由配置中新增children選項,children選項就是和routes一樣的路由配置陣列,同時還支援多次的巢狀。