1. 程式人生 > 其它 >Vue全家桶--10 Vue-Router路由

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-link
to="/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>&nbsp;
                    <button class="btn btn-default btn-xs">檢視(replace)</button>
                </li>
                <li>
                    <span>網際網路大洗牌</span>
                    <button class="btn  btn-default btn-xs">檢視(Push)</button>&nbsp;
                    <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>&nbsp;
                <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!!!