整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          22《Vue 入門教程》VueRouter 路由嵌套

          . 前言

          本小節我們介紹如何嵌套使用 VueRouter。嵌套路由在日常的開發中非常常見,如何定義和使用嵌套路由是本節的重點。同學們在學完本節課程之后需要自己多嘗試配置路由。

          2. 配置嵌套路由

          實際項目中的應用界面,通常由多層嵌套的組件組合而成。同樣地,URL 中各段動態路徑也按某種結構對應嵌套的各層組件,例如:

          /article/vue                          /article/react
          +------------------+                  +-----------------+
          | Article          |                  | Article         |
          | +--------------+ |                  | +-------------+ |
          | | Vue          | |  +------------>  | | React       | |
          | |              | |                  | |             | |
          | +--------------+ |                  | +-------------+ |
          +------------------+                  +-----------------+
          代碼塊12345678

          借助 vue-router,使用嵌套路由配置,就可以很簡單地表達這種關系。 在上一小節中我們學習了如何配置一個路由信息:

            {
              path: '路由地址',
              component: '渲染組件'
            }
          

          要配置嵌套路由,我們需要在配置的參數中使用 children 屬性:

            {
              path: '路由地址',
              component: '渲染組件',
              children: [
                {
                  path: '路由地址',
                  component: '渲染組件'
                }
              ]
            }
          

          2.1 基本使用

          接下來我們對上一小節的例子來做一個改造:在文章頁面,我們對文章進行分類,提供兩個鏈接按鈕 vue、react,點擊可以跳轉到對應的文章列表,具體代碼示例如下:

          實例演示

          <!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>
          </head>
          <body>
            <div id="app">
              <div>
                <router-link to="/index">首頁</router-link>
                <router-link to="/article">文章</router-link>
              </div>
              <router-view></router-view>
            </div>
          </body>
          
          <script src="https://unpkg.com/vue/dist/vue.js"></script>
          <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
          <script type="text/javascript">
          
          const Index = Vue.component('index', {
            template: '<div>Hello,歡迎使用慕課網學習 Vue 教程!</div>',
          })
          
          const Article = Vue.component('myArticle', {
            template: `<div>
                <div>
                  <router-link to="/article/vue">vue</router-link>
                  <router-link to="/article/react">react</router-link>
                </div>
                <router-view></router-view>
              </div>`,
          })
          
          const VueArticle = Vue.component('vueArticle', {
            template: `<ul><li>1. Vue 基礎學習</li><li>2. Vue 項目實戰</li></ul>`,
          })
          
          const ReactArticle = Vue.component('reactArticle', {
            template: `<ul><li>1. React 基礎學習</li><li>2. React 項目實戰</li></ul>`,
          })
          
          const routes = [
            { path: '/index', component: Index },
            { 
              path: '/article', 
              component: Article ,
              children: [
                {
                  path: 'vue', 
                  component: VueArticle ,
                },
                {
                  path: 'react', 
                  component: ReactArticle ,
                }
              ]
            }
          ]
          
          const router = new VueRouter({
            routes: routes
          })
          
            var vm = new Vue({
              el: '#app',
              router,
              data() {
                  return {}
              }
            })
          </script>
          </html>
          

          "運行案例" 可查看在線運行效果

          代碼解釋: HTML 代碼第 12-13 行,我們定義了兩個跳轉鏈接。 HTML 代碼第 15 行,我們使用 <router-view></router-view> 組件來渲染匹配組件。 JS 代碼第 5-7 行,我們定義了組件 Index。 JS 代碼第 9-17 行,我們定義了組件 Article,組件內部使用 <router-link></router-link> 定義出來兩個跳轉鏈接,使用 <router-view></router-view> 來渲染匹配組件。 JS 代碼第 19-21 行,我們定義了組件 VueArticle. JS 代碼第 23-25 行,我們定義了組件 ReactArticle。 JS 代碼第 27-43 行,我們定義了路由數組,在 ‘/article’ 中配置來嵌套路由 children JS 代碼第 44-46 行,創建 router 實例,然后傳 routes 配置。 JS 代碼第 49 行,通過 router 配置參數注入路由。

          2.2 定義路由地址

          在上述的例子中,我們通過 ‘/article/vue’ 來訪問嵌套路由,但是有時候你可能不希望使用嵌套路徑,這時候我們可以對上面例子中的配置信息做一點修改:

          const routes = [
            { path: '/index', component: Index },
            { 
              path: '/article', 
              component: Article ,
              children: [
                {
                  path: '/vueArticle', 
                  component: VueArticle ,
                },
                {
                  path: '/reactArticle', 
                  component: ReactArticle ,
                }
              ]
            }
          ]
          

          ‘/’ 開頭的嵌套路徑會被當作根路徑,因此,我們訪問 ‘/vueArticle’ 就相當于訪問之前的 ‘/article/vue’。

          3. 小結

          本節,我們帶大家學習了 VueRouter 嵌套路由的使用方法,主要知識點有以下幾點:

          • 通過路由配置的 children 屬性定義和使用嵌套路由。
          • 通過修改路由配置的 path 屬性定義嵌套路由的跳轉地址。

          ue3 嵌套路由的使用和 Vue2 相差不大,主要的區別是 Vue3 的路由實例化使用了 createApp() 方法,所以實例化路由時需要傳入根組件。另外,Vue3 的路由對象除了包含 Vue2 中的導航守衛、導航鉤子和解析守衛等功能外,還新增了 meta prop 和 route prop。

          在使用嵌套路由時,建議將路由按照功能模塊進行分層,每一層代表一個主要的功能塊,每個層級下的路由數量不要過多,一般建議不要超過 10 個,層級也不要超過 5 層。同時,根據實際業務需求,可以適當調整路由層級和數量,以達到更好的管理和使用效果。

          route文件下 index.ts文件代碼:


          import {
            createRouter,
            createWebHashHistory,
            RouteRecordRaw
          } from "vue-router";
          // createWebHashHistory,createWebHistory
          
          const routes: RouteRecordRaw[] = [
            {
              path: '/',
              redirect: '/home',
            },
            {
              path: '/home',
              name: 'Home',
              component: () => import('@/views/Home/index.vue'),
              meta: {
                title: 'Home Page',
                roles: ['admin', 'admin1']
              },
              children: [
                {
                  path: 'lx',
                  name: 'Lx',
                  component: () => import('@/views/Home/Lx.vue'),
                  // 也可以使用props傳參方式接收傳來的參數
                  props: (propsRouter) => {
                    // console.log('props >router', propsRouter)
                    // 可以return query 也可以return params支持兩種傳參方式
                    return propsRouter.query
                  },
                  // 多級嵌套 建議用query傳參
                  children: [
                    {
                      path: 'childA',
                      name: 'ChildA',
                      component: () => import('@/views/Home/ChildA.vue'),
                    },
                  ]
                },
                {
                  path: 'lxb/:id/:title', // 提前定義params參數(可以定義多個)
                  name: 'Lxb',
                  component: () => import('@/views/Home/Lxb.vue'),
                },
              ]
            },
          ]
          
          export const router = createRouter({
            // 路由的history模式,共有三種模式,
            // createWebHistory、createWebHashHistory、createMemoryHistory
            history: createWebHashHistory(),// history: createWebHistory(),
            // 路由配置
            routes,
            // 是否嚴格匹配路由
            strict: true,
            // 路由跳轉完成后,頁面滾動行為
            scrollBehavior: () => ({ left: 0, top: 0 }),
          })
          

          main.ts文件代碼:

          import { router } from './route/index'
          import { createApp } from 'vue'
          
          const app = createApp(App)
          app.use(router).mount('#app')

          App.vue文件代碼:

          <template>
            <router-view />
          </template>
          
          <script>
          import { defineComponent } from 'vue'
           // vue3.0版本語法
          export default defineComponent({
            name: 'App',
          })
          </script>

          views文件夾下的Home文件夾下的index.vue文件代碼:

          <template>
            <div class="home">
              <h2>首頁{{ title }}</h2>
              <!-- 模擬有權限時顯示 -->
              <div v-if="roles.includes(role)">
                <h2>嵌套路由</h2>
                <router-link to="/home/lx">push跳轉到/home/lx頁面</router-link>
                <br>
                <!-- 加了/就要寫全 /home/lxb -->
                <router-link replace to="/home/lxb/id:2/title:102">push跳轉到/home/lxb頁面</router-link>
          
                <router-view></router-view>
              </div>
            </div>
          </template>
          
          <script lang="ts">
          import { defineComponent, reactive, onMounted, toRefs, } from 'vue'
          import { useRoute, useRouter } from 'vue-router'
          
          export default defineComponent({
            name: 'Home',
            setup() {
              const router = useRouter()
              const route: any = useRoute()
          
              const state = reactive({
                title: '',
                role: '', // 我的當前角色
                roles: [''],
                routerGo: (path) => {
                  if (path === 'lx') {
                    // query傳參可以用path 也可以用name: Lx
                    router.push({
                      path: path,
                      query: {
                        title: '101',
                        id: 1
                      }
                    })
                    // router.replace
                  } else {
                    // params傳參只能用name
                    router.replace({
                      // path: path + '/id:2/title:102',
                      name: 'Lxb',
                      params: {
                        title: '102',
                        id: 2
                      }
                    })
                  }
                },
              })
              onMounted(() => {
                console.log('/home', route)
                state.title = route.meta.title
                state.roles = route.meta.roles
                // 模擬一個接口
                setTimeout(() => {
                  const res = {
                    code: 200,
                    data: {
                      token: '123456',
                      userName: '吳彥祖',
                      role: 'admin'
                    }
                  }
                  state.role = res.data.role
                }, 0)
              })
              return {
                ...toRefs(state)
              }
            }
          })
          </script>
          
          <style lang="less" scoped>
          .home {
            color: pink;
            font-size: 14px;
          }
          </style>

          views文件夾下的Home文件夾下的Lxb.vue文件代碼:

          <template>
            <div style="font-size: 14px;">
              <h2>我是練習b{{ route?.params?.title }}頁面</h2>
              <div>id:{{ route?.params?.id }}</div>
              <button @click="routerGoBack">返回首頁</button>
            </div>
          </template>
          
          <script lang="ts">
          import { defineComponent, onMounted, reactive, toRefs } from 'vue'
          import { useRoute, useRouter } from 'vue-router'
          
          // vue3.0語法
          export default defineComponent({
            name: 'Lxb',
            setup() {
              const route = useRoute()
              const router = useRouter()
              const state: any = reactive({
                routerGoBack: () => {
                  router.replace('/home')
                  // 由replace跳轉進來的不可以使用router.go(-1) 路由棧是空的》回不到上一個路由
                },
              })
          
              onMounted(() => {
                console.log(route)
              })
          
              return {
                route,
                ...toRefs(state)
              }
            },
          })
          </script>

          views文件夾下的Home文件夾下的Lx.vue文件代碼:

          <template>
            <div style="font-size: 14px;">
              <h2>我是練習{{ title }}頁面</h2>
              <div>id:{{ id }}</div>
              <div>props: {{ props }}</div>
              <button @click="routerGoBack">返回上一頁</button>
              <br>
              <button @click="routerGo('/home/lx/childA')">去子路由childA</button>
              <!-- <router-view></router-view> -->
              <router-view />
            </div>
          </template>
          
          <script lang="ts">
          import { defineComponent, onMounted, reactive, toRefs } from 'vue'
          import { useRoute, useRouter } from 'vue-router'
          
          // vue3.0語法
          export default defineComponent({
            name: 'Lx',
            props: {
              id: {
                type: String,
                default: ''
              },
              title: {
                type: String,
                default: ''
              },
            },
            setup(props) {
              const route = useRoute()
              const router = useRouter()
              const state: any = reactive({
                id: '',
                title: '',
                routerGoBack: () => {
                  router.go(-1) // go(-1)回到上一個路由
                  // 也可以用router.replace('/home')跳回指定頁
                },
                routerGo: (path) => {
                  router.push(path)
                }
              })
          
              onMounted(() => {
                console.log('lx route', route)
                console.log('lx props', props)
                if (route.query) {
                  state.id = route.query.id
                  state.title = route.query.title
                }
              })
          
              return {
                props,
                ...toRefs(state)
              }
            },
          })
          </script>

          views文件夾下的Home文件夾下的ChildA.vue文件代碼:

          <template>
            <div style="font-size: 14px;background: skyblue;">
              <h3>我是ChildA組件</h3>
              <h3>route.query:{{ route.query }}</h3>
            </div>
          </template>
          
          <script lang="ts">
          import { defineComponent, onMounted, } from 'vue'
          import { useRoute, useRouter } from 'vue-router'
          // vue3.0語法
          export default defineComponent({
            name: 'ChildA',
            setup() {
              const router = useRouter()
              const route = useRoute()
              function goBack() {
                router.go(-1)
              }
              onMounted(() => {
                console.log(route)
              })
              // 可以在頁面銷毀前清除事件
              // onUnmounted(() => {
              //   proxy.$mittBus.off('mittUserA')
              // })
              return {
                route, goBack
              }
            },
          })
          </script>

          初始頁面效果:


          先點擊push跳轉到/home/lxb頁面>(嵌套一層的路由)頁面效果:

          嵌套一層的路由從原本/home跳入了/home/lxb 子路由頁面,點擊回到首頁。

          再點擊push跳轉到/home/lx頁面>(嵌套多層的路由)頁面效果:


          先去到了第一層/home/lx子路由頁面,

          再點擊去子路由childA按鈕>頁面效果

          進到了嵌套的第二層/home/lx/childA子路由頁面


          點擊可返回上一頁/home/lx 再點擊可回到/home首頁。


          歡迎關注我的原創文章:小伙伴們!我是一名熱衷于前端開發的作者,致力于分享我的知識和經驗,幫助其他學習前端的小伙伴們。在我的文章中,你將會找到大量關于前端開發的精彩內容。

          學習前端技術是現代互聯網時代中非常重要的一項技能。無論你是想成為一名專業的前端工程師,還是僅僅對前端開發感興趣,我的文章將能為你提供寶貴的指導和知識。

          在我的文章中,你將會學到如何使用HTML、CSS和JavaScript創建精美的網頁。我將深入講解每個語言的基礎知識,并提供一些實用技巧和最佳實踐。無論你是初學者還是有一定經驗的開發者,我的文章都能夠滿足你的學習需求。

          此外,我還會分享一些關于前端開發的最新動態和行業趨勢。互聯網技術在不斷發展,新的框架和工具層出不窮。通過我的文章,你將會了解到最新的前端技術趨勢,并了解如何應對這些變化。

          我深知學習前端不易,因此我將盡力以簡潔明了的方式解釋復雜的概念,并提供一些易于理解的實例和案例。我希望我的文章能夠幫助你更快地理解前端開發,并提升你的技能。

          如果你想了解更多關于前端開發的內容,不妨關注我的原創文章。我會不定期更新,為你帶來最新的前端技術和知識。感謝你的關注和支持,我們一起探討交流技術共同進步,期待與你一同探索前端開發的奇妙世界!

          #前端#

          生成動態的HTML頁面,頁面中使用嵌入 Vue.js 語法可動態生成

          1. {{xxxx}}雙大括號文本綁定

          2. v-xxxx以v-開頭用于標簽屬性綁定,稱為指令

          雙大括號語法{{}}

          格式:{{表達式}}

          作用:

          使用在標簽體中,用于獲取數據

          可以使用 JavaScript 表達式

          一次性插值v-once

          通過使用v-once指令,你也能執行一次性地插值,當數據改變時,插值處的內容不會更新

          輸出HTML指令v-html

          格式:v-html='xxxx'

          作用:

          如果是HTML格式數據,雙大括號會將數據解釋為普通文本,為了輸出真正的 HTML,你需要使用v-html指令。

          Vue 為了防止 XSS 攻擊,在此指令上做了安全處理,當發現輸出內容有 script 標簽時,則不渲染

          XSS 攻擊主要利用 JS 腳本注入到網頁中,讀取 Cookie 值(Cookie一般存儲了登錄身份信息),讀取到了發送到黑客服務器,從而黑客可以使用你的帳戶做非法操作。XSS 攻擊還可以在你進入到支付時,跳轉到釣魚網站。

          元素綁定指令v-bind

          完整格式:v-bind:元素的屬性名='xxxx'

          縮寫格式::元素的屬性名='xxxx'

          作用:將數據動態綁定到指定的元素上

          事件綁定指令v-on

          完整格式:v-on:事件名稱="事件處理函數名"

          縮寫格式:@事件名稱="事件處理函數名"注意:@后面沒有冒號

          作用:用于監聽 DOM 事件

          <!DOCTYPE html>

          <html lang="en">

          <head>

          <meta charset="UTF-8">

          <meta http-equiv="X-UA-Compatible" content="IE=edge">

          <meta name="viewport" content="width=device-width, initial-scale=1.0">

          <title>Document</title>

          </head>

          <body>

          <div id="app">

          <h3>1、{{}}雙大括號輸出文本內容</h3>

          <!-- 文本內容 -->

          <p>{{msg}}</p>

          <!-- JS表達式 -->

          <p>{{score + 1}}</p>

          <h3>2、一次性插值</h3>

          <p v-once>{{score + 1}}</p>

          <h3>3、指令輸出真正的 HTML 內容 v-html</h3>

          <p>雙大括號:{{contentHtml}}</p>

          <!--

          v-html:

          1、如果輸出的內容是HTML數據,雙大括號將數據以普通文本方式進行輸出,為了輸出真正HTML數據,就需要使用v-html指定

          2、為了防止XSS攻擊

          -->

          <p>v-html:<span v-html="contentHtml"></span></p>

          <h3>4、v-bind屬性綁定指令</h3>

          <img v-bind:src="imgUrl">

          <img :src="imgUrl">

          <a :href="tzUrl">跳轉</a>


          <h3>5、事件綁定指令 v-on</h3> <input type="text" value="1" v-model="num"> <button @click='add'>點擊+1</button> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { msg: "菜園子", score: 100, contentHtml: '<span style="color:red">此內容為紅色字體</span>', imgUrl: 'https://cn.vuejs.org/images/logo.png', tzUrl: 'https://www.baidu.com/', num : 10 }, methods: { add: function(){ console.log('add被調用') this.num ++ } }, }) </script></body></html>


          git源碼地址:https://github.com/caiyuanzi-song/vue-demo.git


          主站蜘蛛池模板: 亚洲AV成人一区二区三区观看 | 怡红院一区二区三区| 麻豆国产一区二区在线观看| 久久久久久一区国产精品| 国产精品视频一区| 亚洲高清美女一区二区三区| 日韩精品无码一区二区三区AV | 精品一区二区91| 成人无码精品一区二区三区| 无码日本电影一区二区网站 | 国产精品一区二区久久乐下载| 69久久精品无码一区二区| 国精品无码一区二区三区在线| 91久久精一区二区三区大全| 国产精品亚洲不卡一区二区三区| 一区二区国产精品| 国产一区二区三区无码免费| 在线观看一区二区三区视频| 国产麻豆剧果冻传媒一区| 精品一区狼人国产在线| 国产精品一区二区电影| 日韩精品一区二区三区中文字幕| 日本中文一区二区三区亚洲| 一区二区三区四区在线播放 | 亚洲AV日韩综合一区尤物| 中文字幕日韩一区二区三区不卡| 2022年亚洲午夜一区二区福利| 日本免费一区二区三区四区五六区 | 久久久久无码国产精品一区| 污污内射在线观看一区二区少妇| 日韩人妻一区二区三区蜜桃视频| 色久综合网精品一区二区| 亚洲色精品VR一区区三区| 精品一区二区三人妻视频| 国产精品va一区二区三区| 精品一区二区三区色花堂| 久久久一区二区三区| 国产精品一区在线麻豆| 蜜桃视频一区二区三区| 亚洲日本一区二区三区在线 | 精品在线一区二区|