python 全棧開發,Day91(Vue實例的生命週期,組件間通訊之中央事件總線bus,Vue Router,vue-cli 工具)

昨日內容回顧

0. 組件注意事項!!!
    data屬性必須是一個函數!

1. 註冊全局組件
    Vue.component('組件名',{
        template: ``
    })
    
    var app = new Vue({
        el: '#app'
    })
2. 註冊局部組件
    var app = new Vue({
        el: '#app',
        components:{
            局部組件名:{
                template: `...`
            }
        }
    })
3. 傳值
    1. 父組件 --> 子組件
        1. 父組件經過 v-bind:變量=''
        2. 子組件須要經過props 聲明我須要的變量
    2. 子組件 --> 父組件
        子組件經過觸發自定義事件的方式向外傳遞信息
        1. 子組件: this.$emit('自定義事件')
        2. 父組件: v-on:自定義事件='方法名'
        
    3. 組件間傳值
        1. 補充:Vue實例的生命週期鉤子函數(共8個)
            1. beforeCreate    --> 數據屬性聲明但沒有賦值
            2. created         --> 數據屬性賦值
            3. beforeMount     --> 頁面上的 {{name}} 尚未被渲染
            4. mounted         --> 頁面上的 {{name}} 被替換成真正的內容
            ...
            
        2. 基於bus對象實現
    
4. 插槽(slot)
    插槽是佔位置的!!!
    插槽多了能夠起名字,進行區分!   --> <span slot='heihei'>嘿嘿!</span>
    <alert>根本不顯示</alert>
    
5. 組件的注意事項:
    1. 特殊的組件須要使用is語法聲明一下 好比 table、select、ul等內部使用的組件
    2. 捕獲子組件的原生事件
View Code

解析 DOM 模板時的注意事項

有些 HTML 元素,諸如 <ul><ol><table> 和 <select>,對於哪些元素能夠出如今其內部是有嚴格限制的。而有些元素,諸如 <li><tr> 和 <option>,只能出如今其它某些特定的元素內部。javascript

這會致使咱們使用這些有約束條件的元素時遇到一些問題。例如:css

<table>
  <blog-post-row></blog-post-row>
</table>

這個自定義組件 <blog-post-row> 會被做爲無效的內容提高到外部,並致使最終渲染結果出錯。幸虧這個特殊的 is 特性給了咱們一個變通的辦法:html

<table>
  <tr is="blog-post-row"></tr>
</table>

須要注意的是若是咱們從如下來源使用模板的話,這條限制是不存在vue

到這裏,你須要瞭解的解析 DOM 模板時的注意事項——實際上也是 Vue 的所有必要內容,大概就是這些了。java

 

舉例:table標籤插入一個trnode

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="app">
    <table border="1">
        <tbody>
        <!--自定義組件-->
        <zsq></zsq>
        </tbody>
    </table>
</div>

<!-- 開發環境版本,包含了有幫助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    var app = new Vue({
        el: '#app',
        data: {},
        components:{
            zsq: {
                template: `<tr>我是一個tr標籤!</tr>`
            },
        }
    })
</script>

</body>
</html>
View Code

打開網頁,效果以下:
python

查看html代碼,發現它提高到外部了。通俗來說,就是漂移到table外面了webpack

使用is特性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="app">
    <table border="1">
        <tbody>
        <!--自定義組件-->
        <tr is=zsq></tr>
        </tbody>
    </table>
</div>

<!-- 開發環境版本,包含了有幫助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    var app = new Vue({
        el: '#app',
        data: {},
        components:{
            zsq: {
                template: `<tr>我是一個tr標籤!</tr>`
            },
        }
    })
</script>

</body>
</html>
View Code

刷新網頁,效果以下:git

查看html代碼,這樣就正常了github

 

將原生事件綁定到組件

也就是

觸發原生事件

你可能有不少次想要在一個組件的根元素上直接監聽一個原生事件。這時,你可使用 v-on 的 .native 修飾符:

<base-input v-on:focus.native="onFocus"></base-input>

在有的時候這是頗有用的,不過在你嘗試監聽一個相似 <input> 的很是特定的元素時,這並非個好主意。好比上述 <base-input> 組件可能作了以下重構,因此根元素其實是一個 <label> 元素:

<label>
  {{ label }}
  <input
    v-bind="$attrs"
    v-bind:value="value"
    v-on:input="$emit('input', $event.target.value)"
  >
</label>
View Code

這時,父級的 .native 監聽器將靜默失敗。它不會產生任何報錯,可是 onFocus 處理函數不會如你預期地被調用。

爲了解決這個問題,Vue 提供了一個 $listeners 屬性,它是一個對象,裏面包含了做用在這個組件上的全部監聽器。例如:

{
  focus: function (event) { /* ... */ }
  input: function (value) { /* ... */ },
}
View Code

有了這個 $listeners 屬性,你就能夠配合 v-on="$listeners" 將全部的事件監聽器指向這個組件的某個特定的子元素。對於相似 <input> 的你但願它也能夠配合 v-model 工做的組件來講,爲這些監聽器建立一個相似下述 inputListeners 的計算屬性一般是很是有用的:

Vue.component('base-input', {
  inheritAttrs: false,
  props: ['label', 'value'],
  computed: {
    inputListeners: function () {
      var vm = this
      // `Object.assign` 將全部的對象合併爲一個新對象
      return Object.assign({},
        // 咱們從父級添加全部的監聽器
        this.$listeners,
        // 而後咱們添加自定義監聽器,
        // 或覆寫一些監聽器的行爲
        {
          // 這裏確保組件配合 `v-model` 的工做
          input: function (event) {
            vm.$emit('input', event.target.value)
          }
        }
      )
    }
  },
  template: `
    <label>
      {{ label }}
      <input
        v-bind="$attrs"
        v-bind:value="value"
        v-on="inputListeners"
      >
    </label>
  `
})
View Code

如今 <base-input> 組件是一個徹底透明的包裹器了,也就是說它能夠徹底像一個普通的 <input> 元素同樣使用了:全部跟它相同的特性和監聽器的均可以工做。

 

舉例:第一種寫法,使用.native修飾符

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="app">
    <ztz v-on:click.native='hehe'></ztz>
</div>

<!-- 開發環境版本,包含了有幫助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            name: 'ztz',
            age: 24
        },
        components: {
            ztz: {
                template: `<button>趙天柱 逃課!</button>`
            },
        },
        methods:{
            hehe:function(){
                alert(123);
            }
        }
    })

</script>

</body>
</html>
View Code

刷新網頁,點擊按鈕,效果以下:

舉例:第二種寫法,綁定自定義事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="app">
    <!--<ztz v-on:click.native='hehe'></ztz>-->
    <ztzsb v-on:click='hehe'></ztzsb>
</div>

<!-- 開發環境版本,包含了有幫助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            name: 'ztz',
            age: 24
        },
        components: {
            // ztz: {
            //     template: `<button>趙天柱 逃課!</button>`
            // },
            ztzsb: {
                template: `<button v-on:click='shangkele'>趙天柱 逃課!</button>`,
                methods:{
                    shangkele:function(){
                        this.$emit('click')
                    }
                }
            }
        },
        methods:{
            hehe:function(){
                alert(123);
            }
        }
    })

</script>

</body>
</html>
View Code

刷新網頁,點擊按鈕,效果同上!

針對這2種寫法,推薦使用第一種!

 

1、Vue實例的生命週期

實例生命週期鉤子

每一個 Vue 實例在被建立時都要通過一系列的初始化過程——例如,須要設置數據監聽、編譯模板、將實例掛載到 DOM 並在數據變化時更新 DOM 等。同時在這個過程當中也會運行一些叫作生命週期鉤子的函數,這給了用戶在不一樣階段添加本身的代碼的機會。

好比 created 鉤子能夠用來在一個實例被建立以後執行代碼:

new Vue({
  data: {
    a: 1
  },
  created: function () {
    // `this` 指向 vm 實例
    console.log('a is: ' + this.a)
  }
})
// => "a is: 1"
View Code

也有一些其它的鉤子,在實例生命週期的不一樣階段被調用,如 mountedupdated 和 destroyed。生命週期鉤子的 this 上下文指向調用它的 Vue 實例。

不要在選項屬性或回調上使用箭頭函數,好比 created: () => console.log(this.a)vm.$watch('a', newValue => this.myMethod())。由於箭頭函數是和父級上下文綁定在一塊兒的,this 不會是如你所預期的 Vue 實例,常常致使 Uncaught TypeError: Cannot read property of undefined Uncaught TypeError: this.myMethod is not a function 之類的錯誤。

 

生命週期圖示

下圖展現了實例的生命週期。你不須要立馬弄明白全部的東西,不過隨着你的不斷學習和使用,它的參考價值會愈來愈高。

 

Vue的生命週期,就是從Vue實例被建立開始到實例銷燬時的過程,整個過程主要能夠分爲八個階段分別是:

  1. 建立前(beforeCreate)
  2. 已建立(created)
  3. 編譯前(beforeMount)
  4. 編譯後(mounted)
  5. 更新前(beforeUpdate)
  6. 更新後(update)
  7. 銷燬前(beforeDestroy)
  8. 銷燬後(destroyed)

以上各個階分別會有對應的「鉤子函數」以Vue實例的選項的形式存在。

 

Vue提供的生命週期鉤子以下:

① beforeCreate

在實例初始化以後,數據觀測(data observer,開始監控Data對象數據變化)和初始化事件(init event,Vue內部初始化事件)以前被調用。

② created

在實例已經建立完成以後被調用。實例已完成如下的配置:數據觀測(data observer),屬性和方法的運算,event事件回調。掛載階段還沒有開始,$el 屬性不可見。

③ beforeMount

在掛載開始以前被調用。相關的render函數首次被調用。實例已完成如下的配置:編譯模板,把data裏面的數據和模板生成html。注意此時尚未掛載html到頁面上。

④ mounted

在el 被新建立的 vm.$el 替換,並掛載到實例上去以後調用。實例已完成如下的配置:用上面編譯好的html內容替換el屬性指向的DOM對象。此時模板中的html渲染到了html頁面中,此時通常能夠作一些Ajax操做。注意mounted只會執行一次。

⑤ beforeUpdate

在數據更新以前調用,發生在虛擬DOM從新渲染和打補丁以前。能夠在該鉤子中進一步地更改狀態,不會觸發附加的重渲染過程。

⑥ updated

在因爲數據更改致使的虛擬DOM從新渲染和打補丁以後調用。調用時,組件DOM已經更新,因此能夠執行依賴於DOM的操做。然而在大多數狀況下,應該避免在此期間更改狀態,由於這可能會致使更新無限循環。該鉤子在服務器端渲染期間不被調用。

⑦ beforeDestroy

在實例銷燬以前調用。實例仍然徹底可用。

⑧ destroyed

在實例銷燬以後調用。調用後,全部的事件監聽器會被移除,全部的子實例也會被銷燬。該鉤子在服務器端渲染期間不被調用。

 

關於Vue生命週期的詳細解釋,請參考文章:

http://www.javashuo.com/article/p-gfficcpo-bg.html

這篇文章,寫的很是詳細,你們能夠觀摩一下!

 

若是有想作Vue開發的,vue生命週期必問。大概描述一下Vue實例被建立開始到實例銷燬時的過程,就能夠了!

 

2、組件間通訊之中央事件總線bus

摘要

中央事件總線 - 就是一個名字能夠叫作bus的vue空實例,裏邊沒有任何內容; var bus = new Vue(); 人如其名,她就像一個公交車同樣,來回輸送人,將a站點的A輸送到b站點,再將b站點的B輸送到a站點; 這裏a,b站點就像父、子組件,也像兄、弟組件,或者像兩個沒有任何親戚關係的任何組件; 而A,B就像是各個組件內部要傳輸的數據或者要執行的命令信息,靠bus來通訊。

 

中央事件總線 - 就是一個名字能夠叫作bus的vue空實例,裏邊沒有任何內容;

var bus = new Vue();

人如其名,她就像一個公交車同樣,來回輸送人,將a站點的A輸送到b站點,再將b站點的B輸送到a站點;

這裏a,b站點就像父、子組件,也像兄、弟組件,或者像兩個沒有任何親戚關係的任何組件;

而A,B就像是各個組件內部要傳輸的數據或者要執行的命令信息,靠bus來通訊。

 

若是有父子組件通訊知識基礎的,應該記得當初父子組件通訊,父組件中用$on監聽,子組件中用$emit發射。

現現在父子組件(或任何其餘關係的兩個組件之間)達成一致協議:

將監聽和發射的工做交給了bus來搞,就好像他們兩頭不自駕接送了,改乘公交了本身出發本身回家了。

那局面就是下邊這樣

$on和$emit如今綁在bus上了

bus.$emit(‘同名自定義事件名’,‘$on發送過來的數據’);

在a站點(第一個組件)中的methods方法裏,準備用bus的$emit發射事件任務。

bus.$on(‘自定義事件名’,function(){
    //而後執行什麼你本身懂的。。。
});

在b站點(另外一個組件)實例初始化(mounted鉤子中)時,用bus的$on監聽自家$emit觸發的事件。

Bus實例擴展:

能夠再添加data、methods、computed等選項,在初始化時讓bus獲取一下,任何組件均可以公用了。就像公交車上的座位,只要有座誰都能坐。

能夠包括一些共享通用的信息:好比用戶登陸的姓名、性別、郵箱等,還有油壺受權的token等。

 

舉例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="app">
    <component_1></component_1>
    <hr>
    <component_2></component_2>
</div>

<!-- 開發環境版本,包含了有幫助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    var bus = new Vue();  //中央事件總線

    var app = new Vue({
        el: '#app',
        data: {
            name: 'component_1'
        },
        components:{  //註冊局部組件
            component_1:{
                //v-on 指令監聽 DOM 事件,並在觸發時運行一些 JavaScript 代碼
                template: `<button v-on:click='paolu'>點我</button>`,
                methods:{
                    paolu(){
                        alert(123);
                        bus.$emit('taopao');  //綁定到bus上
                    }
                }
            },
            component_2: {
                template: `<div>{{num}}</div>`,
                data:function(){
                    return {
                        num: 0
                    }
                },
                mounted:function(){
                    // 在這個做用域中 this 指的是 component_2 組件實例
                    console.log(this.num);
                    var _this = this;
                    // el被掛載以後就監聽bus
                    bus.$on('taopao', function(){
                        // 在這個做用域中 this 指的是 bus
                        console.log(this.num);  // undefined
                        alert('趙天柱跑路了...');
                        // 修改component_2組件中的num值
                        // 此時this是誰?是bus
                        // this.num += 1;  // 有問題
                        _this.num += 1;
                    })
                }
            }
        }
    })
</script>

</body>
</html>
View Code

刷新網頁,效果以下:

 

 

1、Vue Router

Vue Router中文文檔

https://router.vuejs.org/zh/

介紹

Vue全家桶:Vue + VueRouter + VueX

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,讓構建單頁面應用變得易如反掌。包含的功能有:

  • 嵌套的路由/視圖表
  • 模塊化的、基於組件的路由配置
  • 路由參數、查詢、通配符
  • 基於 Vue.js 過渡系統的視圖過渡效果
  • 細粒度的導航控制
  • 帶有自動激活的 CSS class 的連接
  • HTML5 歷史模式或 hash 模式,在 IE9 中自動降級
  • 自定義的滾動條行爲

 

先來看一個網頁

點擊不一樣的選項時,頁面並無刷新。如何判斷頁面有沒有刷新呢?看瀏覽器左側這個按鈕,有沒有閃動。

雖然看到url地址變化了,但它並無刷新。這個,就是用vue實現的!

起步

用 Vue.js + Vue Router 建立單頁應用,是很是簡單的。使用 Vue.js ,咱們已經能夠經過組合組件來組成應用程序,當你要把 Vue Router 添加進來,咱們須要作的是,將組件 (components) 映射到路由 (routes),而後告訴 Vue Router 在哪裏渲染它們。下面是個基本例子:

基本使用

必須先引用vue.js,再引用vue-router.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
<div id="app">
    <!--路由的入口-->
    <!-- 使用 router-link 組件來導航. -->
    <!-- 經過傳入 `to` 屬性指定連接. -->
    <!-- <router-link> 默認會被渲染成一個 `<a>` 標籤 -->
    <!--/index表示下面定義的path-->
    <router-link to="/index">index頁面</router-link>
    <router-link to="/home">home頁面</router-link>
    <hr>
    <!--路由的出口-->
    <!-- 路由匹配到的組件將渲染在這裏 -->
    <router-view></router-view>
</div>

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script>
    //寫路由
    const routeArray = [
        {
            path:'/index',
            component:{
                template:`<div><h1>這是index頁面</h1></div>`
            },
        },
        {
            path:'/home',
            component:{  //component表示用什麼渲染
                //template 表示使用模板
                template:`<div><h1>這是home頁面</h1></div>`
            },
        }
    ]
    //生成VueRouter實例
    const routerObj = new VueRouter({
        //routes是關鍵字,它的值必須是一個數組
        routes:routeArray
    })
    //建立和掛載根實例,記得要經過 router 配置參數注入路由
    //從而讓整個應用都有路由功能
    var app = new Vue({
        el:'#app',
        //router是關鍵字
        router:routerObj  //將路由實例掛載到vue實例中
    })
</script>
</body>
</html>
View Code

刷新網頁,效果以下:

 

動態路由匹配

咱們常常須要把某種模式匹配到的全部路由,全都映射到同個組件。例如,咱們有一個 User 組件,對於全部 ID 各不相同的用戶,都要使用這個組件來渲染。那麼,咱們能夠在 vue-router 的路由路徑中使用「動態路徑參數」(dynamic segment) 來達到這個效果:

const User = {
  template: '<div>User</div>'
}

const router = new VueRouter({
  routes: [
    // 動態路徑參數 以冒號開頭
    { path: '/user/:id', component: User }
  ]
})
View Code

如今呢,像 /user/foo 和 /user/bar 都將映射到相同的路由。

一個「路徑參數」使用冒號 : 標記。當匹配到一個路由時,參數值會被設置到 this.$route.params,能夠在每一個組件內使用。因而,咱們能夠更新 User 的模板,輸出當前用戶的 ID:

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}

你能夠看看這個在線例子

你能夠在一個路由中設置多段「路徑參數」,對應的值都會設置到 $route.params 中。例如:

 

模式 匹配路徑 $route.params
/user/:username /user/evan { username: 'evan' }
/user/:username/post/:post_id /user/evan/post/123 { username: 'evan', post_id: 123 }

 

除了 $route.params 外,$route 對象還提供了其它有用的信息,例如,$route.query (若是 URL 中有查詢參數)、$route.hash 等等。你能夠查看 API 文檔 的詳細說明。

 

舉例:顯示xx的頁面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
<div id="app">
    <!--路由的入口-->
    <!-- 使用 router-link 組件來導航. -->
    <!-- 經過傳入 `to` 屬性指定連接. -->
    <!-- <router-link> 默認會被渲染成一個 `<a>` 標籤 -->
    <!--/index表示下面定義的path-->
    <router-link to="/user/zly">趙麗穎</router-link>
    <router-link to="/user/hx">韓雪</router-link>
    <hr>
    <!--路由的出口-->
    <!-- 路由匹配到的組件將渲染在這裏 -->
    <router-view></router-view>
</div>

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script>
    //寫路由
    const routeArray = [
        {
            path: '/user/:name',
            component: {
                template: `<div>
                    <h1>這是{{$route.params.name}}的主頁頁面!</h1>
                </div>`
            }
        }
    ]
    //生成VueRouter實例
    const routerObj = new VueRouter({
        routes: routeArray
    })
    var app = new Vue({
        el:'#app',
        data:{},
        //router是關鍵字,它的值必須是數組
        router:routerObj  //將路由實例掛載到vue實例中
    })
</script>
</body>
</html>
View Code

刷新網頁,效果以下:

舉例2: 獲取url中的年齡和愛好

好比: file:///E:/python_script/Vue/test.html#/user/hx?age=18&hobby=sing

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
<div id="app">
    <!--路由的入口-->
    <!-- 使用 router-link 組件來導航. -->
    <!-- 經過傳入 `to` 屬性指定連接. -->
    <!-- <router-link> 默認會被渲染成一個 `<a>` 標籤 -->
    <!--/index表示下面定義的path-->
    <router-link to="/user/zsp">趙麗穎</router-link>
    <router-link to="/user/hx">韓雪</router-link>
    <hr>
    <!--路由的出口-->
    <!-- 路由匹配到的組件將渲染在這裏 -->
    <router-view></router-view>
</div>

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script>
    //寫路由
    const routeArray = [
        {
            path: '/user/:name',
            component: {
                template: `<div>
                    <h1>這是{{$route.params.name}}的主頁頁面!</h1>
                    <p>芳齡: {{$route.query.age}}</p>
                    <p>愛好: {{$route.query.hobby}}</p>
                </div>`
            }
        }
    ]
    //生成VueRouter實例
    const routerObj = new VueRouter({
        //routes是關鍵字參數,它必須對應一個數組
        routes: routeArray
    })
    var app = new Vue({
        el:'#app',
        data:{},
        //router是關鍵字,它的值必須是數組
        router:routerObj  //將路由實例掛載到vue實例中
    })
</script>
</body>
</html>
View Code

刷新網頁,訪問如下url:

file:///E:/python_script/Vue/test.html#/user/hx?age=18&hobby=看電影

注意:後面的參數是手動加的!效果以下:

 

嵌套路由

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

/user/foo/profile                     /user/foo/posts
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

藉助 vue-router,使用嵌套路由配置,就能夠很簡單地表達這種關係。

接着上節建立的 app:

 html代碼

<div id="app">
  <router-view></router-view>
</div>
View Code

js代碼:

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User }
  ]
})
View Code

這裏的 <router-view> 是最頂層的出口,渲染最高級路由匹配到的組件。一樣地,一個被渲染組件一樣能夠包含本身的嵌套 <router-view>。例如,在 User 組件的模板添加一個 <router-view>

const User = {
  template: `
    <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `
}
View Code

要在嵌套的出口中渲染組件,須要在 VueRouter 的參數中使用 children 配置:

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User,
      children: [
        {
          // 當 /user/:id/profile 匹配成功,
          // UserProfile 會被渲染在 User 的 <router-view> 中
          path: 'profile',
          component: UserProfile
        },
        {
          // 當 /user/:id/posts 匹配成功
          // UserPosts 會被渲染在 User 的 <router-view> 中
          path: 'posts',
          component: UserPosts
        }
      ]
    }
  ]
})
View Code

要注意,以 / 開頭的嵌套路徑會被看成根路徑。 這讓你充分的使用嵌套組件而無須設置嵌套的路徑。

你會發現,children 配置就是像 routes 配置同樣的路由配置數組,因此呢,你能夠嵌套多層路由。

此時,基於上面的配置,當你訪問 /user/foo 時,User 的出口是不會渲染任何東西,這是由於沒有匹配到合適的子路由。若是你想要渲染點什麼,能夠提供一個 空的 子路由:

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id', component: User,
      children: [
        // 當 /user/:id 匹配成功,
        // UserHome 會被渲染在 User 的 <router-view> 中
        { path: '', component: UserHome },

        // ...其餘子路由
      ]
    }
  ]
})
View Code

 

舉例:點擊用戶後,展現用戶詳細信息,並能點擊查看

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
<div id="app">
    <!--路由的入口-->
    <!-- 使用 router-link 組件來導航. -->
    <!-- 經過傳入 `to` 屬性指定連接. -->
    <!-- <router-link> 默認會被渲染成一個 `<a>` 標籤 -->
    <!--/index表示下面定義的path-->
    <router-link to="/user/zsp">趙麗穎</router-link>
    <router-link to="/user/hx">韓雪</router-link>
    <hr>
    <!--路由的出口-->
    <!-- 路由匹配到的組件將渲染在這裏 -->
    <router-view></router-view>
</div>

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script>
    // 寫路由
    // route   --> 路由
    // routes  --> 多個路由
    // router  --> 路由實例
    const routeArray = [
        {
            path: '/user/:name',
            component: {
                //append表示當前路由拼接url,好比/user/hx/info
                //router-view對應子路由的template的內容
                template: `<div>
                    <h1>這是{{$route.params.name}}的主頁頁面!</h1>
                    <p>{{$route.query.age}}</p>
                    <p>{{$route.query.hobby}}</p>

                    <hr>

                    <router-link to='info' append>用戶詳細信息</router-link>
                    <router-view></router-view>
                </div>`
            },
            // 定義子路由
            children:[
                {
                    path: 'info',
                    component:{
                        template: `
                            <div>
                                <h1>釵頭鳳 唐婉</h1>
                                <p>忠厚老實人的惡毒像飯裏的砂礫或脫骨魚片裏未淨的刺給人一種不期待的傷痛。</p>
                            </div>
                        `
                    }
                },
            ]
        }
    ]
    //生成VueRouter實例
    const routerObj = new VueRouter({
        //routes是關鍵字參數,它必須對應一個數組
        routes: routeArray
    })
    var app = new Vue({
        el:'#app',
        data:{},
        //router是關鍵字,它的值必須是數組
        router:routerObj  //將路由實例掛載到vue實例中
    })
</script>
</body>
</html>
View Code

刷新網頁,效果以下:

總結:

1. 基本使用
    1. 必須導入vue-router.js文件
    2. 要有VueRouter()實例
    3. 要把VueRouter實例掛載到Vue實例中
    
    4. 路由的入口
        <router-link to='/index'>index頁面</router-link>
    5. 路由的出口
        <router-view></router-view>
2. 路由的參數
    1. path: '/user/:name' --> 匹配路由
    $route.params.name     --> 取值
    
    2. /user/alex?age=9000 --> url中攜帶參數
    $route.query.age       --> 取出url的參數
    
3. 子路由
    children:[
        {
            path: '',
            component: {
                template: `...`
            }
        }
    ]
    
    <router-link to='info' append></router-link>
View Code

 

4、webpack模板

官方文檔:

https://vuejs-templates.github.io/webpack/

介紹

這個樣板是針對大型,嚴肅的項目,並假設您有點熟悉Webpack和vue-loader請務必閱讀經常使用工做流程配方vue-loader的文檔

若是您只想嘗試vue-loader或製做快速原型,請使用webpack-simple模板。

快速開始

要使用此模板,請使用vue-cli構建項目建議使用npm 3+以得到更高效的依賴樹。

$ npm install -g vue-cli
$ vue init webpack my-project
$ cd my-project
$ npm install
$ npm run dev

vue-cli 是進行vue開發的腳手架工具,方便快速生成一個vue項目

 

先來查看node和npm的版本

C:\Users\xiao>node -v
v10.7.0

C:\Users\xiao>npm -v
6.1.0

新建一個文件夾vue-cli_demo,進入到此目錄

C:\Users\xiao>e:

E:\>cd E:\python_script\Vue\vue-cli_demo

安裝vue-cli,-g表示全局

E:\python_script\Vue\vue-cli_demo>npm install -g vue-cli
npm WARN deprecated coffee-script@1.12.7: CoffeeScript on NPM has moved to "coffeescript" (no hyphen)
C:\Users\xiao\AppData\Roaming\npm\vue -> C:\Users\xiao\AppData\Roaming\npm\node_modules\vue-cli\bin\vue
C:\Users\xiao\AppData\Roaming\npm\vue-init -> C:\Users\xiao\AppData\Roaming\npm\node_modules\vue-cli\bin\vue-init
C:\Users\xiao\AppData\Roaming\npm\vue-list -> C:\Users\xiao\AppData\Roaming\npm\node_modules\vue-cli\bin\vue-list
+ vue-cli@2.9.6
added 252 packages from 218 contributors in 29.948s

查看vue版本

E:\python_script\Vue\vue-cli_demo>vue -V
2.9.6

基於webpack模板建立項目mysite

E:\python_script\Vue\vue-cli_demo>vue init webpack mysite

提示項目名,直接回車

? Project name (mysite)

 項目描述,直接回車

? Project name mysite
? Project description (A Vue.js project)

 做者,直接回車

? Project name mysite
? Project description A Vue.js project
? Author (xiao <383697894@qq.com>)

 這個時候,文字是有顏色的,表示選中狀態,能夠用光標上下移動。選擇默認的Runtime + 便可!

 是否安裝vue-router,直接回車

? Project name mysite
? Project description A Vue.js project
? Author xiao <383697894@qq.com>
? Vue build standalone
? Install vue-router? (Y/n)

是否使用ESLint來編寫代碼?輸入n

它是javascript代碼檢測工具,必須遵循必定的規則才行,不然會有提示!

對於初學者而言,不建議開啓,不然寫代碼會很痛苦的!

? Project name mysite
? Project description A Vue.js project
? Author xiao <383697894@qq.com>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? (Y/n) n

設置單元測試,輸入n

單元測試是用來對一個模塊、一個函數或者一個類來進行正確性檢驗的測試工做。

爲了快速開發,直接關閉掉

? Project name mysite
? Project description A Vue.js project
? Author xiao <383697894@qq.com>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? No
? Set up unit tests (Y/n) n

 是否使用Nightwatch設置e2e測試,輸入n

Nightwatch.js是一個測試web app和web 站點的自動化測試框架, 使用Node.js編寫, 基於Selenium WebDriver API.

它是一個完整的瀏覽器端真實用戶場景測試解決方案, 致力於簡化繼續集成和編寫自動化測試。

小白表示一臉懵逼,關閉掉!

? Project name mysite
? Project description A Vue.js project
? Author xiao <383697894@qq.com>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? No
? Set up unit tests No
? Setup e2e tests with Nightwatch? (Y/n) n

 最後提示,使用npm安裝組件

 直接回車便可

 上面的選項,是一條最簡單的路。初學時,使用最簡單的便可!

 

下面就表示開始安裝了,耐心等待幾分鐘!

出現finished,表示安裝成功

根據提示,執行2個命令,啓動項目

 它會開啓本機的8080端口,經過便可

 提示運行的應用在 http://localhost:8080

 訪問url,效果以下:

 

項目結構

.
├── build/                       # webpack 配置文件
│   └── ...
├── config/
│   ├── index.js                # 主項目配置
│   └── ...
├── src/
│   ├── main.js                 # app 入口文件
│   ├── App.vue                 # 主應用程序組件
│   ├── components/             # ui組件
│   │   └── ...
│   └── assets/                 # 模塊資產(由webpack處理)
│       └── ...
├── static/                     # 純靜態資產(直接複製)
├── test/
│   └── unit/                   # 單元測試
│   │   ├── specs/              # 測試規範文件
│   │   ├── eslintrc            # eslint的配置文件,僅用於單元測試的額外設置
│   │   ├── index.js            # 測試構建入口文件
│   │   ├── jest.conf.js        # 使用Jest進行單元測試時的配置文件
│   │   └── karma.conf.js       # 使用Karma進行單元測試時測試運行器配置文件
│   │   ├── setup.js            # 在Jest運行單元測試以前運行的文件
│   └── e2e/                    # e2e測試
│   │   ├── specs/              # 測試規範文件
│   │   ├── custom-assertions/  # e2e測試的自定義斷言
│   │   ├── runner.js           # 測試運行腳本
│   │   └── nightwatch.conf.js  # 測試運行器配置文件
├── .babelrc                    # babel 配置
├── .editorconfig               # 縮進,空格/製表符和編輯器的相似設置
├── .eslintrc.js                # eslint 配置
├── .eslintignore               # eslint 忽略規則
├── .gitignore                  # 默認的忽略設置
├── .postcssrc.js               # postcss 配置
├── index.html                  # index.html 模板
├── package.json                # 構建腳本和依賴項
└── README.md                   # 默認 README 文件
View Code

主要幾個文件說明:

build/

此目錄包含開發服務器和生產webpack構建的實際配置。一般,您不須要觸摸這些文件,除非您想要自定義Webpack加載器,在這種狀況下您應該查看build/webpack.base.conf.js

config/index.js

這是主要配置文件,它公開了構建設置的一些最多見的配置選項。有關詳細信息,請參閱開發期間的API代理與後端框架集成

src/

這是您的大多數應用程序代碼所在的位置。如何構建此目錄中的全部內容在很大程度上取決於您; 若是您使用的是Vuex,則能夠參考Vuex應用程序建議

static/

此目錄是您不但願使用Webpack處理的靜態資產的轉義窗口。它們將直接複製到生成webpack構建資產的同一目錄中。

有關詳細信息,請參閱處理靜態資產

test/unit

包含單元測試相關文件。有關詳細信息,請參閱單元測試

test/e2e

包含e2e測試相關文件。有關更多詳細信息,請參閱端到端測試

index.html

這是咱們單頁面應用程序模板 index.html在開發和構建期間,Webpack將生成資產,這些生成的資產的URL將自動注入此模板以呈現最終的HTML。

package.json

包含全部構建依賴項和構建命令的NPM包元文件

 

構建命令

全部構建命令都經過NPM腳本執行

npm run dev

啓動Node.js本地開發服務器。有關詳細信息,請參閱開發期間的API代理

  • Webpack + vue-loader用於單個文件Vue組件。
  • 狀態保持熱重載
  • 狀態保留編譯錯誤覆蓋
  • 使用ESLint進行Lint-on-save
  • 來源地圖

npm run build

爲生產創建資產。有關更多詳細信息,請參閱與後端框架集成

  • 使用UglifyJS v3縮小JavaScript 
  • html-minifier縮小HTML
  • 將全部組件中的CSS提取到單個文件中並使用cssnano縮小
  • 全部靜態資產都使用版本哈希編譯,以實現高效的長期緩存,並index.html使用適當的URL自動生成生產,以生成這些生成的資產。

npm run unit

使用Jest在JSDOM中運行單元測試有關詳細信息,請參閱單元測試

  • 在測試文件中支持ES2015 +。
  • 輕鬆嘲笑

npm run e2e

使用Nightwatch運行端到端測試有關更多詳細信息,請參閱端到端測試

  • 在多個瀏覽器中並行運行測試。
  • 使用一個開箱即用的命令:
    • 自動處理Selenium和chromedriver依賴項。
    • 自動生成Selenium服務器。

npm run lint

運行eslint並報告代碼中的任何linting錯誤。請參閱Linter配置

 

修改默認的頁面

先中止vue項目

安裝bootstrap,執行版本爲3.3.7。-D表示當前項目安裝

E:\python_script\Vue\vue-cli_demo\mysite>npm install bootstrap@3.3.7 -D

再開啓vue項目

E:\python_script\Vue\vue-cli_demo\mysite>npm run dev

 

查看package.json,搜索bootstrap

它會自動增長一行

進入node_modules目錄,裏面有一個bootstrap文件夾

 

 進入mysite\src,這裏面纔是咱們須要編輯的文件

文件說明:

 main.js                  # app 入口文件
 App.vue                 # 主應用程序組件
 components/          # ui組件
 assets/                  # 模塊資產(由webpack處理)

查看App.vue文件內容,它由3部分組成

<template></template>         html代碼
<script></script>             js代碼
<style></style>               css代碼

修改App.vue,導入bootstrap的css文件

<template>
  <div id="app">
    <!--導航條-->
    <nav class="navbar navbar-default">
      <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                  data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Brand</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
          <ul class="nav navbar-nav">
            <li class="active"><a href="#">個人首頁</a></li>
            <li><a href="#">個人筆記</a></li>
          </ul>

          <ul class="nav navbar-nav navbar-right">
            <li><a href="#">登陸</a></li>
            <li class="dropdown">
            <li><a href="#">註冊</a></li>
          </ul>
        </div><!-- /.navbar-collapse -->
      </div><!-- /.container-fluid -->
    </nav>

    <img src="./assets/logo.png">
    <router-view/>
  </div>
</template>

<script>
  //導入bootstrap
  import 'bootstrap/dist/css/bootstrap.min.css'

  export default {
    name: 'App'
  }
</script>

<style>
  #app {
    font-family: 'Avenir', Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
    /*margin-top: 60px;*/
  }
</style>
View Code

查看網頁,效果以下:

 

 注意:修改代碼時,網頁會自動加載,不須要刷新頁面!

 

做業:

使用vue-cli,實現下面的效果:

修改App.vue,代碼以下:

<template>
  <div id="app">
    <!--導航條-->
    <nav class="navbar navbar-default">
      <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                  data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Brand</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
          <ul class="nav navbar-nav">
            <li class="active"><a href="#">個人首頁</a></li>
            <li><a href="#">個人筆記</a></li>
          </ul>

          <ul class="nav navbar-nav navbar-right">
            <li><a href="#">登陸</a></li>
            <li class="dropdown">
            <li><a href="#">註冊</a></li>
          </ul>
        </div><!-- /.navbar-collapse -->
      </div><!-- /.container-fluid -->
    </nav>
    <div class="container-fluid text-left">
      <div class="row clearfix">
        <div class="col-md-12 column">
          <div class="row clearfix">
            <div class="panel panel-info">
              <div class="panel-heading">
                <h3 class="panel-title">
                  個人筆記
                </h3>
              </div>
              <div class="panel-body">
                <div class="col-md-2 column">
                  <ul class="list-group">
                    <li class="list-group-item">
                      個人筆記1
                      <span class="glyphicon glyphicon-trash pull-right"></span>
                      <span class="glyphicon glyphicon-pencil pull-right" style="margin-right: 15px"></span>
                    </li>
                    <li class="list-group-item">
                      個人筆記2
                      <span class="glyphicon glyphicon-trash pull-right"></span>
                      <span class="glyphicon glyphicon-pencil pull-right" style="margin-right: 15px"></span>
                    </li>
                    <li class="list-group-item">
                      測試測試1
                      <span class="glyphicon glyphicon-trash pull-right"></span>
                      <span class="glyphicon glyphicon-pencil pull-right" style="margin-right: 15px"></span>
                    </li>
                    <li class="list-group-item">
                      測試測試2
                      <span class="glyphicon glyphicon-trash pull-right"></span>
                      <span class="glyphicon glyphicon-pencil pull-right" style="margin-right: 15px"></span>
                    </li>
                  </ul>
                </div>
                <div class="col-md-5 column">
                  <form>
                    <div class="input-group">
                      <span class="input-group-addon" id="basic-addon1">標題</span>
                      <input type="text" class="form-control" placeholder="請輸入標題" aria-describedby="basic-addon1">
                    </div>
                    <div style="height: 20px"></div>
                    <textarea class="form-control" style="width: 100%;height: 600px;" placeholder="Textarea"></textarea>
                  </form>
                </div>
                <div class="col-md-5 column">
                  <button type="button" class="btn btn-default btn-success">添加</button>
                  <div style="height: 20px"></div>
                  <div style="border: #C1C1C1 solid 1px;height: 600px">
                  </div>
                </div>
              </div>
              <!--<div class="panel-footer">-->
              <!--Panel footer-->
              <!--</div>-->
            </div>
          </div>
        </div>
      </div>
    </div>
    <!--<img src="./assets/logo.png">-->
    <!--<router-view/>-->
  </div>
</template>

<script>
  //導入bootstrap
  import 'bootstrap/dist/css/bootstrap.min.css'

  export default {
    name: 'App'
  }
</script>

<style>
  #app {
    font-family: 'Avenir', Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
    /*margin-top: 60px;*/
  }

</style>
View Code

訪問網頁,效果以下:

相關文章
相關標籤/搜索