第六章 前端開發——Vue框架

第六章 前端開發學習——Vue框架javascript

 

1、Vue介紹css

2、Vue實例html

3、Vue視圖前端

4、Vue組件vue

5、Vue過分動畫java

 

1、Vue介紹webpack

1.前端框架介紹web

A)前端框架有npm

  • React      Facebook
  • Angular   Google
  • Vue         全世界

B)Angular、Vue、React的區別bootstrap

Vue與React

  • React與Vue 都採用虛擬DOM
  • 核心功能都在覈心庫中,其餘相似路由這樣的功能則由其餘庫進行處理
  • React的生態系統更龐大,由ReactNative來進行混合App開發; Vue更輕量
  • React由獨特的JSX語法; Vue是基於傳統的Web計數進行擴展(HTML、CSS、JavaScript),更容易學習

Vue與Angular

  • Angular1和Angular2之後的版本 是徹底不一樣的兩個框架; 通常Angular1被稱做Angular.js, Angular以後的版本被稱做 Angular

  • Vue與Angular的語法很是類似

  • Vue沒有像Angular同樣深刻開發,只保證了基本功能。 Angular過於笨重

  • Vue的運行速度比Angular快得多

  • Angular的髒檢查機制帶來諸多性能問題

 

2.什麼是Vue(what):

  • Vue 是一套用於構建用戶界面的漸進式框架
  • 使用Vue框架,能夠徹底在瀏覽器端渲染頁面,服務端只提供數據
  • 使用Vue框架能夠很是方便的構建 單頁面應用 (SPA)

Vue與JQuery的區別:

  • jQuery 仍然是操做DOM的思想, 主要jQuery 用來寫頁面特效

  • Vue是前端框架(MVVM) ,對項目進行分層。 處理數據

Vue優勢:

  • 不存在依賴
  • 輕便(25k min)
  • 適用範圍廣(大中小型項目、PC、移動端、混合開發)
  • 本土框架,社區很是活躍
  • 語法簡單、學習成本低
  • 雙向數據綁定(所見即所得)

MVVM

  • M 模型層 Model

  • V 視圖層 View

  • VM (控制層) VIEW-MODEL

 

3.多頁面應用與單頁面應用

A)多頁面應用(MultiPage Application,MPA)

多頁面跳轉刷新全部資源,每一個公共資源(js、css等)需選擇性從新加載,經常使用於 app 或 客戶端等

B)單頁面應用(SinglePage Web Application,SPA)

只有一張Web頁面的應用,是一種從Web服務器加載的富客戶端,單頁面跳轉僅刷新局部資源 ,公共資源(js、css等)僅需加載一次,經常使用於PC端官網、購物等網站

二者對比:

 

4.Vue入門

A)安裝

方式一:直接<script>引入

方式二:CDN

  • https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js
  • https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js
  • # 以手動指定版本號

方式三:NPM

在用 Vue 構建大型應用時推薦使用 NPM 安裝[1]。NPM 能很好地和諸如 webpack 或 Browserify 模塊打包器配合使用。同時 Vue 也提供配套工具來開發單文件組件。

npm install vue

方式四:構建工具 (CLI)

npm install -g @vue/cli

vue create my-project

 

2、Vue實例

1.建立實例

A)建立實例

var app = new Vue({
  el: '#app',

})
  • 每一個 Vue 應用都是經過用 Vue 函數建立一個新的 Vue 實例開始的
  • 一個 Vue 應用由一個經過 new Vue 建立的根 Vue 實例,以及可選的嵌套的、可複用的組件樹組成。

B)掛載元素

 

2.數據與方法

A)添加數據data

Vue({
    
    data: {
        
    }
})
  • 當一個 Vue 實例被建立時,它向 Vue 的響應式系統中加入了其 data 對象中能找到的全部的屬性。當這些屬性的值發生改變時,視圖將會產生「響應」,即匹配更新爲新的值。
  • 只有當實例被建立時 data 中存在的屬性纔是響應式的
  • 若是你知道你會在晚些時候須要一個屬性,可是一開始它爲空或不存在,那麼你僅須要設置一些初始值

B)實例方法

Vue 實例還暴露了一些有用的實例屬性與方法。它們都有前綴 $,以便與用戶定義的屬性區分開來

  • vm.$el
  • vm.$data
  • vm.$watch(dataAttr, fn)

 

3.計算屬性和偵聽器

A)添加方法methods

Vue({
    methods: {
        
    }
})
  • methods用來裝載能夠調用的函數,你能夠直接經過 Vue 實例訪問這些方法,或者在指令表達式中使用。方法中的 this 自動綁定爲 Vue 實例。

B)添加計算屬性computed

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue</title>
    <style>
        p {
            border:1px solid #ccc;
            padding: 20px;
            width: 400px;
        }
    </style>
</head>
<body>
    <div id="app">
        <h1>Vue計算屬性</h1>
        <hr>
        firstName: <input type="text" v-model='firstName'> <br>
        lastName: <input type="text" v-model='lastName'> <br>
        <p>
            {{ fullName }}
        </p>
    </div>


    <script src="../vue.js"></script>
    <script>
        //建立Vue實例
        let vm = new Vue({
            el:'#app',
            data: {
                firstName:'',
                lastName:''
            },
            computed: {
                fullName: function(){
                    return this.firstName + this.lastName
                }
            }
        });

        //console.log(vm.fullName)
        //console.log(typeof vm.fullName)
    </script>
</body>
</html>
計算屬性應用

Vue({
    computed: {
        屬性名: function(){
            
        }
    }
})
  • 模板內的表達式很是便利,可是設計它們的初衷是用於簡單運算的。在模板中放入太多的邏輯會讓模板太重且難以維護,這時候應該使用計算屬性

C)添加偵聽屬性watch

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue</title>
    <style>
        p {
            border:1px solid #ccc;
            padding: 20px;
            width: 400px;
        }
    </style>
</head>
<body>
    <div id="app">
        <h1>Vue計算屬性</h1>
        <hr>
        請輸入全名: <input type="text" v-model='fullName'>
        <p>
            lastName: {{ lastName }}
        </p>
        <p>
            firstName: {{ firstName }}
        </p>
    </div>


    <script src="../vue.js"></script>
    <script>
        //建立Vue實例
        let vm = new Vue({
            el:'#app',
            data: {
                fullName:'',
                firstName:'',
                lastName:''
            },
            watch: {
                fullName: function(){
                    this.firstName = this.fullName.split(' ')[0]
                    this.lastName = this.fullName.split(' ')[1]
                }
            }
    
        })
    </script>
</body>
</html>
偵聽屬性應用

Vue({
    watch: {
        屬性: function(){
            
        }
    }
})
  • 雖然計算屬性在大多數狀況下更合適,但有時也須要一個自定義的偵聽器。這就是爲何 Vue 經過 watch 選項提供了一個更通用的方法,來響應數據的變化。當須要在數據變化時執行異步或開銷較大的操做時,這個方式是最有用的

 

D)方法,計算屬性,偵聽屬性的區別

它們三者都是以函數爲主體,可是它們之間卻各有區別。

計算屬性與方法:

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

相比之下,每當觸發從新渲染時,調用方法將總會再次執行函數。

計算屬性與偵聽屬性:

  • watch擅長處理的場景:一個數據影響多個數據
  • computed擅長處理的場景:多個數據影響一個數據

4.delimiters

做用:改變純文本插入分隔符。

 

 

5.生命週期

A)生命週期鉤子函數(紅色重要經常使用

(1)beforeCreate

在實例初始化以後,數據觀測(data observer)和 event/watcher 事件配置以前被調用。

(2)created:

數據建立成功 data methods computed watch
在這裏從服務器獲取數據

在實例建立完成後被當即調用。在這一步,實例已完成如下的配置:數據觀測(data observer)、屬性和方法的運算、watch/event 事件回調。然而,掛載階段還沒開始,$el 屬性目前不可見。

(3)beforeMount

在掛載開始以前被調用,相關的 render 函數將首次被調用。

注意:該鉤子在服務器端渲染期間不被調用。

(4)mounted:此時,Vue實例已經掛載到元素上。 操做DOM請在這裏

el 被新建立的 vm.el替換,並掛載到實例上去以後調用該鉤子。若是root實例掛載了一個文檔內元素,當mounted被調用時vm.el 也在文檔內。頁面渲染完成後初始化的處理均可以放在這裏。

注意:mounted 不會承諾全部的子組件也都一塊兒被掛載。

(5)beforeUpdate

數據更新時調用,發生在虛擬 DOM 從新渲染和打補丁以前。

你能夠在這個鉤子中進一步地更改狀態,這不會觸發附加的重渲染過程。

(6)updated

因爲數據更改致使的虛擬 DOM 從新渲染和打補丁,在這以後會調用該鉤子。

當這個鉤子被調用時,組件 DOM 已經更新,因此你如今能夠執行依賴於 DOM 的操做。然而在大多數狀況下,你應該避免在此期間更改狀態。若是要相應狀態改變,一般最好使用計算屬性或 watcher 取而代之。

注意:updated 不會承諾全部的子組件也都一塊兒被重繪。

(7)activated

keep-alive 組件激活時調用。

(8)deactivated

keep-alive 組件停用時調用。

(9)beforeDestroy

實例銷燬以前調用。在這一步,實例仍然徹底可用。

(10)destroyed

Vue 實例銷燬後調用。調用後,Vue 實例指示的全部東西都會解綁定,全部的事件監聽器會被移除,全部的子實例也會被銷燬。

B)生命週期圖示

 

3、Vue視圖

1.基本模板語法

 A)文本

  • 數據綁定最多見的形式就是使用「Mustache」語法 (雙大括號) 的文本插值
  • v-text 指令也能夠用於數據綁定,若是要更新部分的 textContent ,須要使用 插值。
  • 經過使用 v-once 指令,你也能執行一次性地插值,當數據改變時,插值處的內容不會更新

B)原始HTML

雙大括號會將數據解釋爲普通文本,而非 HTML 代碼。爲了輸出真正的 HTML,你須要使用 v-html 指令

Tips:你的站點上動態渲染的任意 HTML 可能會很是危險,由於它很容易致使 XSS 攻擊。請只對可信內容使用 HTML 插值,毫不要對用戶提供的內容使用插值。

C)屬性

  • Mustache語法不能做用在 HTML 特性上,遇到這種狀況應該使用 v-bind 指令
  • 在布爾屬性的狀況下,它們的存在即暗示爲 true, 若是值是 null、undefined 或 false,則屬性不會被包含在渲染出來的

 D)使用JavaScript表達式(不建議)

  • {{ number + 1 }}
  • {{ ok ? 'YES' : 'NO' }}
  • {{ message.split('').reverse().join('') }}
  • <div v-bind:id="'list-' + id"></div>
  • {{ var a = 1 }}    <!-- 這是語句,不是表達式 -->
  • {{ if (ok) { return message } }}    <!-- 流控制也不會生效,請使用三元表達式 -->

E)防止刷新或加載閃爍

  • v-cloak並不須要添加到每一個標籤,只要在el掛載的標籤上添加就能夠
  •  

 

2.指令

A)指令

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

B)指令列表

  • v-text
  • v-html
  • v-show
  • v-if
  • v-else
  • v-else-if
  • v-for
  • v-on
  • v-bind
  • v-model
  • v-pre
  • v-cloak
  • v-once

C)縮寫

v-bind縮寫

<!-- 完整語法 -->
<a v-bind:href="url">...</a>

<!-- 縮寫 -->
<a :href="url">...</a>

v-on縮寫

<!-- 完整語法 -->
<a v-on:click="doSomething">...</a>

<!-- 縮寫 -->
<a @click="doSomething">...</a>

 

3.條件渲染與列表渲染

A)條件渲染

相關指令

  • v-if
  • v-else
  • v-else-if
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue條件渲染</title>
    <style>
        .box {
            border:1px solid #ccc;
            padding: 10px;
            width: 600px;
        }
    </style>
</head>
<body>

    <div id="app">
        <h1>條件渲染</h1>
        <hr>
        <button @click="isShow = !isShow">改變</button>
        <!-- <div class="box" v-if="true">
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rem quo saepe, eum nisi. Atque, pariatur ad sapiente alias, dignissimos tempora iusto ullam veritatis, obcaecati ipsa dicta sunt dolorem ducimus eos!
        </div> -->
        
        <template v-if="isShow">
            <h2>鋤禾</h2>
            <p>鋤禾日黨務</p>
            <p>鋤禾日黨務</p>
            <p>鋤禾日黨務</p>
        </template>
        


        <div class="box" v-else>
            HELLO 同志
        </div>


        <hr>

        <input type="number" v-model="tag" max="3" min="0" step="1">

        <div class="box" v-if="tag == 0" key="1">
            00000000000000000000000000
        </div>

        <div class="box" v-else-if="tag == 1" key="2">
            1111111111111111111111111111
        </div>

        <div class="box" v-else-if="tag == 2" key="3">
            222222222222222222222222222222
        </div>

        <div class="box" v-else key="4">
            else esle else else else else
        </div>


        <hr>


        <p v-show="false">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ipsam incidunt perspiciatis, soluta repellendus ipsa placeat hic? Aspernatur modi, corporis incidunt deserunt accusantium laudantium, voluptates maxime eveniet maiores a labore nam.</p>
    </div>
    
    
    <script src="../vue.js"></script>
    <script>
        new Vue({
            el:'#app',
            data: {
                isShow: true,
                tag:0
            }
        })
    </script>
</body>
</html>
條件渲染

控制多個元素

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

複用已有元素

  • Vue 會盡量高效地渲染元素,一般會複用已有元素而不是從頭開始渲染
  • 要想每次都從新渲染,只需添加一個具備惟一值的 key 屬性

v-show

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

與 v-if 的區別

  • v-if 是「真正」的條件渲染,由於它會確保在切換過程當中條件塊內的事件監聽器和子組件適當地被銷燬和重建。
  • v-show 就簡單得多——無論初始條件是什麼,元素老是會被渲染,而且只是簡單地基於 CSS 進行切換。
  • 通常來講,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。所以,若是須要很是頻繁地切換,則使用 v-show 較好;若是在運行時條件不多改變,則使用 v-if 較好。

 

B)列表渲染

遍歷數組

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>列表渲染</title>
</head>
<body>
    <div id="app">
        <h1>列表渲染</h1>
        <hr>
        <button @click="updateItemList()">更新數組</button>
        <ul>
            <li v-for="(item,index) in itemList"> {{index}} {{item}} </li>
        </ul>

        <table>
            <tr>
                <th>序號</th>
                <th>姓名</th>
                <th>年齡</th>
                <th>工做</th>
                <th>地址</th>
            </tr>
            <tr v-for="item in dataList" :key="item.id" v-if="item.id > 2">
                <td>{{ item.id }}</td>
                <td>{{ item.name }}</td>
                <td>{{ item.age }}</td>
                <td>{{ item.job }}</td>
                <td>{{ item.address }}</td>
            </tr>
        </table>
    </div>

    <script src="../vue.js"></script>
    <script>
        new Vue({
            el:'#app',
            data: {
                itemList: ['曹操', '諸葛亮', '劉備', '孫權', '周瑜', '董卓'],
                dataList: [
                    {id:1, name:'曹操', age:19, job:'大王', address:'許都'},
                    {id:2,name:'諸葛亮', age:19, job:'丞相', address:'許都'},
                    {id:3,name:'劉備', age:19, job:'大王', address:'許都'},
                    {id:4,name:'孫權', age:19, job:'大王', address:'許都'},
                    {id:5,name:'董卓', age:19, job:'大王', address:'許都'}
                ]
            },
            methods: {
                updateItemList: function(){
                    //this.itemList[1] = '賈寶玉'
                    //this.itemList.push('賈寶玉');
                    //this.itemList.pop();
                    //this.itemList.reverse();
                    Vue.set(this.itemList, 1, '趙雲')
                }
            }
        })
    </script>
</body>
</html>
列表渲染

 

<ul id="example-1">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>

v-for 還支持一個可選的第二個參數爲當前項的索引

<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ index }} - {{ item.message }}
  </li>
</ul>

遍歷對象

<!-- 只取值 -->
<li v-for="value in object">
  {{ value }}
</li>

<!-- 值、屬性名 -->
<div v-for="(value, key) in object">
  {{ key }}: {{ value }}
</div>

<!--值、屬性名、索引-->
<div v-for="(value, key, index) in object">
  {{ index }}. {{ key }}: {{ value }}
</div>

key

  • 當 Vue.js 用 v-for 正在更新已渲染過的元素列表時,它默認用「就地複用」策略。
  • 這個默認的模式是高效的,可是隻適用於不依賴子組件狀態或臨時 DOM 狀態 的列表渲染輸出。
  • 爲了給 Vue 一個提示,以便它能跟蹤每一個節點的身份,從而重用和從新排序現有元素,你須要爲每項提供一個惟一 key 屬性。由於在遍歷,須要用 v-bind 來綁定動態值
  • 建議儘量在使用 v-for 時提供 key,除非遍歷輸出的 DOM 內容很是簡單,或者是刻意依賴默認行爲以獲取性能上的提高。

更新檢測

數組

因爲 JavaScript 的限制,Vue 不能檢測如下變更的數組:

​ 當你利用索引直接設置一個項時,例如:vm.items[indexOfItem] = newValue 當你修改數組的長度時,例如:vm.items.length = newLength

對象

仍是因爲 JavaScript 的限制,Vue 不能檢測對象屬性的添加或刪除

方法

  • Vue.set()
  • vm.$set()

遍歷數字

<div>
  <span v-for="n in 10">{{ n }} </span>
</div>

v-for on <tmplate>

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

v-for 和 v-if

當它們處於同一節點,v-for 的優先級比 v-if 更高,這意味着 v-if 將分別重複運行於每一個 v-for 循環中。

<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo }}
</li>

 

3.樣式

A)綁定HTML Class

對象語法

方法一:

<div v-bind:class="{ active: isActive }"></div>

方法二:

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

方法三:

 <div v-bind:class="classObject"></div>

 

數組語法

<div v-bind:class="[activeClass, errorClass]"></div>

 

B)綁定內聯樣式

對象語法

方法一:

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

方法二:

<div v-bind:style="styleObject"></div>

 

 

數組語法

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

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

 

自動添加前綴

當 v-bind:style 使用須要添加瀏覽器引擎前綴的 CSS 屬性時,如 transform,Vue.js 會自動偵測並添加相應的前綴。

 

4.事件綁定

A)事件綁定

監聽事件

事件處理方法

<div id="example-2">
  <!-- `greet` 是在下面定義的方法名 -->
  <button v-on:click="greet">Greet</button>
</div>

內聯調用方法

 

有時也須要在內聯語句處理器中訪問原始的 DOM 事件。能夠用特殊變量 $event 把它傳入方法

<button v-on:click="warn('Form cannot be submitted yet.', $event)">
  Submit
</button>

 

B)事件修飾符

  • .stop
  • <!-- 阻止單擊事件繼續傳播 阻止事件冒泡-->
    <a v-on:click.stop="doThis"></a>
  • .prevent
  • <!-- 提交事件再也不重載頁面 阻止默認事件-->
    <form v-on:submit.prevent="onSubmit"></form>
  • .capture
  • <!-- 添加事件監聽器時使用事件捕獲模式 -->
    <!-- 即元素自身觸發的事件先在此到處理,而後才交由內部元素進行處理 -->
    <div v-on:click.capture="doThis">...</div>
  • .self
  • <!-- 只當在 event.target 是當前元素自身時觸發處理函數 -->
    <!-- 即事件不是從內部元素觸發的 -->
    <div v-on:click.self="doThat">...</div>
  • .once
  • <!-- 點擊事件將只會觸發一次 2.1.4新增-->
    <a v-on:click.once="doThis"></a>
  • .passive
  • <!-- 滾動事件的默認行爲 (即滾動行爲) 將會當即觸發 2.3.0新增-->
    <!-- 而不會等待 `onScroll` 完成  -->
    <!-- 這其中包含 `event.preventDefault()` 的狀況 -->
    <!--.passive 修飾符尤爲可以提高移動端的性能。-->
    <div v-on:scroll.passive="onScroll">...</div>

補充:

①修飾符能夠串聯

<a v-on:click.stop.prevent="doThat"></a>

②容許只有修飾符

<form v-on:submit.prevent></form>

 

C)按鍵修飾符

數字

按鍵別名

  • .enter(回車)
  • <!-- 回車鍵 -->
    <input v-on:keyup.enter="submit">
  • <!-- 只有在 `keyCode` 是 13 時(ASCII碼13是回車鍵)調用 `vm.submit()` -->
    <input v-on:keyup.13="submit">
  • .tab
  • .delete (捕獲「刪除」和「退格」鍵)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

 

D)系統修飾鍵

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

  • .ctrl
  • .alt
  • .shift
  • .meta
  • 注意:在 Mac 系統鍵盤上,meta 對應 command 鍵 (⌘)。在 Windows 系統鍵盤 meta 對應 Windows 徽標鍵 (⊞)。在 Sun 操做系統鍵盤上,meta 對應實心寶石鍵 (◆)。在其餘特定鍵盤上,尤爲在 MIT 和 Lisp 機器的鍵盤、以及其後繼產品,好比 Knight 鍵盤、space-cadet 鍵盤,meta 被標記爲「META」。在 Symbolics 鍵盤上,meta 被標記爲「META」或者「Meta」。

組合鍵

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

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

 

5.表單輸入綁定

你能夠用 v-model 指令在表單 <input> 及 <textarea> 元素上建立雙向數據綁定。它會根據控件類型自動選取正確的方法來更新元素。

v-model 會忽略全部表單元素的 value、checked、selected 特性的初始值而老是將 Vue 實例的數據做爲數據來源。你應該經過 JavaScript 在組件的 data 選項中聲明初始值。

A)基礎語法

①文本

<input v-model="message" placeholder="edit me">
<textarea v-model="message" placeholder="add multiple lines"></textarea>

②複選框

單個複選框

<input type="checkbox" id="checkbox" v-model="checked">

<input
  type="checkbox"
  v-model="toggle"
  true-value="yes"
  false-value="no"
>

多個複選框

<div id='example'>
  <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="john" value="John" v-model="checkedNames">
  <label for="john">John</label>
  <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
  <label for="mike">Mike</label>
  <br>
  <span>Checked names: {{ checkedNames }}</span>
</div>

 

 

③單選按鈕

綁定value對應的字符串

<div id="example">
  <input type="radio" id="one" value="One" v-model="picked">
  <label for="one">One</label>
  <br>
  <input type="radio" id="two" value="Two" v-model="picked">
  <label for="two">Two</label>
  <br>
  <span>Picked: {{ picked }}</span>
</div>

④選擇框

單選,綁定對應所選的值

<div id="example">
  <select v-model="selected">
    <option disabled value="">請選擇</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <span>Selected: {{ selected }}</span>
</div>

多選時 ,綁定到一個數組

<div id="example">
  <select v-model="selected" multiple style="width: 50px;">
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <br>
  <span>Selected: {{ selected }}</span>
</div>

B)修飾符

.lazy

在默認狀況下,v-model 在每次 input 事件觸發後將輸入框的值與數據進行同步

添加 lazy 修飾符,從而轉變爲使用 change 事件進行同步

<!-- 在「change」時而非「input」時更新 -->
<input v-model.lazy="msg" >

.number

若是想自動將用戶的輸入值轉爲數值類型,能夠給 v-model 添加 number 修飾符

<input v-model.number="age" type="number">

.trim

自動過濾用戶輸入的首尾空白字符,能夠給 v-model 添加 trim 修飾符

<input v-model.trim="msg">

 

4、Vue組件

什麼是組件(what):

組件(Component)是 Vue.js 最強大的功能之一。組件能夠擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器爲它添加特殊功能。在有些狀況下,組件也能夠表現爲用 is 特性進行了擴展的原生 HTML 元素。

全部的 Vue 組件同時也都是 Vue 的實例,因此可接受相同的選項對象(除了一些根級特有的選項)並提供相同的生命週期鉤子。

如何理解組件:

簡單理解,每一個Page就是一個組件 (註冊組件、登陸組件、商品列表組件),頁面的組成部分 (輪播圖,選項卡,下拉菜單...),件其實就是一個獨立的 HTML,它的內部可能有各類結構、樣式、邏輯,某些地方來講有些像 iframe,它都是在頁面中引入以後展示另外一個頁面的內容,但實際上它與 iframe 又徹底不一樣,iframe 是一個獨立封閉的內容,而組件既是一個獨立的內容,仍是一個受引入頁面控制的內容。

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

例如,你可能會有頁頭、側邊欄、內容區等組件,每一個組件又包含了其它的像導航連接、博文之類的組件。

爲何要使用組件(why):

舉個簡單的列子,最近個人項目中有一個日曆模塊,多個頁面都要用這個日曆,而每一個頁面的日曆都存在一些差異,若是不使用組件,我要完成這個項目,作到各個頁面的日曆大致一致,而部分地方存在差別,我可能就須要寫幾套日曆代碼了。

而使用組件呢?一套代碼,一個標籤,而後分別在不一樣地方引用,根據不一樣的需求進行差別控制便可。

<calendar></calendar>

我能夠經過給 calendar 傳遞值實如今本頁面對日曆的控制,讓它知足我這個頁面的某些單獨需求。

有人會問,你 calendar 標籤是什麼鬼?前面有這麼一句話,組件是自定義元素。calendar 就是我自定義的元素,它就是一個組件。因此在項目中,你會發現有各類五花八門的標籤名,他們就是一個個組件。

 組件的構成:

  data
  methods
  computed
  watch
  template 模板
  鉤子函數
  ...

 

1.組件基礎

A)註冊組件

咱們把建立一個組件稱爲註冊組件,若是你把組件理解成爲變量,那麼註冊組件你就能夠理解爲聲明變量。咱們經過 Vue.component 來註冊一個全局組件。

Vue.component(componentName, {
    //選項
})

對於自定義組件的命名,Vue.js 不強制遵循 W3C 規則(小寫,而且包含一個短槓),儘管這被認爲是最佳實踐。

*根實例

一個組件就是一個 vue實例
根實例(new Vue()) 其實根實例 就是根組件

B)組件選項

  • 與建立Vue示例時的選項相同(除了一些根級特有的選項)

  • 一個組件的 data 選項必須是一個函數 (每一個組件實例具備本身的做用域,組件複用不會互相影響)

  •  

C)組件使用

組件能夠複用

D)組件模板

每一個組件模板必須只有一個根元素

模板形式一:內聯模板 (不推薦)

<my-component inline-template>
  <div>
    <p>These are compiled as the component's own template.</p>
    <p>Not parent's transclusion content.</p>
  </div>
</my-component>

模板形式二:template 選項指定字符串 (模板字符串)

模板形式三:X-Templates模板

<script type="text/x-template" id="hello-world-template">
  <p>Hello hello hello</p>
</script>


Vue.component('hello-world', {
  template: '#hello-world-template'
})

模板形式四:單文件組件(.vue)(最優,工做中使用較多)

 

E)全局組件與局部組件

全局組件

局部組件

 

F)父組件與子組件

父子組件斷定只在組件使用時考慮

下圖根組件模板內使用其它組件,因此這些組件都是子組件

 

2.組件之間的嵌套使用與互相通訊

組件設計初衷就是要配合使用的,最多見的就是造成父子組件的關係:組件 A 在它的模板中使用了組件 B。它們之間必然須要相互通訊:父組件可能要給子組件下發數據,子組件則可能要將它內部發生的事情告知父組件。

每一個組件的做用域都是獨立的,因此在組件嵌套使用的時候子組件不能直接使用父組件中的數據。

A)父組件經過Prop向子組件傳遞數據

基本使用

在子組件中聲明 prop,而後添加一個 message

<child message="hello!"></child>

Vue.component('child', { // 聲明 props props: ['message'], // 就像 data 同樣,prop 也能夠在模板中使用 // 一樣也能夠在 vm 實例中經過 this.message 來使用 template: '<span>{{ message }}</span>' })

一個組件默承認以擁有任意數量的 prop,任何值均可以傳遞給任何 prop。咱們可以在組件實例中訪問這個值,

而後直接傳入值就能夠在子組件中使用 message。

Tips:若某個組件須要在根組件中使用,組件(Vue.component)必須先註冊到Vue類中再實例化

其它形式:

a)

b)

 

Prop 的大小寫

HTML 中的特性名是大小寫不敏感的,因此瀏覽器會把全部大寫字符解釋爲小寫字符。這意味着當你使用 DOM 中的模板時,camelCase (駝峯命名法) 的 prop 名須要使用其等價的 kebab-case (短橫線分隔命名) 命名

傳入一個對象的全部屬性

<blog-post v-bind="post"></blog-post>

等價於

<blog-post
  v-bind:id="post.id"
  v-bind:title="post.title"
></blog-post>

Prop驗證

咱們能夠爲組件的 prop 指定驗證要求

Vue.component('my-component', {
  props: {
    // 基礎的類型檢查 (`null` 匹配任何類型)
    propA: Number,
    // 多個可能的類型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 帶有默認值的數字
    propD: {
      type: Number,
      default: 100
    },
    // 帶有默認值的對象
    propE: {
      type: Object,
      // 對象或數組且必定會從一個工廠函數返回默認值
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定義驗證函數
    propF: {
      validator: function (value) {
        // 這個值必須匹配下列字符串中的一個
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

類型列表:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol
  • 自定義的構造函數

B)子組件經過事件向父組件傳遞數據

on(eventName)+on(eventName)+emit(eventName) 實現通信

在父組件中使用 on(eventName)監聽事件,而後在子組件中使用on(eventName)監聽事件,而後在子組件中使用emit(eventName) 觸發事件,這樣就能實現子組件向父組件傳值。

①子組件定義模板,定義事件addCount()

②子組件向父組件發送事件this.$emit

③父組件的模板中的子組件經過自定義事件監聽

④父組件定製對應方法

 

使用事件拋出一個值

有的時候用一個事件來拋出一個特定的值是很是有用的。這時可使用 $emit 的第二個參數來提供這個值

 

3.插槽slot

A)經過插槽分發內容

Something bad happened.· 會替換掉 slot標籤

Vue.component('alert-box', {
  template: `
    <div class="demo-alert-box">
      <strong>Error!</strong>
      <slot></slot>
    </div>
  `
})
<alert-box>
  Something bad happened.
</alert-box>

 

B)模板中多個插槽

組件模板

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

調用組件

<base-layout>
  <template slot="header">
    <h1>Here might be a page title</h1>
  </template>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <p slot="footer">Here's some contact info</p>
</base-layout>

C)插槽默認內容

<button type="submit">
  <slot>Submit</slot>
</button>

 

4.動態組件

A)實現動態組件

在不一樣組件之間進行動態切換

<component is="組件名" class="tab"></component>

components: {
                'login-component': {
                    template: `
                    <form action="#">
                        <div class="form-group">
                            <label for="#">用戶名</label>
                            <input type="text" class="form-control" />
                        </div>
                        <div class="form-group">
                            <label for="#">密碼</label>
                            <input type="password" class="form-control" />
                        </div>
                        <button class="btn btn-default btn-block">登陸</button>
                    </form>
                    `
                },
                'register-component': {
                    template: `
                    <form action="#">
                        <div class="form-group">
                            <label for="#">用戶名</label>
                            <input type="text" class="form-control" />
                        </div>
                        <div class="form-group">
                            <label for="#">密碼</label>
                            <input type="password" class="form-control" />
                        </div>
                        <div class="form-group">
                            <label for="#">確認密碼</label>
                            <input type="password" class="form-control" />
                        </div>
                        <button class="btn btn-primary btn-block">註冊</button>
                    </form>
                    `
                },
                'no-login-component': {
                    template:`
                    <div>
                        我是李剛,我不用登陸,我牛逼
                    </div>
                    `
                }
            }
View Code

B)在動態組件上使用 keep-alive

包裹動態組件時,會緩存不活動的組件實例,而不是銷燬它們

主要用於保留組件狀態或避免從新渲染

<!-- 基本 -->
<keep-alive>
  <component :is="view"></component>
</keep-alive>

<!-- 多個條件判斷的子組件 -->
<keep-alive>
  <comp-a v-if="a > 1"></comp-a>
  <comp-b v-else></comp-b>
</keep-alive>

C)綁定組件選項對象

 動態組件能夠綁定 組件選項對象(有component屬性的對象),而不是已註冊組件名的示例

var tabs = [
  {
    name: 'Home', 
    component: { 
      template: '<div>Home component</div>' 
    }
  },
  {
    name: 'Posts',
    component: {
      template: '<div>Posts component</div>'
    }
  },
  {
    name: 'Archive',
    component: {
      template: '<div>Archive component</div>',
    }
  }
]

new Vue({
  el: '#dynamic-component-demo',
  data: {
      tabs: tabs,
    currentTab: tabs[0]
  }
})
<component
    v-bind:is="currentTab.component"
    class="tab"
 >
</component>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>動態組件</title>
    <link rel="stylesheet" href="../dist/css/bootstrap.css">
    <style>
        .panel {
            border-top: none;
        }
    </style>
</head>
<body>
    <div id="app">
        <div class="container">
            <div class="page-header">
                <h1>動態組件</h1>
            </div>
            <div class="row">
                <div class="col-md-6">
                    <ul class="nav nav-tabs">
                        <li v-for="item,index in tabs" :class="{active:isTab(index)}" @click="setTab(index)"><a href="javascript:0">{{ item.tabName }}</a></li>
                    </ul>

                    <div class="panel">
                        <div class="panel-body">
                            <keep-alive>
                                <component :is="tabs[tab].tabComponent"></component>
                            </keep-alive>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="../dist/js/vue.js"></script>
    <script>
        //建立根實例
        new Vue({
            el:'#app',
            data: {
                tabs: [
                        {'tabName':'登陸', 'tabComponent':'login-component'},
                        {'tabName':'註冊', 'tabComponent':'register-component'},
                        {'tabName':'免登陸', 'tabComponent':'no-login-component'},
                      ],
                tab: 0
            },
            methods: {
                isTab(index) {
                    return this.tab === index;
                },
                setTab(index) {
                    this.tab = index;
                }
            },
            components: {
                'login-component': {
                    template: `
                    <form action="#">
                        <div class="form-group">
                            <label for="#">用戶名</label>
                            <input type="text" class="form-control" />
                        </div>
                        <div class="form-group">
                            <label for="#">密碼</label>
                            <input type="password" class="form-control" />
                        </div>
                        <button class="btn btn-default btn-block">登陸</button>
                    </form>
                    `
                },
                'register-component': {
                    template: `
                    <form action="#">
                        <div class="form-group">
                            <label for="#">用戶名</label>
                            <input type="text" class="form-control" />
                        </div>
                        <div class="form-group">
                            <label for="#">密碼</label>
                            <input type="password" class="form-control" />
                        </div>
                        <div class="form-group">
                            <label for="#">確認密碼</label>
                            <input type="password" class="form-control" />
                        </div>
                        <button class="btn btn-primary btn-block">註冊</button>
                    </form>
                    `
                },
                'no-login-component': {
                    template:`
                    <div>
                        我是李剛,我不用登陸,我牛逼
                    </div>
                    `
                }
            }
        })
    </script>
</body>
</html>
View Code

 

5.組件的其餘特性

A)解析DOM模板時的注意事項

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

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

上面的寫法,渲染效果會不甚理想,能夠採用如下寫法

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

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

  • 字符串 (例如:template: '...')
  • 單文件組件 (.vue)
  • <script type="text/x-template">

B)Prop的一些問題

Prop的屬性名問題

HTML 中的特性名是大小寫不敏感的,因此瀏覽器會把全部大寫字符解釋爲小寫字符。這意味着當你使用 DOM 中的模板時,camelCase (駝峯命名法) 的 prop 名須要使用其等價的 kebab-case (短橫線分隔命名) 命名

若是你使用字符串模板,那麼這個限制就不存在了。

非Prop屬性

組件上定義的非Prop屬性 會傳遞到 組件模板的根元素上

class 和 style 特性會很是智能,即兩邊的值會被合併起來

對prop從新賦值

子組件中,對prop從新賦值,會報警告

C)組件的相關問題

將原生事件綁定到組件

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

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

.sync 修飾符

在有些狀況下,咱們可能須要對一個 prop 進行「雙向綁定」

推薦以 update:my-prop-name 的模式觸發事件

//子組件中
this.$emit('update:title', newTitle)
<!-- 上級組件 模板中 -->
<text-document
  v-bind:title="doc.title"
  v-on:update:title="doc.title = $event"
></text-document>

以上寫法能夠換成下列寫法

<text-document v-bind:title.sync="doc.title"></text-document>

 

5、Vue過分動畫

【待補充】

相關文章
相關標籤/搜索