VueJs 學習筆記

VueJs學習筆記

參考資料:https://cn.vuejs.org/javascript

特效庫:TweenJS(補間動畫庫)  VelocityJS(輕量級JS動畫庫)  Animate.css(CSS預設動畫庫)css

比較其餘框架:https://cn.vuejs.org/v2/guide/comparison.htmlhtml

Github:vue2-elm  前端

安裝

npm install vuevue

使用時推薦安裝:Vue Devtools 能夠方便調試 https://github.com/vuejs/vue-devtools#vue-devtoolsjava

安裝命令行,快速搭建大型單頁應用node

npm install --g vue-cli webpack

vue init webpack my-projectgit

npm run devgithub

聲明式渲染

Vue容許你採用簡潔的模板語法來聲明式將數據渲染進Dom。

此時app.message會進行雙向綁定,修改的同時也會改變Dom渲染。稱爲響應式元素

<div id="app">
    {{message}}
</div>
<script type="text/javascript">
    var app = new Vue({
        el: "#app",
        data: {
            message:"Hello Vue"
        }
    });
</script>

除了聲明式渲染,還可使用v-bind指令來綁定數據。v-bind屬性稱爲指令,指令帶有前綴v-。以表示它是Vue.js提供的特殊屬性

會在渲染過的DOM上應用特殊的響應式行爲。這個指令意思是把title屬性和Vue的message綁定在一塊兒。

<div id="app">
    <span v-bind:title="message">
        Hello 
    </span>
</div>
<script type="text/javascript">
    var app = new Vue({
        el: "#app",
        data: {
            message:"Hello Vue"
        }
    });
</script>

判斷與循環

控制切換一個元素,使用v-if。不只能夠綁定文本到數據,也能夠綁定Dom結構

<div id="app">
    <span v-if="seen">
        Hello 
    </span>
</div>
<script type="text/javascript">
    var app = new Vue({
        el: "#app",
        data: {
            seen:false
        }
    });
</script>

v-for 能夠綁定數據到數組循環一個列表

<div id="app">
    <ol>
        <li v-for="todo in items"></li>
    </ol>
</div>
<script type="text/javascript">
    var app = new Vue({
        el: "#app",
        data: {
            items:[
                {
                    text:"A"
                },{
                    text:"B"
                },{
                    text:"C"
                }
            ]
        }
    });
</script>

處理用戶輸入

使用v-on指令能夠綁定一個監聽事件用於調用咱們Vue實例中的方法

<div id="app">
    <p>{{message}}</p>
    <button v-on:click="reverSetMessage">Click</button>
</div>
<script type="text/javascript">
    var app = new Vue({
        el: "#app",
        data: {
            message:"Hello"
        },
        methods:{
            reverSetMessage:function(){
                this.message = "123";
            }
        }
    });
</script>

使用v-model可使表單輸入和應用狀態中作雙向綁定。當其中一個修改時,會同時修改另外一個

<div id="app">
    <p>{{message}}</p>
    <input type="text" v-model="message" />
</div>
<script type="text/javascript">
    var app = new Vue({
        el: "#app",
        data: {
            message:"Hello"
        }
    });
</script>

組件構建應用

組件系統是Vue.js另外一個重要的概念,由於它提供了一種抽象,讓咱們能夠用獨立可複用的小組件來構建大型應用。

在Vue裏一個組件實質上是一個擁有預約義選項的一個Vue實例。使用component能夠建立組件,能夠在另外一個地方寫入它。

咱們定義一個接受字段,props["todo"],使系統能夠接受todo參數。使用v-bind指令將前面v-for循環的變量,傳給todo

而後在組件的template就能夠進行渲染了。

<div id="app">
        <ol>
            <todo-item v-for="item in groceryList" v-bind:todo="item"></todo-item>
        </ol>
    </div>
    <script type="text/javascript">
        Vue.component('todo-item', {
            props:["todo"],
            template: '<li>{{todo.text}}</li>'
        })
        var app = new Vue({
            el:"#app",
            data:{
                groceryList:[
                    {"text":"Vegetables"},
                    {"text":"Cheese"},
                    {"text":"Whatever else humans"}
                ]
            }
        })
    </script>

在這個例子中,咱們將應用分割成兩個更小的單元,子元素經過props接口實現了與父元素很好的解耦

咱們能夠在不影響到父應用的基礎上將應用總體分割成一個個小組件。最終可能頁面只是如下面這種形式展示

<div id="app">
  <app-nav></app-nav>
  <app-view>
    <app-sidebar></app-sidebar>
    <app-content></app-content>
  </app-view>
</div>

構造器 

每一個Vue應用都是經過構造函數Vue建立的Vue根實例啓動的。vm變量代表Vue實例

var vm = new Vue({
            //選項
        })

在實例化Web時,須要傳入選擇對象,能夠包含數據、模板、掛載元素、方法、生命週期鉤子等選擇。Api地址

能夠擴展Vue構造器,從而用預約義選項建立可複用的組件構造器,Vue的組件其實都是被擴展的Vue實例

var MyComponent = Vue.extend({
  // 擴展選項
})
// 全部的 `MyComponent` 實例都將以預約義的擴展選項被建立
var myComponentInstance = new MyComponent()

屬性和方法

每一個Vue實例都會代理其data對象裏全部的屬性。這些被代理的屬性也是響應式的

var data = { a: 1 }
var vm = new Vue({
  data: data
})
vm.a === data.a // -> true
// 設置屬性也會影響到原始數據
vm.a = 2
data.a // -> 2
// ... 反之亦然
data.a = 3
vm.a // -> 3

 除了data屬性,Vue實例暴露了一些有用的實例屬性和方法。這些屬性和方法都有前綴$,以便於代理區分開。

var data = { a: 1 }
var vm = new Vue({
  el: '#example',
  data: data
})
vm.$data === data // -> true
vm.$el === document.getElementById('example') // -> true
// $watch 是一個實例方法
vm.$watch('a', function (newVal, oldVal) {
  // 這個回調將在 `vm.a`  改變後調用
})

生命週期 

每一個Vue實例被建立以前都要通過一系列的初始化過程。在這個過程當中會調用一些生命週期鉤子,給咱們提供執行自定義邏輯的機會。

例如,created鉤子。鉤子的this指向vm實例

<div id="app">
        {{message}}
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el:"#app",
            data:{
                message:"Hello"
            },
            created:function(){
                console.log("created鉤子");
            }
        })
    </script>

執行順序以下:

new Vue()、beforeCreate鉤子、檢查數據、初始化事件、

created鉤子、模板渲染、beforeMount鉤子、建立vm.$el、mounted鉤子

Mounted、beforeDestrory鉤子、事件監聽器、銷燬、destroyed鉤子

模板語法

Vue使用基於HTML模板語法、容許聲明式的將DOM綁定至底層Vue實例數據。

全部Vue的模板都是合法的HTML,都能被瀏覽器和HTML解析器進行解析。

插值

文本

數據綁定最多見的就是Mustache語法(雙大括號)文本插值。能夠進行響應式綁定

<span>Message:{{msg}}</span>

使用v-once指令,能夠一次性的插值,當數據改變時不會更新

<span v-once>Message:{{msg}}</span>

純HTML

使用v-html,被插入的內容都會當作HTML處理。但容易致使XSS攻擊

<div v-html="rawHtml"></div>

屬性

Mustache語法不能再屬性裏使用。在屬性中須要使用v-bind

<div v-bind:id="dynamicId"></div>

<button v-bind:disabled="boolBtn">Button</div> //能夠控制按鈕可否使用

使用Js表達式

Vue提供了JavaScript表達式支持。能夠在Mustache語法中直接寫Js

{{ alert(123); }}

指令

v-if 指令根據表達式的值來移除/插入Dom元素

<p v-if="seen">Now you See</p>

參數

一些指令能接受一個參數,在指令後以冒號指明。

<a v-bind:href="url"></a>

<a v-on:click="aClick"></a>

修飾符

指明特殊後綴,用於指出一個指定應該以特殊方法綁定。例如:.prevent修飾符告訴v-on指令對於觸發的事件採用event.preventDefault()

例如,禁止冒泡。<form v-on:submit.prevent="onSubmit"></form>

過濾器

Vue容許您定義過濾器,被用做一些常見的文本格式化,過濾器應該被加載mustache尾部,有管道符指示

過濾器只能在mustanche和v-bind中使用。使用filters定義

{{message|capitalize}}

<div v-bind:id="rawId | formatId"></div>

過濾器函數總接受表達式的值做爲第一個參數。能夠在過濾器中對值進行修改返回便可。例以下方輸出的是321而不是Hello

<div id="app">
        {{message | capital}}
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el:"#app",
            data:{
                message:"Hello"
            },
            filters:{
                capital:function(value)
                {
                    console.log(value);
                    return "321";
                }
            }
        })
    </script>

縮寫

v-bind可縮寫成:。例如:<a v-bind:href="url"></a> == <a :href="url"></a>

v-on可縮寫成@。例如:<a v-on:click="aClick"></a> == <a @click="aClick"></a>

計算屬性

模板中綁定表達式只用於簡單的操做。若是須要進行邏輯操做,應當使用計算屬性 computed

計算屬性只是做爲message的getter。若是改變revermessage是無效的

<div id="app">
        <p>{{message}}</p>
        <p>{{reverMessage}}</p>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el:"#app",
            data:{
                message:"Hello"
            },
            computed:{
                reverMessage:function(){
                    return this.message.split('').reverse().join('');
                }
            }
        })
    </script>

計算屬性默認只有getter,不過咱們也能夠顯示添加一個setter

computed: {
  reverMessage: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}

方法

咱們能夠定義Method方法,在mustanche中進行調用。

方法和計算屬性不一樣的是,計算屬性依賴於緩存,只有相關依賴發生改變時纔會重新取值。

也就是說只要message沒有改變,reverMessage就不會進行計算,也不會執行函數。

<div id="app">
        <p>{{message}}</p>
        <p>{{reverMessage()}}</p>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el:"#app",
            data:{
                message:"Hello"
            },
            methods:{
                reverMessage:function(){
                    return this.message.split('').reverse().join('');
                }
            }
        })
    </script>

觀察Watchers(異步進行Ajax操做)

當你想要在數據變化時,執行異步操做或開銷較大的操做,這是頗有用的。例如Ajax

<div id="watch-example">
        <p>
            輸入文本會進行監控查詢:
            <input v-model="question">
        </p>
        <p>
            {{message}}
        </p>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            data: {
                question: '',
                message: "Hello"
            },
            watch: {
                question: function (newQuery) {
                    this.message = "正在查詢...";
                    this.getAnswer()
                }
            },
            methods: {
                getAnswer: function(){
                    //執行Ajax操做
                    this.message = this.question;
                }
            }
        })
    </script>

綁定Html Class

對象語法

能夠傳給 v-bind:class一個對象,以動態切換class。下面語法表示若是isActive爲真,則就給div的class賦值active。

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

綁定class與原有class不衝突。能夠傳多個值來切換多個class

<div class="static"
     v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
data: {
  isActive: true,
  hasError: false
}
//渲染爲
<div class="static active"></div>

當isActive或hasError發生變化時,class列表將相應的更新。例如:hasError = true。渲染爲:div class="static active text-danger"

能夠直接綁定一個對象。而後在data中對這個對象的class,進行布爾賦值

<div v-bind:class="classObject" id="watch-example">
        <p>
            {{message}}
        </p>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            data: {
                message: "Hello",
                classObject: {
                    active: true,
                    active2: false
                }
            }
        })
    </script>

這個時候,若是咱們須要對class進行邏輯計算而後在賦值。就可使用計算屬性。這是一個經常使用且強大的模式

<div v-bind:class="classObject" id="watch-example">
        <p>
            {{message}}
        </p>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            data: {
                message: "Hello"
            },
            computed: {
                classObject: function () {
                    if (this.message == "Hello") {
                        return {
                            active: true,
                            active2: false
                        }
                    } else {
                        return {
                            active: true,
                            active2: true
                        }
                    }
                }            
             }
        })
    </script>

數組語法

能夠把一個數組傳給v-bind:class,以應用一個列表

<div v-bind:class="[isActive,isActive2]" id="watch-example">
        <p>
            {{message}}
        </p>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            data: {
                message: "Hello",
                isActive:"active",
                isActive2:"active2"
            },
        })
    </script>

也能夠根據條件來進行切換。使用三元運算符

<div v-bind:class="[true ? isActive : '',isActive2]" id="watch-example">

也能夠將對象綁定和數組綁定混用

<div v-bind:class="[{ active: isActive }, isActive2]">

綁定Style

對象語法

v-bind:style 語法十分直觀

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

data: {
                activeColor:"red",
                fontSize:"10"
            }

一般直接綁定到一個樣式對象更加清晰。

<div v-bind:style="styleObject" id="watch-example">
        <p>
            {{message}}
        </p>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            data: {
                message: "Hello",
                styleObject:{
                    color:"red",
                    fontSize:"10px"
                }
            }
        })
    </script>

數組語句

v-bind:style 數據數組能夠將多個樣式對象應用到一個元素上

<div v-bind:style="[active,active2]">

自動添加前綴

當v-bind:style使用須要特定前綴的CSS屬性時,如transform。Vue會自動監聽並添加對應前綴

條件渲染

咱們可使用v-if和v-else,實現邏輯判斷功能。

<div v-bind:style="styleObject" id="watch-example">
        <p v-if="ok">Yes</p>
        <p v-else>No</p>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            data: {
                ok:true
            }
        })
    </script>

v-else 必須緊跟着v-if,否則不會進行渲染。

template包裝渲染

可使用template標籤來包裝一組標籤,進行渲染

<div id="watch-example">
        <template v-if="ok">
            <p>1</p>
            <p>2</p>
            <p>Yes</p>
        </template>
        <p v-else>No</p>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            data: {
                ok: true
            }
        })
    </script>

在Vue2.1中,新增了v-else-if。能夠鏈式的屢次使用

Key控制元素重用

使用key能夠控制元素重用。例以下面代碼,當容許用戶在不一樣的登陸方式之間切換。若是不添加key,則輸入的數據會保存

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address" key="email-input">
</template>

v-show

與v-if相似,只不過v-show會先進行渲染,操做CSS屬性display

v-show 與 v-if相比

v-if是真實的條件渲染,會確保條件快在切換中適當地銷燬與重建。也是惰性的,若是在初始化渲染時條件爲假,則什麼也不作

通常來講v-if有更高的切換消耗,v-show有更高的初始化消耗。頻繁切換用v-show,運行條件不大可能改變用v-if

v-for

v-for用來根據一組數據的選擇列表來渲染。v-for指令須要item in items形式的特殊語法

基本使用

<ul id="watch-example">
            <li v-for="item in items">
                {{item.message}}
            </li>
        </ul>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            data: {
                items:[
                    {"message":"Foo"},
                    {"message":"Bar"}
                ]
            }
        })
    </script>

 

v-for還支持第二個可選參數當作當前索引

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

template

跟v-if同樣,v-for也可使用template

對象迭代

也可使用v-for 進行一個對象迭代處理。會輸出每一個對象的值

<ul id="watch-example">
        <li v-for="(value,index) in object">
            {{value}} + {{index}}
        </li>
    </ul>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            data: {
                object: {
                    FirstName: "A",
                    LastName: "B",
                    Old: 12
                }
            }
        })
    </script>

也能夠提供第二個的參數爲鍵名

<div v-for="(value, key) in object">
  {{ key }} : {{ value }}
</div>

第三個參數爲索引

<div v-for="(value, key, index) in object">
  {{ index }}. {{ key }} : {{ value }}
</div>

整數迭代

v-for能夠取整數,在這種狀況下會重複屢次

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

Key

當Vue用v-for正在更新已渲染過的元素列表時,默認若是數據項的順序被改變,Vue將不是移動Dom元素來匹配數據項的順序。

而是簡單複用此處每一個元素,確保已經渲染過了。爲了讓Vue從新排序現有元素,須要給每一項提供一個key

<div v-for="item in items" v-bind:key="item.id">
  <!-- 內容 -->
</div>

事件處理器

監聽事件

能夠用v-on來監聽DOM事件觸發一些代碼

 <div id="watch-example">
        <button v-on:click="counter+=1">add</button>
        <p>{{counter}}</p>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            data: {
                counter:0
            }
        })
    </script>

方法事件處理器

v-on能夠定義一個方法來執行復雜的邏輯操做

<div id="watch-example">
        <button v-on:click="greet">add</button>
        <p>{{counter}}</p>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            data: {
                counter:0
            },
            methods:{
                greet:function(){
                    this.counter += 1;
                }
            }
        })
    </script>

也能夠直接顯示調用方法。vm.greet();

方法傳參

除了上面這種方法調用,還能夠給方法傳遞參數。

<div id="watch-example">
        <button v-on:click="greet(1)">add</button>
        <p>{{counter}}</p>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            data: {
                counter: 0
            },
            methods: {
                greet: function (count) {
                    this.counter = count += 1;
                }
            }
        })
    </script>

$event

若是須要在方法裏訪問原生DOM事件,能夠用特殊變量$event把它傳入方法

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

// ...
methods: {
  warn: function (message, event) {
    // 如今咱們能夠訪問原生事件對象
    if (event) event.preventDefault()
    alert(message)
  }
}

事件修飾符

在事件處理程序中調用 event.preventDefault()阻止事件默認行動、event.stopPropagation()中止事件傳播(禁止冒泡)

是很是常見的需求,雖然咱們能夠在methods中輕鬆實現這點,但更好的方式是methods只有純粹的數據邏輯,而不處理Dom事件細節

爲了解決此問題,Vue.js爲 v-on 提供了事件修飾符,經過由 . 表示的指令後綴來調用修飾符

<!-- 阻止單擊事件冒泡 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件再也不重載頁面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修飾符能夠串聯  -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修飾符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件偵聽器時使用事件捕獲模式 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只當事件在該元素自己(而不是子元素)觸發時觸發回調 -->
<div v-on:click.self="doThat">...</div>

//2.14新增
<!-- 將觸發單擊事件最多一次 -->
<a v-on:click.once="doThis"></a>

按鍵修飾符

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

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

Vue爲最經常使用的按鍵定義了別名

所有的按鍵別名:

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

2.10新增

  • .ctrl
  • .alt
  • .shift
  • .meta

表單控件綁定

基礎用法

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

文本

<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>

多行文本

<span>Multiline message is:</span>
<p style="white-space: pre">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="add multiple lines"></textarea>

複選框

v-model 綁定的值 爲 true 或 false

<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label> 
<input
  type="checkbox"
  v-model="toggle"
  v-bind:true-value="a"
  v-bind:false-value="b"
>

// 當選中時
vm.toggle === vm.a
// 當沒有選中時
vm.toggle === vm.b

多選框

<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>

new Vue({
  el: '...',
  data: {
    checkedNames: []
  }
})

單選框

v-model 綁定的值爲 value。One 或者 Two

<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>
<input type="radio" v-model="pick" v-bind:value="a">

// 當選中時
vm.pick === vm.a

多選列表

v-model綁定的值,在選中的狀況下爲 option的value

<select v-model="selected" multiple>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
<br>
<span>Selected: {{ selected }}</span>

動態選項

<select v-model="selected">
  <option v-for="option in options" v-bind:value="option.value">
    {{ option.text }}
  </option>
</select>
<span>Selected: {{ selected }}</span>

new Vue({
  el: '...',
  data: {
    selected: 'A',
    options: [
      { text: 'One', value: 'A' },
      { text: 'Two', value: 'B' },
      { text: 'Three', value: 'C' }
    ]
  }
})
<select v-model="selected">
    <!-- 內聯對象字面量 -->
  <option v-bind:value="{ number: 123 }">123</option>
</select>

// 當選中時
typeof vm.selected // -> 'object'
vm.selected.number // -> 123

修飾符

.lazy

默認狀況下,v-model在input事件中同步輸入框的值和數據。但能夠添加一個修飾符lazy,從而轉變爲change事件中同步

<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >

.number

若是想自動將用戶輸入的值轉換爲number,若是轉換不成功則返回原值。能夠添加一個.number修飾符給v-model來處理

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

.trim

能夠過濾用戶輸入的首尾空格

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

組件

組件是VueJs最強大的功能之一,組件能夠擴展HTML元素,封裝可重用代碼。在較高層面上,組件是自定義元素,VueJs爲他添加特殊功能。

有些狀況下,組件也能夠是原生HTML元素的形式,以is特性擴展。

註冊

要註冊一個全局組件,可使用Vue.component(tagName,options)。標籤名使用W3C規則,小寫而且包含一個短槓

Vue.component("Demo-component",{
            //操做
        });

組件註冊以後,則能夠在頁面中使用了。

<div id="watch-example">
        <demo-component></demo-component>
    </div>
    <script type="text/javascript">
        Vue.component("demo-component",{
            template:"<div>A Custome</div>"
        });

        var vm = new Vue({
            el: "#watch-example"
        })
    </script>

有時候咱們不須要全局註冊,可使用局部註冊(components),只針對本頁面和父頁面進行顯示。

<div id="watch-example">
        <demo-component></demo-component>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            components: {
                "demo-component": {
                    template: "<div>A Custome</div>"
                }
            }
        })
    </script>

DOM模板解析說明 

當使用Dom做爲模板時,會受到一些HTML限制,由於Vue只有在瀏覽器解析和標準化HTML後才能獲取內容。

例如:<ul>、<ol>、<table>、<select>限制了能包裹的屬性。致使在這些標籤下進行組件會被認爲是無效內容。

可是也有變通的方法,可使用特殊的 is 屬性。

data必須是函數

使用組件的時候,大多數能夠傳到Vue構造器中的選項均可以在註冊組件時使用。可是有一個例外,data 必須是函數。

若是咱們在組件中寫以下代碼。會受到報錯:The "data" option should be a function that returns a per-instance value in component definitions

 <div id="watch-example">
        <demo-component></demo-component>
    </div>
    <script type="text/javascript">
        Vue.component("demo-component",{
            template:"<div>{{message}}</div>",
            data:{
                message:"Hello"
            }
        })
        var vm = new Vue({
            el: "#watch-example"
        })
    </script>

提示data必須是一個函數,因此咱們修改成以下代碼

<div id="watch-example">
        <demo-component></demo-component>
    </div>
    <script type="text/javascript">
        Vue.component("demo-component", {
            template: "<div>{{message}}</div>",
            data: function () {
                return {
                    message: "Hello"
                }
            }
        })
        var vm = new Vue({
            el: "#watch-example"
        })
    </script>

構成組件

組件意味着協同工做,一般父子組件會是這樣的關係。組件在A在它的模板中使用了組件B,他們之間是必然須要通訊的。

父組件給子組件傳遞數據,子組件須要將它內部發生的事情告知父組件。

然而,在一個良好的接口定義中儘量的將父子組件解耦是很重要的。這保證了每一個組件能夠在相對隔離的環境中書寫和理解

也大幅提升了組件的可維護性和可重用性。

在Vue中,父子組件的關係能夠總結爲:props down 屬性向下、event up 事件向上。父組件經過props向下傳遞數據給子組件

子組件經過event給父組件發送消息。

Prop

使用Prop傳遞數據

組件的實例做用域是孤立的,子組件不能直接引用父組件的數據。但可使用props吧數據傳給子組件

message 是父組件用來傳遞數據的一個自定義屬性,子組件須要顯示地使用props選項聲明「message」

<div id="watch-example">
        <demo-component message="Hello World"></demo-component>
    </div>
    <script type="text/javascript">
        Vue.component("demo-component", {
            props:["message"],
            template:"<span>{{message}}</span>"
        });
        var vm = new Vue({
            el: "#watch-example"
        })
    </script>

傳遞過來的值,跟data是同樣的,均可以直接綁定。例如:綁定style

 <div id="watch-example">
        <demo-component message="Hello World" size="10px"></demo-component>
    </div>
    <script type="text/javascript">
        Vue.component("demo-component", {
            props: ["message", "size"],
            template: "<span style='font-size:10px' v-bind:style={fontSize:size}>{{message}}</span>"
        });
        var vm = new Vue({
            el: "#watch-example"
        })
    </script>

動態屬性

使用v-bind能夠動態綁定屬性到父組件中。每當數據變化,該變化也會傳到子組件

<div id="watch-example">
        <input v-model="parentMsg" />
        <demo-component :message="parentMsg" size="10px"></demo-component>
    </div>
    <script type="text/javascript">
        Vue.component("demo-component", {
            props: ["message", "size"],
            template: "<span style='font-size:10px' v-bind:style={fontSize:size}>{{message}}</span>"
        });
        var vm = new Vue({
            el: "#watch-example",
            data:{
                parentMsg:''
            }
        })
    </script>

傳遞數值

若是想要給組件傳遞一個數字,是不可使用常量傳遞的。由於它傳遞的並非實際的數字。例如

<div id="watch-example">
        <demo-component size="10"></demo-component>
    </div>
    <script type="text/javascript">
        Vue.component("demo-component", {
            props: ["message", "size"],
            template: "<div><button v-on:click=add>add</button><span>{{size}}</span></div>",
            methods:{
                add:function(){
                    this.size += 1;
                }
            }
        });
        var vm = new Vue({
            el: "#watch-example"
        })
    </script>

demo-component size是常量傳遞,也就是傳遞的字符串。那麼在add方法中,實際上會變成 1011111 這種形式

因此咱們針對數字傳遞時,要使用 v-bind:size 或者 :size

咱們儘可能不要直接操做傳遞過來的值,因此咱們使用data或者計算屬性,來完成操做 

Vue.component("demo-component", {
            props: ["message", "size"],
            template: "<div><button v-on:click=add>add</button><span>{{cSize}}</span></div>",
            data: function () {
                return {
                    cSize: this.size
                }
            },
            methods: {
                add: function () {
                    this.cSize += 1;
                }
            }
        });

單向數據流

prop是單向綁定的,也就是說父組件的屬性變化時,將傳導給子組件。但不會反過來。這是爲了怕子組件,改變父組件的狀態

每次父組件更新時,子組件的全部prop也會更新。這意味着,咱們不能在子組件改變prop的狀態。Vue會提出警告。

一般有兩種改變prop的狀況,

1.prop做爲初始值傳入,子組件以後只是將它的初始值做爲本地數據的初始值使用

2.prop做爲須要被轉變的原始值傳入

那麼,咱們可使用兩種方式來應對轉變

1.使用data屬性,並將prop的初始值做爲局部數據的初始值

props: ['initialCounter'],
data: function () {
  return { counter: this.initialCounter }
}

2.使用計算屬性,此屬性從prop的值計算得出

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

注意:JavaScript中對象和數組是引用類型,在組件中改變,父組件也會隨之改變

Prop驗證

組件能夠爲props指定驗證要求,若是未指定驗證要求,Vue會發出警告。

Vue.component('example', {
  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 value > 10
      }
    }
  }
})

type 能夠是下面原生構造器:

  • String
  • Number
  • Boolean
  • Function
  • Object
  • Array

type 也能夠是一個自定義構造器,使用 instanceof 檢測。

自定義事件

父組件是使用props傳遞數據給子組件,若是子組件要把數據傳回給父組件。就須要使用自定義事件

v-on綁定自定義事件

每一個Vue實例都實現了事件接口

使用 $on(eventName) 監聽事件

使用 $emit(eventName) 觸發事件

父組件能夠在使用子組件的地方直接用v-on來監聽子組件觸發的事件

 <div id="watch-example">
        <p>{{total}}</p>
        <button-counter v-on:increment="incrementTotal"></button-counter>
    </div>
    <script type="text/javascript">
        Vue.component("button-counter", {
            template: "<button v-on:click=increment>{{counter}}</button>",
            data: function () {
                return {
                    counter:0
                }
            },
            methods: {
                increment: function () {
                    this.counter+=1;
                    this.$emit("increment")
                }
            }
        });
        var vm = new Vue({
            el: "#watch-example",
            data:{
                total:0
            },
            methods:{
                incrementTotal:function(){
                    this.total += 1;
                }
            }
        })
    </script>

使用自定義事件的表單輸入組件

自定義事件也能夠用來建立自定義的表單輸入組件,使用v-model 來進行數據雙向綁定

<input v-model="something">

只是一個語法糖,它對應的語句是

<input v-bind:value="something" v-on:input="something = $event.target.value">

<custom-input v-bind:value="something" v-on:input="something = arguments[0]"></custom-input>

$event.target.value 意思是最初觸發事件的DOM元素

要讓v-model生效,必須接受一個value屬性、在有新的value時觸發input事件。

ref = "sel",這是Vue2.0的特性,添加此特性才能夠$ this.$refs.sel.value

一個簡單的下拉框例子。每次下拉都會往前推進一個位置

<div id="watch-example">
        <currency-input v-model="price"></currency-input>
    </div>
    <script type="text/javascript">
        Vue.component("currency-input", {
            template: '\
               <span>\
                 <select ref="sel" v-bind:value="value" v-on:change="updateValue($event.target.value)">\
                    <option value ="1">Volvo</option>\
                    <option value ="2">Saab</option>\
                    <option value="3">Opel</option>\
                    <option value="4">Audi</option>\
                </select>\
                </span>\
                ',
            props: ["value"],
            methods: {
                updateValue: function (value) {
                    var formattedValue = Number(value);
                    if (formattedValue < 4) {
                        formattedValue += 1;
                    } else {
                        formattedValue = 1;
                    }
                    if (formattedValue !== value) {
                        this.$refs.sel.value = formattedValue
                    }
                    this.$emit('input', formattedValue);
                }
            }
        });
        var vm = new Vue({
            el: "#watch-example",
            data: {
                price: "1"
            }
        })
    </script>

 

使用Slot分發內容

在使用組件時,常常須要像這樣組合它們

<app>
  <app-header></app-header>
  <app-footer></app-footer>
</app>

有兩點須要注意:

1. <app> 組件不知道它的掛載點會有什麼內容。掛載點的內容是由<app>的父組件決定的

2. <app> 組件極可能有它本身的模板

爲了讓組件能夠組合,咱們須要一種方式來混合父組件的內容與子組件本身的模板。

這個過程稱爲 內容分發 。Vue實現了一個內容分發API。使用特殊的slot元素做爲原始內容的插槽

編譯做用域 

<child-component>
  {{ message }}
</child-component>

上面例子中,message應該綁定到父組件的數據。

組件做用域簡單地說

父組件模板的內容在父組件做用域內編譯;

子組件的模板內容在子組件做用域內編譯;

例以下面的代碼,就不會再子組件中運行

<child-component v-show="someChildProperty"></child-component>

單個Slot

對於下面這種狀況,除非子組件模板包含一個<slot>插口,不然父組件的內容將會丟棄

<child-component>
  {{ message }}
</child-component>

當子組件只有一個<slot>而且沒有屬性的時候,父組件整個內容片斷將插入到slot所在的DOM位置,而且替換到slot標籤自己

最初寫在slot標籤底下的內容都被視爲備用內容。只有宿主元素爲空,且沒有要插入的內容時纔會顯示

假定子組件有下面的模板

<div>
  <h2>我是子組件的標題</h2>
  <slot>
    只有在沒有要分發的內容時纔會顯示。
  </slot>
</div>

父組件

<div>
  <h1>我是父組件的標題</h1>
  <my-component>
    <p>這是一些初始內容</p>
    <p>這是更多的初始內容</p>
  </my-component>
</div>

渲染結果

<div>
  <h1>我是父組件的標題</h1>
  <div>
    <h2>我是子組件的標題</h2>
    <p>這是一些初始內容</p>
    <p>這是更多的初始內容</p>
  </div>
</div>

具名Slot

slot元素能夠用一個特殊的屬性name來配置如何分發內容。多個slot能夠有多個不一樣的名字。

具名slot將匹配內容片斷中有對應slot特性的元素。

仍然能夠由一個匿名的slot。它是默認的slot。做爲找不到內容片斷的備用插槽。若是沒有默認的slot,找不到的內容會被拋棄

例以下面的例子。使用自定義屬性slot後面跟名字來指定

<div id="watch-example">
        <currency-input>
            <h1 slot="header">頁面標題</h1>
            <p>主要內容</p>
            <p>另外一個主要內容</p>
            <p slot="footer">聯繫信息</p>
        </currency-input>
    </div>
    <script type="text/javascript">
        Vue.component("currency-input", {
            template: '\
                        <div class="container">\
                            <header>\
                                <slot name="header"></slot>\
                            </header>\
                            <main>\
                                <slot></slot>\
                            </main>\
                            <footer>\
                                <slot name="footer"></slot>\
                            </footer>\
                        </div>\
                        '
        });
        var vm = new Vue({
            el: "#watch-example"
        })
    </script>

上面代碼渲染的狀況爲

<div class="container">
  <header>
    <h1>這裏多是一個頁面標題</h1>
  </header>
  <main>
    <p>主要內容的一個段落。</p>
    <p>另外一個主要段落。</p>
  </main>
  <footer>
    <p>這裏有一些聯繫信息</p>
  </footer>
</div>

做用域插槽

做用域插槽是一種特殊類型。2.1.0新增,使用一個可重用模板替換已渲染的元素。

子組件中,只需將數據傳遞到插槽,就像prop傳遞給組件同樣。

在父級組件中,具備特殊屬性scope的<template>元素,表示它是做用域插槽的模板。scope的值對應一個臨時變量

此變量接受從子組件中傳遞的prop對象。

動態組件

多個組件可使用一個掛載點,使用 內鏈組件 components 可讓他們動態切換

<div id="watch-example">
        <component v-bind:is="currentView"></component>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#watch-example",
            data:{
                currentView:"A"
            },
            components:{
                A:{
                    template:"<div>childA</div>" 
                },
                B:{
                    template: '<div>childB</div>'
                }
            }
        })
    </script>

咱們修改vm.currentView就能夠實現組件切換的功能了

也能夠直接綁定到組件對象上,不過不推薦這種使用

var Home = {
  template: '<p>Welcome home!</p>'
}
var vm = new Vue({
  el: '#example',
  data: {
    currentView: Home
  }
})

keep-alive

若是須要把切換的組件保留在內存中,而不是重新渲染。能夠添加keep-alive標籤,嵌套調用組件

<keep-alive>
            <component v-bind:is="currentView"></component>
        </keep-alive>

這樣能夠保留狀態,不進行重新渲染。

編寫可複用的組件

在編寫組件時要考慮是否須要複用組件,可複用組件應當定義一個清晰的公開接口

Vue組件的API來自三部分:props,events,slots

Props:容許外部環境傳遞數據給組件

Events:容許組件觸發外部環境的反作用

Slots:容許外部環境將額外的內容組合在組件中

在調用過程當中,使用v-bind 和 v-on的簡寫語法。會讓模板變得更加簡潔

<my-component
  :foo="baz"
  :bar="qux"
  @event-a="doThis"
  @event-b="doThat"
>
  <img slot="icon" src="...">
  <p slot="main-text">Hello!</p>
</my-component>

子組件索引

儘管有props和events,可是有時候仍然須要在js中直接訪問子組件。爲此可使用ref爲子組件指定一個索引ID

<div id="parent">
  <user-profile ref="profile"></user-profile>
</div>

var parent = new Vue({ el: '#parent' })
// 訪問子組件
var child = parent.$refs.profile

當ref和v-for一塊兒使用時,ref是一個數組或對象,包含相應的子組件

$refs 只在組件渲染完成之後才填充,而且它是非響應式的。僅僅做爲訪問子組件的應急方案。儘可能避免使用

異步組件 

在大型應用中,咱們可能須要將應用拆分紅多個小模塊,按需下載。爲了讓事情更簡單,Vue容許將組件定義爲一個工廠函數。

動態解析組件的定義。Vue只在組件須要渲染時觸發工廠函數,而且把結果緩存起來,用於後面再次渲染。

例以下面代碼,咱們能夠把組件模板提取出來

 Vue.component("hello-world", function(resolve,reject){
            $.get("./xtemplate.html").then(function(res){
                resolve({
                    template:res
                })
            });
        });

可是咱們在使用Vue的時候,儘可能擺脫掉jQuery,咱們可使用 vue-resource https://github.com/pagekit/vue-resource

咱們引用完vue-resource之後,就能夠替代jQuery的ajax了

使用vue-resource的代碼以下:

Vue.component("cxy-demo4", function (resolve, reject) {
    Vue.http.get("/xtemplate.html").then(function (res) {
        resolve({
            template: res.body,
            data: function () {
                return {
                    message: "123"
                }
            }
        })
    })
})

 

完美解決~

不過,仍是推薦使用 webpack 的 vue-loader。

X-Templates

一種比較優雅的模板加載方式。在JavaScript裏面使用text/x-template類型,並指定一個id

可是這種加載方式至關於跟組件進行隔離了。因此要謹慎使用

<div id="watch-example">
        <hello-world></hello-world>
    </div>
    <script type="text/x-template" id="hello-world-template">
        <p>Hello World</p>
    </script>
    <script type="text/javascript">
        Vue.component("hello-world",{
            template:"#hello-world-template"
        })
        var vm = new Vue({
            el: "#watch-example"
        })
    </script>

v-once靜態組件

若是組件中包含大量靜態內容,能夠考慮使用v-once將渲染結果緩存起來

Vue.component('terms-of-service', {
  template: '\
    <div v-once>\
      <h1>Terms of Service</h1>\
      ... a lot of static content ...\
    </div>\
  '
})

過分效果

Vue在插入、更新或移除DOM時,提供多種不一樣方式的應用過分效果。包括如下工具

  • 在CSS過分和動畫中自動應用CSS
  • 能夠配合使用第三方CSS動畫庫,如Animate.css
  • 在過分鉤子函數中使用Javascript直接操做Dom
  • 能夠配合使用第三方Javascript動畫庫,如Velocity.js

單元素/組件的過分

Vue提供了 transition 的封裝組件,在下列狀況下能夠給任何元素和組件添加 entering(進入)/leaving(離開)過分

  • 條件渲染(使用 v-if)
  • 條件展現(使用 v-show)
  • 動態組件
  • 組件根節點

例以下面例子

<style type="text/css">
        .fade-enter-active,
        .fade-leave-active {
            transition: opacity .5s
        }
        
        .fade-enter,
        .fade-leave-active {
            opacity: 0
        }
    </style>

<div id="demo">
        <button v-on:click="show = !show">Toggle</button>
        <transition name="fade">
            <p v-if="show">hello</p>
        </transition>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#demo",
            data: {
                show: true
            }
        })
    </script>

元素封裝成過分組件以後,在遇到插入或刪除時,Vue將

  1. 自動嗅探目標元素是否有CSS過分或動畫,並在合適時添加/刪除CSS類名
  2. 若是過分組件設置了過分的JavaScript鉤子函數,會在相應的階段調用鉤子函數
  3. 若是沒有找到Js鉤子函數而且也沒有檢測到CSS過分/動畫,DOM操做當即執行

過分-CSS-類名

有4個CSS類名在enter/leave的過分中切換

  1. v-enter:定義進入過分的開始狀態,在元素被插入時生效,在下一幀移除
  2. v-enter-active:定義進入過分的結束狀態,在元素被插入時生效,在過分/動畫完成後移除
  3. v-leave:定義離開過分的開始狀態,在離開過分被觸發時生效,在下一幀移除
  4. v-leave-active:定義離開過分的結束狀態,在離開過分被觸發時生效,在過分/動畫完成後移除

這些在enter/leave的過分中切換的類名,v-是這些類名的前綴。使用<transition name="my-transion">

能夠重置前綴,好比v-enter替換爲my-transition-enter

v-enter-active 和 v-lelave-active能夠控制 進入/離開 過分的不一樣階段

CSS過分

經常使用的過分都是CSS過分。下面是一個簡單的例子

<div id="demo">
        <button @click="show = !show">Toggle</button>
        <transition name="fade">
            <p v-if="show">hello</p>
        </transition>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#demo",
            data: {
                show: true
            }
        })
    </script>

<style type="text/css">
        .fade-enter-active{
            transition: all 3s ease;
        }
        .fade-leave-active{
            transition: all 8s linear;
        }
        .fade-enter, .fade-leave-active{
            transform: translateX(100px);
            opacity: 0;
        }
    </style>

CSS動畫

CSS動畫用法和過分相似,區別是在動畫中v-enter類名的節點插入DOM後不會當即刪除。

而是在觸發animationend事件時刪除。下面是一個動畫效果的例子

<style type="text/css">
        @keyframes bounce-in {
            0% {
                transform: scale(0);
            }
            50% {
                transform: scale(1.5);
            }
            100% {
                transform: scale(1);
            }
        }
        
        @keyframes bounce-out {
            0% {
                transform: scale(1);
            }
            50% {
                transform: scale(1.5);
            }
            100% {
                transform: scale(0);
            }
        }
        
        .fade-enter-active {
            animation: bounce-in .5s;
        }
        
        .fade-leave-active {
            animation: bounce-out .5s;
        }
    </style>

自定義過濾類名

能夠經過如下特徵來自定義過分類名

  • enter-class
  • enter-active-class
  • leave-class
  • leave-active-class

這些特效的優先級高於普通類名。對於使用第三方過分系統和第三方CSS動畫庫十分有效。

下面代碼使使用,Animate.css 結合使用

<div id="demo" style="margin-left: 50px">
        <button @click="show = !show">Toggle</button>
        <transition name="fade" 
            enter-active-class="animated tada" 
            leave-active-class="animated bounceOutRight"> 
            <p v-if="show">hello</p>
        </transition>
    </div>

JavaScript鉤子

能夠在屬性中聲明JavaScript鉤子

<transition
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:after-enter="afterEnter"
  v-on:enter-cancelled="enterCancelled"
  v-on:before-leave="beforeLeave"
  v-on:leave="leave"
  v-on:after-leave="afterLeave"
  v-on:leave-cancelled="leaveCancelled"
>
  <!-- ... -->
</transition>

--------------------------------------------------------------------
// ... methods: { // -------- // 進入中 // -------- beforeEnter: function (el) { // ... }, // 此回調函數是可選項的設置 // 與 CSS 結合時使用 enter: function (el, done) { // ... done() }, afterEnter: function (el) { // ... }, enterCancelled: function (el) { // ... }, // -------- // 離開時 // -------- beforeLeave: function (el) { // ... }, // 此回調函數是可選項的設置 // 與 CSS 結合時使用 leave: function (el, done) { // ... done() }, afterLeave: function (el) { // ... }, // leaveCancelled 只用於 v-show 中 leaveCancelled: function (el) { // ... } }

這些鉤子函數能夠結合CSS transitions/animations 使用,也能夠單獨使用

在 enter 和 leave中,回調函數 done 是必須的。不然他們會被同步調用,過分會當即完成

對僅使用JavaScript過分元素添加 v-bind:css="false",Vue會跳過CSS檢測。

使用Velocity.js的簡單例子

<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<div id="example-4">
  <button @click="show = !show">
    Toggle
  </button>
  <transition
    v-on:before-enter="beforeEnter"
    v-on:enter="enter"
    v-on:leave="leave"
    v-bind:css="false"
  >
    <p v-if="show">
      Demo
    </p>
  </transition>
</div>
new Vue({
  el: '#example-4',
  data: {
    show: false
  },
  methods: {
    beforeEnter: function (el) {
      el.style.opacity = 0
      el.style.transformOrigin = 'left'
    },
    enter: function (el, done) {
      Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
      Velocity(el, { fontSize: '1em' }, { complete: done })
    },
    leave: function (el, done) {
      Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 })
      Velocity(el, { rotateZ: '100deg' }, { loop: 2 })
      Velocity(el, {
        rotateZ: '45deg',
        translateY: '30px',
        translateX: '30px',
        opacity: 0
      }, { complete: done })
    }
  }
})

其餘更多的渲染效果。查看如下連接

https://cn.vuejs.org/v2/guide/transitions.html#初始渲染的過渡

單文件組件(node.js)

在許多Vue項目中,使用Vue.component 來定義全局組件,緊接着用new Vue在每一個頁面指定一個容器元素

  • 全局定義:強制要求每一個component中的命名不得重複
  • 字符串模板:缺少語法高亮,在HTML多行時,還須要 \
  • 不支持CSS:HTML和JS組件化時,CSS被遺漏
  • 沒有構建步驟:限制只能使用HTML和ES5,不能使用預處理器

.vue 的單文件組件能夠解決以上問題。而且還可使用Webpack 或 Browserify。

下面就是 .vue的單文件組件 示例。能夠得到:完整語法高亮,CommonJS模塊,組價化CSS

<template>
    <p>{{greeting}} World!</p>
</template>
<script>
    module.exports = {
        data: function () {
            return {
                greething: "Hello"
            }
        }
    }
</script>
<style scoped>
    p {
        font-size: 2em;
        text-align: center;
    }
</style>

有了 .vue 組件,咱們就進入了高級JavaScript應用領域。須要學習一些工具的使用

Node Package Manager(NPM):https://docs.npmjs.com/getting-started/what-is-npm  會操做就能夠

Modern JavaScript with ES6:https://babeljs.io/docs/learn-es2015/ 

學習完這些工具後,咱們就能夠進行webpack2教程了

webpack2:https://doc.webpack-china.org/

vue-loader : https://lvyongbo.gitbooks.io/vue-loader/content/?q=

vue-loader實例:https://sally-xiao.gitbooks.io/book/content/index.html

Vue-loader

vue-loader 是Webpack的加載器,能夠將.vue後綴的單文件組件轉換成純Javascript模塊

vue-loader提供不少很是酷炫的功能

  • 默認啓用ES2015(ES6的另外一個稱呼)
  • 容許爲Vue組件的每一個部分使用其餘Webpack裝載程序,
  • 容許.vue文件中可應用自定義加載程序鏈的自定義部分
  • 處理在引用中的靜態資源<style>和<template>做爲模塊依賴項,並用webpack加載他們
  • 能夠模擬每一個組件的做用域CSS
  • 支持在開發過程當中組件熱加載

簡而言之,webpack和vue-loader的組合,提供了一個現代、靈活而且很是強大的前端工做流程

什麼是Webpack?

參考資料:http://www.cnblogs.com/chenxygx/p/5126539.html

Vue組件規格

一個*.vue文件是使用HTML的語法描述Vue組合而成的自定義文件格式。每一個*.vue文件有三種類型的頂層語言塊

<template>、<script>、<style>。和任選的附加自定義塊。例如:

<template>
  <div class="example">{{ msg }}</div>
</template>

<script>
export default {
  data () {
    return {
      msg: 'Hello world!'
    }
  }
}
</script>

<style>
.example {
  color: red;
}
</style>

<custom1>
  This could be e.g. documentation for the component.
</custom1>

vue-loader將解析文件,提取每個語言塊。經過裝載器加載,最後組裝回一個CommonJS模塊

module.exports 是一個Vue.js 組件選項對象

vue-loader經過lang語言指定屬性支持非默認語言,例如

<style lang="sass">
  /* write SASS! */
</style>

語言塊 

<template>

默認語言:htmll

每一個*.vue文件最多能夠包含一個<template>塊

內容將做爲字符串提取,並用做template編譯的Vue組件的選項

<script>

默認語言:js

每一個*.vue文件最多能夠包含一個<script>塊

該腳本在相似CommonJS的環境中執行,可使用require() 其餘依賴項,而且支持ES6

腳本必須導出Vue.js組件選項對象,Vue.extend() 也支持導出建立的擴展構造函數

<style>

默認語言:css

<style>單個*.vue文件中支持多個標籤

一個<style>標籤能夠有scoped和module屬性

默認狀況下,內容將被提取並<head>做爲實際<style>標記動態插入 。

也能夠經過配置 Webpack 使組件內全部樣式提取到一個CSS文件中。

自定義塊 

vue-loader 10.2.0 中支持

*.vue對於任何項目特定須要,能夠在文件中包含其餘自定義快,例如<doce>

vue-loader將使用標籤名稱來查找應將那些webpack加載器應用於該部分的內容

應在選項loaders部分中vue-loader指定webpack裝載程序

Src Imports

若是但願將組件拆分紅多個文件,可使用src屬性爲語言塊導入外部文件

<template src="./template.html"></template>
<style src="./style.css"></style>
<script src="./script.js"></script>

須要使用./進行相對路徑定位,獲取從已安裝的npm包中導入

<style src="todomvc-app-css/index.css">

註釋

在每一個語言塊中,使用該語言的註釋方法。對於頂級註釋,使用HTML註釋語法

<!-- comment contents here -->

項目設置

使用vue-cli

建立項目的時候,推薦使用腳手架工具,能夠用 vue-loader 和 vue-cli,命令以下

npm install -g vue-cli
vue init webpack-simple hello-vue
cd hello-vue
npm install
npm run dev # 一切就緒!

解釋一下:

全局安裝vue-cli

vue init <template-name> <project-name>。目前可使用的模板有如下幾種。

  1. browserify:全功能的Browserify + vueify。包括熱加載、靜態檢測、單元測試
  2. browserify-simple:一個簡易的Browserify + vueify,以便於快速開始
  3. webpack:全功能的webpack + vueify,包括熱加載、靜態檢測、單元測試
  4. webpack-simple:一個建議的webpack + vueify,以便於快速開始

使用npm run dev,能夠運行項目。在項目路徑下,執行 webpack 可打包相關項目

而後就能夠用IIS部署訪問了

ES2015

當vue-loader 檢測到 babel-loader 或者 buble-loader 在項目中存在時

將會用它們處理全部*.vue文件的<script>部分,因此,咱們就可使用Vue組件中的ES2015

學習筆記:http://www.cnblogs.com/chenxygx/p/6509564.html

一個引用其餘Vue組件的,經典模式代碼示例以下

<script>
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'

export default {
  components: {
    ComponentA,
    ComponentB
  }
}
</script>

使用ES2015精簡語法定義子組件。ComponentA Vue會自動轉爲component-a。

因此就能夠在模板中引用組件<component-a>

轉換正常*.js文件

因爲vue-loader只能處理*.vue文件,須要在配置文件中告訴Webpack用babel-loader或者buble-loader

可使用vue-cli 腳手架工具建立

Scoped CSS

當<style>標籤有scoped屬性的時候(<style scoped>),它的CSS只能做用於當前做用域。

會由PostCSS轉義成以下格式

//before
<style scoped> .example
{ color: red; } </style> <template> <div class="example">hi</div> </template>
//after
<style>
.example[_v-f3f3eg9] {
  color: red;
}
</style>

<template>
  <div class="example" _v-f3f3eg9>hi</div>
</template>
  • 同一個組件能同時擁有做用域和無做用域的樣式
  • 父組件有做用域的CSS會影響到子組件
  • 有做用域的樣式對其餘部分沒有影響

PostCSS

任何經過 vue-loader 處理過的CSS都在用PostCSS 重寫有做用域限制的CSS部分。

你也能添加自定義的PostCSS插件處理。例如:autoprefixer 或 CSSNext

// webpack.config.js
module.exports = {
  // 其餘配置...
  plugins: [
    new webpack.LoaderOptionsPlugin({
      vue: {
        // 使用用戶自定義插件
        postcss: [require('postcss-cssnext')()]
      }
    })
  ]
}

熱加載

當你啓用熱加載功能,編寫完 *.vue 文件後,組件的全部實例對象被替換,而頁面並無從新加載

仍然保持應用原有狀態,這在你調整模板或修改組件樣式的時候,大大改善了開發體驗。

當使用 vue-cli 時,熱加載自動啓用

預處理器

在Webpack中,全部的預處理需須要和一個相應的加載器一同使用。

vue-loader 容許你用其它的Webpack 加載器去處理 Vue組件一部分代碼。

會根據 lang 屬性自動用適當的加載器去處理。

CSS

例如咱們編譯用SASS編譯<style>標籤

npm install sass-loader node-sass --save-dev

<style lang="sass">
  /* 這裏寫一些 sass 代碼 */
</style>

在引擎內部,首先<style>標籤內的內容會被 sass-loader 編譯,而後再被一步步處理。

Javascript

默認狀況下,Vue組件內的全部Javascript會被babel-loader處理

npm install coffee-loader --save-dev

<script lang="coffee">
     # 這裏寫一些 coffeescript!
</script>

Templates

處理模板的過程有些不一樣,由於大多數webpack模板加載器(例如:jade-loader),會返回一個模板處理函數

而不是被編譯過的HTML字符,因此只須要安裝 jade 便可

npm install jade --save-dev

<template lang="jade">
div
  h1 Hello world!
</template>

URL資源處理

vue-loader 能夠自動用 css-loader 和Vue組件編譯器來處理樣式和模板文件。

在處理過程當中,全部的資源URL都會被當作依賴的模塊來處理。例如:<img src=""> 被轉移成 require("")

//原始
<img src="../image.png">

//轉義
createElement('img', { attrs: { src: require('../image.png') }})

由於.png並非Javascript文件,須要配置webpack來使用file-loader和url-loader處理它們

使用腳手架工具 vue-cli 也能幫你配置這些。

file-loader 容許你指定在哪裏複製和存放靜態資源文件,用版本哈希值命名從而更好的利用緩存。

意味着能夠把圖片放到*.vue文件旁邊,可以使用相對路徑,而不須要擔憂發佈時候的URL。

使用適當的配置,webpack打包輸出的時候,會自動把文件路徑轉爲正確的URL

url-loader 容許你內聯 base-64 數據格式的URL資源。能夠減小HTTP請求小文件的數量

產品構建

當產品發佈的時候,須要作兩件事情

1.壓縮應用的代碼量

2.解決Vue.js源代碼中的全部警告

實際上咱們須要的配置以下所示:

// webpack.config.js
module.exports = {
  // ... 其餘選項
  plugins: [
    // Vue.js 代碼報警告
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    // 清除無用代碼來縮小代碼量
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    }),
    // optimize module ids by occurence count
    new webpack.optimize.OccurenceOrderPlugin()
  ]
}

 

$

路由

大多數單頁面應用,都推薦使用官方支持的vue-router庫。更多細節能夠看 vue-router文檔

文檔地址:http://router.vuejs.org/zh-cn/

單元測試

能夠及使用Karma進行自動化測試。

文檔地址:http://karma-runner.github.io/1.0/index.html

服務器渲染

$

相關文章
相關標籤/搜索