vue入門

學習目標

  • 會建立Vue實例,知道Vue的常見屬性
  • 會使用Vue的生命週期的鉤子函數
  • 會使用vue常見指令
  • 會使用vue計算屬性和watch監控
  • 會編寫Vue組件
  • 掌握組件間通訊
  • 瞭解vue-router使用

0.前言

前幾天咱們已經對後端的技術棧有了初步的瞭解、而且已經搭建了整個後端微服務的平臺。接下來要作的事情就是功能開發了。可是沒有前端頁面,咱們確定無從下手,所以今天咱們就要來了解一下前端的一些技術,完成前端頁面搭建。javascript

先聊一下前端開發模式的發展。php

靜態頁面html

最初的網頁以HTML爲主,是純靜態的網頁。網頁是隻讀的,信息流只能從服務端到客戶端單向流通。開發人員也只關心頁面的樣式和內容便可。前端

異步刷新,操做DOMvue

1995年,網景工程師Brendan Eich 花了10天時間設計了JavaScript語言.java

隨着JavaScript的誕生,咱們能夠操做頁面的DOM元素及樣式,頁面有了一些動態的效果,可是依然是以靜態爲主。node

ajax盛行:jquery

  • 2005年開始,ajax逐漸被前端開發人員所重視,由於不用刷新頁面就能夠更新頁面的數據和渲染效果。
  • 此時的開發人員不只僅要編寫HTML樣式,還要懂ajax與後端交互,而後經過JS操做Dom元素來實現頁面動態效果。比較流行的框架如Jquery就是典型表明。

MVVM,關注模型和視圖ios

2008年,google的Chrome發佈,隨後就以極快的速度佔領市場,超過IE成爲瀏覽器市場的主導者。git

2009年,Ryan Dahl在谷歌的Chrome V8引擎基礎上,打造了基於事件循環的異步IO框架:Node.js。

  • 基於事件循環的異步IO
  • 單線程運行,避免多線程的變量同步問題
  • JS能夠編寫後臺代碼,先後臺統一編程語言

node.js的偉大之處不在於讓JS邁向了後端開發,而是構建了一個龐大的生態系統。

2010年,NPM做爲node.js的包管理系統首次發佈,開發人員能夠遵循Common.js規範來編寫Node.js模塊,而後發佈到NPM上供其餘開發人員使用。目前已是世界最大的包模塊管理系統。

隨後,在node的基礎上,涌現出了一大批的前端框架:

1525825983230

MVVM模式

  • M:即Model,模型,包括數據和一些基本操做
  • V:即View,視圖,頁面渲染結果
  • VM:即View-Model,模型與視圖間的雙向操做(無需開發人員干涉)

在MVVM以前,開發人員從後端獲取須要的數據模型,而後要經過DOM操做Model渲染到View中。然後當用戶操做視圖,咱們還須要經過DOM獲取View中的數據,而後同步到Model中。

而MVVM中的VM要作的事情就是把DOM操做徹底封裝起來,開發人員不用再關心Model和View之間是如何互相影響的:

  • 只要咱們Model發生了改變,View上天然就會表現出來。
  • 當用戶修改了View,Model中的數據也會跟着改變。

把開發人員從繁瑣的DOM操做中解放出來,把關注點放在如何操做Model上。

1525828854056

而咱們今天要學習的,就是一款MVVM模式的框架:Vue

1.認識Vue

Vue (讀音 /vjuː/,相似於 view) 是一套用於構建用戶界面的漸進式框架。與其它大型框架不一樣的是,Vue 被設計爲能夠自底向上逐層應用。Vue 的核心庫只關注視圖層,不只易於上手,還便於與第三方庫或既有項目整合。另外一方面,當與現代化的工具鏈以及各類支持類庫結合使用時,Vue 也徹底可以爲複雜的單頁應用提供驅動。

前端框架三巨頭:Vue.js、React.js、AngularJS,vue.js以其輕量易用著稱,vue.js和React.js發展速度最快,AngularJS仍是老大。
複製代碼

官網:cn.vuejs.org/

參考:cn.vuejs.org/v2/guide/

1525829249048

Git地址:github.com/vuejs

1525829030730

尤雨溪,Vue.js 創做者,Vue Technology創始人,致力於Vue的研究開發。

2.Node和NPM

前面說過,NPM是Node提供的模塊管理工具,能夠很是方便的下載安裝不少前端框架,包括Jquery、AngularJS、VueJs都有。爲了後面學習方便,咱們先安裝node及NPM工具。

2.1.下載Node.js

下載地址:nodejs.org/en/

1529594451775

推薦下載LTS版本。

課程中採用的是8.11.3版本。也是目前最新的。你們自行下載或者使用課前資料中提供的安裝包。而後下一步安裝便可。

完成之後,在控制檯輸入:

node -v
複製代碼

看到版本信息:

1529595770482

2.2.NPM

Node自帶了NPM了,在控制檯輸入npm -v查看:

1529595810923

npm默認的倉庫地址是在國外網站,速度較慢,建議你們設置到淘寶鏡像。可是切換鏡像是比較麻煩的。推薦一款切換鏡像的工具:nrm

咱們首先安裝nrm,這裏-g表明全局安裝。可能須要一點兒時間

npm install nrm -g
複製代碼

1529596099952

而後經過nrm ls命令查看npm的倉庫列表,帶*的就是當前選中的鏡像倉庫:

1529596219439

經過nrm use taobao來指定要使用的鏡像源:

1529596312671

而後經過nrm test npm來測試速度:

1529596566134

注意:

  • 有教程推薦你們使用cnpm命令,可是使用發現cnpm有時會有bug,不推薦。
  • 安裝完成請必定要重啓下電腦!!!
  • 安裝完成請必定要重啓下電腦!!!
  • 安裝完成請必定要重啓下電腦!!!

3.快速入門

接下來,咱們快速領略下vue的魅力

3.1.建立工程

建立一個新的空工程:

1529596874127

1529597228506

而後新建一個module:

1529597325121

選中static web,靜態web項目:

1529597573453

位置信息:

1529597672429

3.2.安裝vue

3.2.1.下載安裝

下載地址:github.com/vuejs/vue

能夠下載2.5.16版本https://github.com/vuejs/vue/archive/v2.5.16.zip

下載解壓,獲得vue.js文件。

3.2.2.使用CDN

或者也能夠直接使用公共的CDN服務:

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

或者:

<!-- 生產環境版本,優化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
複製代碼

3.2.3.推薦npm安裝

在idea的左下角,有個Terminal按鈕,點擊打開控制檯:

1529598030268

進入hello-vue目錄,先輸入:npm init -y 進行初始化

1529598244471

安裝Vue,輸入命令:npm install vue --save

1529598444504

而後就會在hello-vue目錄發現一個node_modules目錄,而且在下面有一個vue目錄。

1529602488684

node_modules是經過npm安裝的全部模塊的默認位置。

3.3.vue入門案例

3.3.1.HTML模板

在hello-vue目錄新建一個HTML

1529719572523

在hello.html中,咱們編寫一段簡單的代碼:

1529719673944

h2中要輸出一句話:xx 很是帥。前面的xx是要渲染的數據。

3.3.2.vue聲明式渲染

而後咱們經過Vue進行渲染:

<body>
    <div id="app">
        <h2>{{name}},很是帥!!!</h2>
    </div>
</body>
<script src="node_modules/vue/dist/vue.js" ></script>
<script> // 建立vue實例 var app = new Vue({ el:"#app", // el即element,該vue實例要渲染的頁面元素 data:{ // 渲染頁面須要的數據 name: "峯哥" } }); </script>
複製代碼
  • 首先經過 new Vue()來建立Vue實例
  • 而後構造函數接收一個對象,對象中有一些屬性:
    • el:是element的縮寫,經過id選中要渲染的頁面元素,本例中是一個div
    • data:數據,數據是一個對象,裏面有不少屬性,均可以渲染到視圖中
      • name:這裏咱們指定了一個name屬性
  • 頁面中的h2元素中,咱們經過{{name}}的方式,來渲染剛剛定義的name屬性。

打開頁面查看效果:

1529722898366

更神奇的在於,當你修改name屬性時,頁面會跟着變化:

1529723206508

3.3.3.雙向綁定

咱們對剛纔的案例進行簡單修改:

<body>
    <div id="app">
        <input type="text" v-model="num">
        <h2>
            {{name}},很是帥!!!有{{num}}位女神爲他着迷。
        </h2>
    </div>
</body>
<script src="node_modules/vue/dist/vue.js" ></script>
<script> // 建立vue實例 var app = new Vue({ el: "#app", // el即element,該vue實例要渲染的頁面元素 data: { // 渲染頁面須要的數據 name: "峯哥", num: 5 } }); </script>
複製代碼
  • 咱們在data添加了新的屬性:num
  • 在頁面中有一個input元素,經過v-modelnum進行綁定。
  • 同時經過{{num}}在頁面輸出

效果:

1529723206508

咱們能夠觀察到,輸入框的變化引發了data中的num的變化,同時頁面輸出也跟着變化。

  • input與num綁定,input的value值變化,影響到了data中的num值
  • 頁面{{num}}與數據num綁定,所以num值變化,引發了頁面效果變化。

沒有任何dom操做,這就是雙向綁定的魅力。

3.3.4.事件處理

咱們在頁面添加一個按鈕:

<button v-on:click="num++">點我</button>
複製代碼
  • 這裏用v-on指令綁定點擊事件,而不是普通的onclick,而後直接操做num
  • 普通click是沒法直接操做num的。

效果:

4.Vue實例

4.1.建立Vue實例

每一個 Vue 應用都是經過用 Vue 函數建立一個新的 Vue 實例開始的:

var vm = new Vue({
  // 選項
})
複製代碼

在構造函數中傳入一個對象,而且在對象中聲明各類Vue須要的數據和方法,包括:

  • el
  • data
  • methods

等等

接下來咱們一 一介紹。

4.2.模板或元素

每一個Vue實例都須要關聯一段Html模板,Vue會基於此模板進行視圖渲染。

咱們能夠經過el屬性來指定。

例如一段html模板:

<div id="app">
    
</div>
複製代碼

而後建立Vue實例,關聯這個div

var vm = new Vue({
	el:"#app"
})
複製代碼

這樣,Vue就能夠基於id爲app的div元素做爲模板進行渲染了。在這個div範圍之外的部分是沒法使用vue特性的。

4.3.數據

當Vue實例被建立時,它會嘗試獲取在data中定義的全部屬性,用於視圖的渲染,而且監視data中的屬性變化,當data發生改變,全部相關的視圖都將從新渲染,這就是「響應式「系統。

html:

<div id="app">
    <input type="text" v-model="name"/>
</div>
複製代碼

js:

var vm = new Vue({
    el:"#app",
    data:{
        name:"劉德華"
    }
})
複製代碼
  • name的變化會影響到input的值
  • input中輸入的值,也會致使vm中的name發生改變

4.4.方法

Vue實例中除了能夠定義data屬性,也能夠定義方法,而且在Vue實例的做用範圍內使用。

html:

<div id="app">
    {{num}}
    <button v-on:click="add"></button>
</div>
複製代碼

js:

var vm = new Vue({
    el:"#app",
    data:{
        num: 0
    },
    methods:{
        add:function(){
            // this表明的當前vue實例
            this.num++;
        }
    }
})
複製代碼

4.5.生命週期鉤子

4.5.1.生命週期

每一個 Vue 實例在被建立時都要通過一系列的初始化過程 :建立實例,裝載模板,渲染模板等等。Vue爲生命週期中的每一個狀態都設置了鉤子函數(監聽函數)。每當Vue實例處於不一樣的生命週期時,對應的函數就會被觸發調用。

生命週期:

Vue life cycle

4.5.2.鉤子函數

beforeCreated:咱們在用Vue時都要進行實例化,所以,該函數就是在Vue實例化時調用,也能夠將他理解爲初始化函數比較方便一點,在Vue1.0時,這個函數的名字就是init。

created:在建立實例以後進行調用。

beforeMount:頁面加載完成,沒有渲染。如:此時頁面仍是{{name}}

mounted:咱們能夠將他理解爲原生js中的window.onload=function({.,.}),或許你們也在用jquery,因此也能夠理解爲jquery中的$(document).ready(function(){….}),他的功能就是:在dom文檔渲染完畢以後將要執行的函數,該函數在Vue1.0版本中名字爲compiled。 此時頁面中的{{name}}已被渲染成峯哥

beforeDestroy:該函數將在銷燬實例前進行調用 。

destroyed:改函數將在銷燬實例時進行調用。

beforeUpdate:組件更新以前。

updated:組件更新以後。

例如:created表明在vue實例建立後;

咱們能夠在Vue中定義一個created函數,表明這個時期的鉤子函數:

// 建立vue實例
    var app = new Vue({
        el: "#app", // el即element,該vue實例要渲染的頁面元素
        data: { // 渲染頁面須要的數據
            name: "峯哥",
            num: 5
        },
        methods: {
            add: function(){
                this.num--;
            }
        },
        created: function () {
            this.num = 100;
        }
    });
複製代碼

結果:

1529835200236

4.5.3.this

咱們能夠看下在vue內部的this變量是誰,咱們在created的時候,打印this

methods: {
            add: function(){
                this.num--;
                console.log(this);
            }
        },
複製代碼

控制檯的輸出:

1529835379275

5.指令

什麼是指令?

指令 (Directives) 是帶有 v- 前綴的特殊特性。指令特性的預期值是:單個 JavaScript 表達式。指令的職責是,當表達式的值改變時,將其產生的連帶影響,響應式地做用於 DOM。

例如咱們在入門案例中的v-on,表明綁定事件。

5.1.插值表達式

5.1.1.花括號

格式:

{{表達式}}
複製代碼

說明:

  • 該表達式支持JS語法,能夠調用js內置函數(必須有返回值)
  • 表達式必須有返回結果。例如 1 + 1,沒有結果的表達式不容許使用,如:var a = 1 + 1;
  • 能夠直接獲取Vue實例中定義的數據或函數

示例:

HTML:

<div id="app">{{name}}</div>
複製代碼

JS:

var app = new Vue({
    el:"#app",
    data:{
        name:"Jack"
    }
})
複製代碼

5.1.2.插值閃爍

使用{{}}方式在網速較慢時會出現問題。在數據未加載完成時,頁面會顯示出原始的{{}},加載完畢後才顯示正確數據,咱們稱爲插值閃爍。

咱們將網速調慢一些,而後試試看剛纔的案例:

1529836021593

刷新頁面:

5.1.3.v-text和v-html

使用v-text和v-html指令來替代{{}}

說明:

  • v-text:將數據輸出到元素內部,若是輸出的數據有HTML代碼,會做爲普通文本輸出
  • v-html:將數據輸出到元素內部,若是輸出的數據有HTML代碼,會被渲染

示例:

HTML:

<div id="app">
    v-text:<span v-text="hello"></span> <br/>
    v-html:<span v-html="hello"></span>
</div>
複製代碼

JS:

var vm = new Vue({
    el:"#app",
    data:{
        hello: "<h1>你們好,我是峯哥</h1>"
    }
})
複製代碼

效果:

1529836688083

而且不會出現插值閃爍,當沒有數據時,會顯示空白。

5.2.v-model

剛纔的v-text和v-html能夠看作是單向綁定,數據影響了視圖渲染,可是反過來就不行。接下來學習的v-model是雙向綁定,視圖(View)和模型(Model)之間會互相影響。

既然是雙向綁定,必定是在視圖中能夠修改數據,這樣就限定了視圖的元素類型。目前v-model的可以使用元素有:

  • input
  • select
  • textarea
  • checkbox
  • radio
  • components(Vue中的自定義組件)

基本上除了最後一項,其它都是表單的輸入項。

舉例:

html:

<div id="app">
    <input type="checkbox" v-model="language" value="Java" />Java<br/>
    <input type="checkbox" v-model="language" value="PHP" />PHP<br/>
    <input type="checkbox" v-model="language" value="Swift" />Swift<br/>
    <h1>
        你選擇了:{{language.join(',')}}
    </h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var vm = new Vue({ el:"#app", data:{ language: [] } }) </script>
複製代碼
  • 多個CheckBox對應一個model時,model的類型是一個數組,單個checkbox值默認是boolean類型
  • radio對應的值是input的value值
  • texttextarea 默認對應的model是字符串
  • select單選對應字符串,多選對應也是數組

效果:

1529837541201

5.3.v-on

5.3.1.基本用法

v-on指令用於給頁面元素綁定事件。

語法:

v-on:事件名="js片斷或函數名"
複製代碼

示例:

<div id="app">
    <!--事件中直接寫js片斷-->
    <button v-on:click="num++">增長一個</button><br/>
    <!--事件指定一個回調函數,必須是Vue實例中定義的函數-->
    <button v-on:click="decrement">減小一個</button><br/>
    <h1>有{{num}}個女神迷戀峯哥</h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el:"#app", data:{ num:100 }, methods:{ decrement(){ this.num--; } } }) </script>
複製代碼

效果:

另外,事件綁定能夠簡寫,例如v-on:click='add'能夠簡寫爲@click='add'

5.3.2.事件修飾符

在事件處理程序中調用 event.preventDefault()event.stopPropagation() 是很是常見的需求。儘管咱們能夠在方法中輕鬆實現這點,但更好的方式是:方法只有純粹的數據邏輯,而不是去處理 DOM 事件細節。

爲了解決這個問題,Vue.js 爲 v-on 提供了事件修飾符。修飾符是由點開頭的指令後綴來表示的。

  • .stop :阻止事件冒泡到父元素
  • .prevent:阻止默認事件發生*
  • .capture:使用事件捕獲模式
  • .self:只有元素自身觸發事件才執行。(冒泡或捕獲的都不執行)
  • .once:只執行一次

阻止默認事件

<div id="app">
    <!--右擊事件,並阻止默認事件發生-->
    <button v-on:contextmenu.prevent="num++">增長一個</button>
    <br/>
    <!--右擊事件,不阻止默認事件發生-->
    <button v-on:contextmenu="decrement($event)">減小一個</button>
    <br/>
    <h1>有{{num}}個女神迷戀峯哥</h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el: "#app", data: { num: 100 }, methods: { decrement(ev) { // ev.preventDefault(); this.num--; } } }) </script>
複製代碼

效果:(右鍵「增長一個」,不會觸發默認的瀏覽器右擊事件;右鍵「減小一個」,會觸發默認的瀏覽器右擊事件)

5.3.3.按鍵修飾符

在監聽鍵盤事件時,咱們常常須要檢查常見的鍵值。Vue 容許爲 v-on 在監聽鍵盤事件時添加按鍵修飾符:

<!-- 只有在 `keyCode` 是 13 時調用 `vm.submit()` -->
<input v-on:keyup.13="submit">
複製代碼

記住全部的 keyCode 比較困難,因此 Vue 爲最經常使用的按鍵提供了別名:

<!-- 同上 -->
<input v-on:keyup.enter="submit">

<!-- 縮寫語法 -->
<input @keyup.enter="submit">
複製代碼

所有的按鍵別名:

  • .enter*
  • .tab
  • .delete (捕獲「刪除」和「退格」鍵)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

5.3.4.組合按鈕

能夠用以下修飾符來實現僅在按下相應按鍵時才觸發鼠標或鍵盤事件的監聽器。

  • .ctrl
  • .alt
  • .shift

例如:

<!-- Alt + C -->
<input @keyup.alt.67="clear">

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
複製代碼

5.4.v-for

遍歷數據渲染頁面是很是經常使用的需求,Vue中經過v-for指令來實現。

5.4.1.遍歷數組

語法:

v-for="item in items"
複製代碼
  • items:要遍歷的數組,須要在vue的data中定義好。
  • item:迭代獲得的數組元素的別名

示例

<div id="app">
    <ul>
        <li v-for="user in users">
            {{user.name}} - {{user.gender}} - {{user.age}}
        </li>
    </ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el: "#app", data: { users:[ {name:'柳巖', gender:'女', age: 21}, {name:'峯哥', gender:'男', age: 18}, {name:'范冰冰', gender:'女', age: 24}, {name:'劉亦菲', gender:'女', age: 18}, {name:'古力娜扎', gender:'女', age: 25} ] }, }) </script>
複製代碼

效果:

1530006198953

5.4.2.數組角標

在遍歷的過程當中,若是咱們須要知道數組角標,能夠指定第二個參數:

語法

v-for="(item,index) in items"


複製代碼
  • items:要迭代的數組
  • item:迭代獲得的數組元素別名
  • index:迭代到的當前元素索引,從0開始。

示例

<ul>
        <li v-for="(user, index) in users">
            {{index + 1}}. {{user.name}} - {{user.gender}} - {{user.age}}
        </li>
    </ul>
複製代碼

效果:

1530006094601

5.4.3.遍歷對象

v-for除了能夠迭代數組,也能夠迭代對象。語法基本相似

語法:

v-for="value in object"
v-for="(value,key) in object"
v-for="(value,key,index) in object"
複製代碼
  • 1個參數時,獲得的是對象的屬性值
  • 2個參數時,第一個是屬性值,第二個是屬性名
  • 3個參數時,第三個是索引,從0開始

示例:

<div id="app">
    <ul>
        <li v-for="(value, key, index) in user">
            {{index + 1}}. {{key}} - {{value}}
        </li>
    </ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var vm = new Vue({ el:"#app", data:{ user:{name:'峯哥', gender:'男', age: 18} } }) </script>
複製代碼

效果:

1530006251975

5.4.4.key

當 Vue.js 用 v-for 正在更新已渲染過的元素列表時,它默認用「就地複用」策略。若是數據項的順序被改變,Vue 將不會移動 DOM 元素來匹配數據項的順序, 而是簡單複用此處每一個元素,而且確保它在特定索引下顯示已被渲染過的每一個元素。

這個功能能夠有效的提升渲染的效率。

可是要實現這個功能,你須要給Vue一些提示,以便它能跟蹤每一個節點的身份,從而重用和從新排序現有元素,你須要爲每項提供一個惟一 key 屬性。理想的 key 值是每項都有的且惟一的 id。

示例:

<ul>
    <li v-for="(item,index) in items" :key=index></li>
</ul>
複製代碼
  • 這裏使用了一個特殊語法::key="" 咱們後面會講到,它可讓你讀取vue中的屬性,並賦值給key屬性
  • 這裏咱們綁定的key是數組的索引,應該是惟一的

5.5.v-if和v-show

5.5.1.基本使用

v-if,顧名思義,條件判斷。當獲得結果爲true時,所在的元素纔會被渲染。

語法:

v-if="布爾表達式"


複製代碼

示例:

<div id="app">
    <button v-on:click="show = !show">點我呀</button>
    <br>
    <h1 v-if="show">
        看到我啦?!
    </h1>
    <h1 v-show="show">
        看到我啦?!show
    </h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el: "#app", data: { show: true } }) </script>
複製代碼

效果:

5.5.2.與v-for結合

當v-if和v-for出如今一塊兒時,v-for優先級更高。也就是說,會先遍歷,再判斷條件。

修改v-for中的案例,添加v-if:

<ul>
        <li v-for="(user, index) in users" v-if="user.gender == '女'">
            {{index + 1}}. {{user.name}} - {{user.gender}} - {{user.age}}
        </li>
    </ul>
複製代碼

效果:

1530013415911

只顯示女性用戶信息

5.5.3.v-else

你可使用 v-else 指令來表示 v-if 的「else 塊」:

<div id="app">
    <h1 v-if="Math.random() > 0.5">
        看到我啦?!if
    </h1>
    <h1 v-else>
        看到我啦?!else
    </h1>
</div>
複製代碼

v-else 元素必須緊跟在帶 v-if 或者 v-else-if 的元素的後面,不然它將不會被識別。

v-else-if,顧名思義,充當 v-if 的「else-if 塊」,能夠連續使用:

<div id="app">
    <button v-on:click="random=Math.random()">點我呀</button><span>{{random}}</span>
    <h1 v-if="random >= 0.75">
        看到我啦?!if
    </h1>
    <h1 v-else-if="random > 0.5">
        看到我啦?!if 0.5
    </h1>
    <h1 v-else-if="random > 0.25">
        看到我啦?!if 0.25
    </h1>
    <h1 v-else>
        看到我啦?!else
    </h1>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el: "#app", data: { random: 1 } }) </script>
複製代碼

相似於 v-elsev-else-if 也必須緊跟在帶 v-if 或者 v-else-if 的元素以後。

演示:

1530013415911

5.5.4.v-show

另外一個用於根據條件展現元素的選項是 v-show 指令。用法大體同樣:

<h1 v-show="ok">Hello!</h1>


複製代碼

不一樣的是帶有 v-show 的元素始終會被渲染並保留在 DOM 中。v-show 只是簡單地切換元素的 CSS 屬性 display

示例:

<div id="app">
        <!--事件中直接寫js片斷-->
        <button v-on:click="show = !show">點擊切換</button><br/>
        <h1 v-if="show">
            你好
        </h1>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script type="text/javascript"> var app = new Vue({ el:"#app", data:{ show:true } }) </script>
複製代碼

代碼:

5.6.v-bind

html屬性不能使用雙大括號形式綁定,只能使用v-bind指令。

在將 v-bind 用於 class 和 style 時,Vue.js 作了專門的加強。表達式結果的類型除了字符串以外,還能夠是對象或數組。

<div id="app">
    <!--能夠是數據模型,能夠是具備返回值的js代碼塊或者函數-->
    <div v-bind:title="title" style="border: 1px solid red; width: 50px; height: 50px;"></div>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el: "#app", data: { title: "title", } }) </script>
複製代碼

效果:

1530025378843

在將 v-bind 用於 class 和 style 時,Vue.js 作了專門的加強。表達式結果的類型除了字符串以外,還能夠是對象或數組。

5.6.1.綁定class樣式

數組語法

咱們能夠藉助於v-bind指令來實現:

HTML:

<div id="app">
    <div v-bind:class="activeClass"></div>
    <div v-bind:class="errorClass"></div>
    <div v-bind:class="[activeClass, errorClass]"></div>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var app = new Vue({ el: "#app", data: { activeClass: 'active', errorClass: ['text-danger', 'text-error'] } }) </script>
複製代碼

渲染後的效果:(具備active和hasError的樣式)

1530026818515

對象語法

咱們能夠傳給 v-bind:class 一個對象,以動態地切換 class:

<div v-bind:class="{ active: isActive }"></div>
複製代碼

上面的語法表示 active 這個 class 存在與否將取決於數據屬性 isActivetruthiness(全部的值都是真實的,除了false,0,「」,null,undefined和NaN)。

你能夠在對象中傳入更多屬性來動態切換多個 class。此外,v-bind:class 指令也能夠與普通的 class 屬性共存。以下模板:

<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
複製代碼

和以下 data:

data: {
  isActive: true,
  hasError: false
}
複製代碼

結果渲染爲:

<div class="static active"></div>
複製代碼

active樣式和text-danger樣式的存在與否,取決於isActive和hasError的值。本例中isActive爲true,hasError爲false,因此active樣式存在,text-danger不存在。

5.6.2.綁定style樣式

數組語法

數組語法能夠將多個樣式對象應用到同一個元素上:

<div v-bind:style="[baseStyles, overridingStyles]"></div>
複製代碼

數據:

data: {
    baseStyles: {'background-color': 'red'},
    overridingStyles: {border: '1px solid black'}
}
複製代碼

渲染後的結果:

<div style="background-color: red; border: 1px solid black;"></div>
複製代碼

對象語法

v-bind:style 的對象語法十分直觀——看着很是像 CSS,但實際上是一個 JavaScript 對象。CSS 屬性名能夠用駝峯式 (camelCase) 或短橫線分隔 (kebab-case,記得用單引號括起來) 來命名:

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
複製代碼

數據:

data: {
  activeColor: 'red',
  fontSize: 30
}
複製代碼

效果:

<div style="color: red; font-size: 30px;"></div>
複製代碼

5.6.3.簡寫

v-bind:class能夠簡寫爲:class

5.7.計算屬性

在插值表達式中使用js表達式是很是方便的,並且也常常被用到。

可是若是表達式的內容很長,就會顯得不夠優雅,並且後期維護起來也不方便,例以下面的場景,咱們有一個日期的數據,可是是毫秒值:

data:{
    birthday:1529032123201 // 毫秒值
}
複製代碼

咱們在頁面渲染,但願獲得yyyy-MM-dd的樣式:

<h1>您的生日是:{{
    new Date(birthday).getFullYear() + '-'+ new Date(birthday).getMonth()+ '-' + new Date(birthday).getDay()
    }}
</h1>
複製代碼

雖然能獲得結果,可是很是麻煩。

Vue中提供了計算屬性,來替代複雜的表達式:

var vm = new Vue({
    el:"#app",
    data:{
        birthday:1429032123201 // 毫秒值
    },
    computed:{
        birth(){// 計算屬性本質是一個方法,可是必須返回結果
            const d = new Date(this.birthday);
            return d.getFullYear() + "-" + d.getMonth() + "-" + d.getDay();
        }
    }
})
複製代碼
  • 計算屬性本質就是方法,可是必定要返回數據。而後頁面渲染時,能夠把這個方法當成一個變量來使用。

頁面使用:

<div id="app">
       <h1>您的生日是:{{birth}} </h1>
    </div>
複製代碼

效果:

1530029950644

咱們能夠將同一函數定義爲一個方法而不是一個計算屬性。兩種方式的最終結果確實是徹底相同的。然而,不一樣的是計算屬性是基於它們的依賴進行緩存的。計算屬性只有在它的相關依賴發生改變時纔會從新求值。這就意味着只要birthday尚未發生改變,屢次訪問 birthday 計算屬性會當即返回以前的計算結果,而沒必要再次執行函數。

5.8.watch

watch可讓咱們監控一個值的變化。從而作出相應的反應。

示例:

<div id="app">
    <input type="text" v-model="message">
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var vm = new Vue({ el:"#app", data:{ message:"" }, watch:{ message(newVal, oldVal){ console.log(newVal, oldVal); } } }) </script>
複製代碼

效果:

1530030506879

6.組件化

在大型應用開發的時候,頁面能夠劃分紅不少部分。每每不一樣的頁面,也會有相同的部分。例如可能會有相同的頭部導航。

可是若是每一個頁面都獨自開發,這無疑增長了咱們開發的成本。因此咱們會把頁面的不一樣部分拆分紅獨立的組件,而後在不一樣頁面就能夠共享這些組件,避免重複開發。

在vue裏,全部的vue實例都是組件

6.1.全局組件

咱們經過Vue的component方法來定義一個全局組件。

<div id="app">
    <!--使用定義好的全局組件-->
    <counter></counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> // 定義全局組件,兩個參數:1,組件名稱。2,組件參數 Vue.component("counter",{ template:'<button v-on:click="count++">你點了我 {{ count }} 次,我記住了.</button>', data(){ return { count:0 } } }) var app = new Vue({ el:"#app" }) </script>
複製代碼
  • 組件其實也是一個Vue實例,所以它在定義時也會接收:data、methods、生命週期函數等
  • 不一樣的是組件不會與頁面的元素綁定,不然就沒法複用了,所以沒有el屬性。
  • 可是組件渲染須要html模板,因此增長了template屬性,值就是HTML模板
  • 全局組件定義完畢,任何vue實例均可以直接在HTML中經過組件名稱來使用組件了。
  • data必須是一個函數,再也不是一個對象。

效果:

6.2.組件的複用

定義好的組件,能夠任意複用屢次:

<div id="app">
    <!--使用定義好的全局組件-->
    <counter></counter>
    <counter></counter>
    <counter></counter>
</div>
複製代碼

效果:

1530084943778

你會發現每一個組件互不干擾,都有本身的count值。怎麼實現的?

組件的data屬性必須是函數

當咱們定義這個 <counter> 組件時,它的data 並非像以前直接提供一個對象:

data: {
  count: 0
}
複製代碼

取而代之的是,一個組件的 data 選項必須是一個函數,所以每一個實例能夠維護一份被返回對象的獨立的拷貝:

data: function () {
  return {
    count: 0
  }
}
複製代碼

若是 Vue 沒有這條規則,點擊一個按鈕就會影響到其它全部實例!

6.3.局部組件

一旦全局註冊,就意味着即使之後你再也不使用這個組件,它依然會隨着Vue的加載而加載。

所以,對於一些並不頻繁使用的組件,咱們會採用局部註冊。

咱們先在外部定義一個對象,結構與建立組件時傳遞的第二個參數一致:

const counter = {
    template:'<button v-on:click="count++">你點了我 {{ count }} 次,我記住了.</button>',
    data(){
        return {
            count:0
        }
    }
};
複製代碼

而後在Vue中使用它:

var app = new Vue({
    el:"#app",
    components:{
        counter:counter // 將定義的對象註冊爲組件
    }
})
複製代碼
  • components就是當前vue對象子組件集合。
    • 其key就是子組件名稱
    • 其值就是組件對象名
  • 效果與剛纔的全局註冊是相似的,不一樣的是,這個counter組件只能在當前的Vue實例中使用

6.4.組件通訊

一般一個單頁應用會以一棵嵌套的組件樹的形式來組織:

1525855149491

  • 頁面首先分紅了頂部導航、左側內容區、右側邊欄三部分
  • 左側內容區又分爲上下兩個組件
  • 右側邊欄中又包含了3個子組件

各個組件之間以嵌套的關係組合在一塊兒,那麼這個時候不可避免的會有組件間通訊的需求。

6.4.1.props(父向子傳遞)

  1. 父組件使用子組件時,自定義屬性(屬性名任意,屬性值爲要傳遞的數據)
  2. 子組件經過props接收父組件數據,經過自定義屬性的屬性名

父組件使用子組件,並自定義了title屬性:

<div id="app">
    <h1>打個招呼:</h1>
    <!--使用子組件,同時傳遞title屬性-->
    <introduce title="你們好,我是鋒哥"/>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> Vue.component("introduce",{ // 直接使用props接收到的屬性來渲染頁面 template:'<h1>{{title}}</h1>', props:['title'] // 經過props來接收一個父組件傳遞的屬性 }) var app = new Vue({ el:"#app" }) </script>
複製代碼

效果:

1530093525973

6.4.2.props驗證

咱們定義一個子組件,並接收復雜數據:

const myList = {
        template: '\ <ul>\ <li v-for="item in items" :key="item.id">{{item.id}} : {{item.name}}</li>\ </ul>\ ',
        props: {
            items: {
                type: Array,
                default: [],
                required: true
            }
        }
    };
複製代碼
  • 這個子組件能夠對 items 進行迭代,並輸出到頁面。
  • props:定義須要從父組件中接收的屬性
    • items:是要接收的屬性名稱
      • type:限定父組件傳遞來的必須是數組
      • default:默認值
      • required:是否必須

當 prop 驗證失敗的時候,(開發環境構建版本的) Vue 將會產生一個控制檯的警告。

咱們在父組件中使用它:

<div id="app">
    <h2>傳智播客已開設以下課程:</h2>
    <!-- 使用子組件的同時,傳遞屬性,這裏使用了v-bind,指向了父組件本身的屬性lessons -->
    <my-list :items="lessons"/>
</div>
複製代碼
var app = new Vue({
    el:"#app",
    components:{
        myList // 當key和value同樣時,能夠只寫一個
    },
    data:{
        lessons:[
            {id:1, name: 'java'},
            {id:2, name: 'php'},
            {id:3, name: 'ios'},
        ]
    }
})
複製代碼

效果:

1530107338625

type類型,能夠有:

1530108427358

注意:子組件模板有且只有一個根標籤

6.4.3.動態靜態傳遞

給 prop 傳入一個靜態的值:

<introduce title="你們好,我是鋒哥"/>
複製代碼

給 prop 傳入一個動態的值: (經過v-bind從數據模型中,獲取title的值)

<introduce :title="title"/>
複製代碼

靜態傳遞時,咱們傳入的值都是字符串類型的,但實際上任何類型的值均可以傳給一個 props。

<!-- 即使 `42` 是靜態的,咱們仍然須要 `v-bind` 來告訴 Vue -->
<!-- 這是一個JavaScript表達式而不是一個字符串。-->
<blog-post v-bind:likes="42"></blog-post>

<!-- 用一個變量進行動態賦值。-->
<blog-post v-bind:likes="post.likes"></blog-post>
複製代碼

6.4.4.子向父的通訊:$emit

來看這樣的一個案例:

<div id="app">
    <h2>num: {{num}}</h2>
    <!--使用子組件的時候,傳遞num到子組件中-->
    <counter :num="num"></counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> Vue.component("counter", {// 子組件,定義了兩個按鈕,點擊數字num會加或減 template:'\ <div>\ <button @click="num++">加</button> \ <button @click="num--">減</button> \ </div>', props:['num']// count是從父組件獲取的。 }) var app = new Vue({ el:"#app", data:{ num:0 } }) </script>
複製代碼
  • 子組件接收父組件的num屬性
  • 子組件定義點擊按鈕,點擊後對num進行加或減操做

咱們嘗試運行,好像沒問題,點擊按鈕試試:

1525859093172

子組件接收到父組件屬性後,默認是不容許修改的。怎麼辦?

既然只有父組件能修改,那麼加和減的操做必定是放在父組件:

var app = new Vue({
    el:"#app",
    data:{
        num:0
    },
    methods:{ // 父組件中定義操做num的方法
        increment(){
            this.num++;
        },
        decrement(){
            this.num--;
        }
    }
})
複製代碼

可是,點擊按鈕是在子組件中,那就是說須要子組件來調用父組件的函數,怎麼作?

咱們能夠經過v-on指令將父組件的函數綁定到子組件上:

<div id="app">
    <h2>num: {{num}}</h2>
    <counter :count="num" @inc="increment" @dec="decrement"></counter>
</div>
複製代碼

在子組件中定義函數,函數的具體實現調用父組件的實現,並在子組件中調用這些函數。當子組件中按鈕被點擊時,調用綁定的函數:

Vue.component("counter", {
            template:'\ <div>\ <button @click="plus">加</button> \ <button @click="reduce">減</button> \ </div>',
            props:['count'],
            methods:{
                plus(){
                    this.$emit("inc");
                },
                reduce(){
                    this.$emit("dec");
                }
            }
        })
複製代碼
  • vue提供了一個內置的this.$emit()函數,用來調用父組件綁定的函數

效果:

7.路由vue-router

7.1.場景模擬

如今咱們來實現這樣一個功能:

一個頁面,包含登陸和註冊,點擊不一樣按鈕,實現登陸和註冊頁切換:

7.1.1.編寫父組件

爲了讓接下來的功能比較清晰,咱們先新建一個文件夾:src

而後新建一個HTML文件,做爲入口:index.html

1530148321175

而後編寫頁面的基本結構:

<div id="app">
    <span>登陸</span>
    <span>註冊</span>
    <hr/>
    <div>
        登陸頁/註冊頁
    </div>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script type="text/javascript"> var vm = new Vue({ el:"#app" }) </script>
複製代碼

樣式:

1530149363817

7.1.2.編寫登陸及註冊組件

接下來咱們來實現登陸組件,之前咱們都是寫在一個文件中,可是爲了複用性,開發中都會把組件放入獨立的JS文件中,咱們新建一個user目錄以及login.js及register.js:

1530156389366

編寫組件,這裏咱們只寫模板,不寫功能。

login.js內容以下:

const loginForm = {
    template:'\ <div>\ <h2>登陸頁</h2> \ 用戶名:<input type="text"><br/>\ 密碼:<input type="password"><br/>\ </div>\ '
}
複製代碼

register.js內容:

const registerForm = {
    template:'\ <div>\ <h2>註冊頁</h2> \ 用&ensp;戶&ensp;名:<input type="text"><br/>\ 密&emsp;&emsp;碼:<input type="password"><br/>\ 確認密碼:<input type="password"><br/>\ </div>\ '
}
複製代碼

7.1.3.在父組件中引用

<div id="app">
    <span>登陸</span>
    <span>註冊</span>
    <hr/>
    <div>
        <!--<loginForm></loginForm>-->
        <!-- 疑問:爲何不採用上面的寫法? 因爲html是大小寫不敏感的,若是採用上面的寫法,則被認爲是<loginform></loginform> 因此,若是是駝峯形式的組件,須要把駝峯轉化爲「-」的形式 -->
        <login-form></login-form>
        <register-form></register-form>
    </div>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script src="user/login.js"></script>
<script src="user/register.js"></script>
<script type="text/javascript"> var vm = new Vue({ el: "#app", components: { loginForm, registerForm } }) </script>
複製代碼

效果:

1530157389501

7.1.5.問題

咱們期待的是,當點擊登陸或註冊按鈕,分別顯示登陸頁或註冊頁,而不是一塊兒顯示。

可是,如何才能動態加載組件,實現組件切換呢?

雖然使用原生的Html5和JS也能實現,可是官方推薦咱們使用vue-router模塊。

7.2.vue-router簡介和安裝

使用vue-router和vue能夠很是方便的實現 複雜單頁應用的動態路由功能。

官網:router.vuejs.org/zh-cn/

使用npm安裝:npm install vue-router --save

1530161293338

在index.html中引入依賴:

<script src="../node_modules/vue-router/dist/vue-router.js"></script>
複製代碼

7.3.快速入門

新建vue-router對象,而且指定路由規則:

// 建立VueRouter對象
const router = new VueRouter({
    routes:[ // 編寫路由規則
        {
            path:"/login", // 請求路徑,以「/」開頭
            component:loginForm // 組件名稱
        },
        {
            path:"/register",
            component:registerForm
        }
    ]
})
複製代碼
  • 建立VueRouter對象,並指定路由參數
  • routes:路由規則的數組,能夠指定多個對象,每一個對象是一條路由規則,包含如下屬性:
    • path:路由的路徑
    • component:組件名稱

在父組件中引入router對象:

var vm = new Vue({
    el:"#app",
    components:{// 引用登陸和註冊組件
        loginForm,
        registerForm
    },
    router // 引用上面定義的router對象
})
複製代碼

頁面跳轉控制:

<div id="app">
    <!--router-link來指定跳轉的路徑-->
    <span><router-link to="/login">登陸</router-link></span>
    <span><router-link to="/register">註冊</router-link></span>
    <hr/>
    <div>
        <!--vue-router的錨點-->
        <router-view></router-view>
    </div>
</div>
複製代碼
  • 經過<router-view>來指定一個錨點,當路由的路徑匹配時,vue-router會自動把對應組件放到錨點位置進行渲染
  • 經過<router-link>指定一個跳轉連接,當點擊時,會觸發vue-router的路由功能,路徑中的hash值會隨之改變

效果:

注意:單頁應用中,頁面的切換並非頁面的跳轉。僅僅是地址最後的hash值變化。

事實上,咱們總共就一個HTML:index.html

更多詳情

請訪問: juntech.top

相關文章
相關標籤/搜索