每一個vue與應用都需要通過實例化來實現。
<div id="vue_det"> <h1>site : {{site}}</h1> <h1>url : {{url}}</h1> <h1>{{details()}}</h1> </div> <script type="text/javascript"> var vm = new Vue({ el: '#vue_det', data: { site: "菜鳥教程", url: "www.runoob.com", alexa: "10000" }, methods: { details: function() { return this.site + " - 學的不僅是技術,更是夢想!"; } } }) </script>
<div id="vue_det"> <h1>site : {{site}}</h1> <h1>url : {{url}}</h1> <h1>{{details()}}</h1> </div> <script type="text/javascript"> var vm = new Vue({ el: '#vue_det', data: { site: "菜鳥教程", url: "www.runoob.com", alexa: "10000" }, methods: { details: function() { return this.site + " - 學的不僅是技術,更是夢想!"; } } }) </script>
el
參數,它是 DOM 元素中的 id。在上面實例中 id 爲 vue_det。這意味着我們接下來的改動全部在以上指定的 div 內,div 外部不受影響。<div id = "vue_det"></div>
<div id = "vue_det"></div>
data
用於定義屬性,實例中有三個屬性分別爲:site、url、alexa。methods
用於定義的函數,可以通過 return 來返回函數值。{{ }}
用於輸出對象屬性和函數返回值。<div id="vue_det"> <h1>site : {{site}}</h1> <h1>url : {{url}}</h1> <h1>{{details()}}</h1> </div>
<div id="vue_det"> <h1>site : {{site}}</h1> <h1>url : {{url}}</h1> <h1>{{details()}}</h1> </div>
當這些屬性的值發生改變時,html 視圖將也會產生相應的變化
。<div id="vue_det"> <h1>site : {{site}}</h1> <h1>url : {{url}}</h1> <h1>Alexa : {{alexa}}</h1> </div> <script type="text/javascript"> // 我們的數據對象 var data = { site: "菜鳥教程", url: "www.runoob.com", alexa: 10000} var vm = new Vue({ el: '#vue_det', data: data }) // 它們引用相同的對象! document.write(vm.site === data.site) // true document.write("<br>") // 設置屬性也會影響到原始數據 vm.site = "Runoob" document.write(data.site + "<br>") // Runoob // ……反之亦然 data.alexa = 1234 document.write(vm.alexa) // 1234 </script>
<div id="vue_det"> <h1>site : {{site}}</h1> <h1>url : {{url}}</h1> <h1>Alexa : {{alexa}}</h1> </div> <script type="text/javascript"> // 我們的數據對象 var data = { site: "菜鳥教程", url: "www.runoob.com", alexa: 10000} var vm = new Vue({ el: '#vue_det', data: data }) // 它們引用相同的對象! document.write(vm.site === data.site) // true document.write("<br>") // 設置屬性也會影響到原始數據 vm.site = "Runoob" document.write(data.site + "<br>") // Runoob // ……反之亦然 data.alexa = 1234 document.write(vm.alexa) // 1234 </script>
<div id="vue_det"> <h1>site : {{site}}</h1> <h1>url : {{url}}</h1> <h1>Alexa : {{alexa}}</h1> </div> <script type="text/javascript"> // 我們的數據對象 var data = { site: "菜鳥教程", url: "www.runoob.com", alexa: 10000} var vm = new Vue({ el: '#vue_det', data: data }) document.write(vm.$data === data) // true document.write("<br>") // true document.write(vm.$el === document.getElementById('vue_det')) // true </script>
<div id="vue_det"> <h1>site : {{site}}</h1> <h1>url : {{url}}</h1> <h1>Alexa : {{alexa}}</h1> </div> <script type="text/javascript"> // 我們的數據對象 var data = { site: "菜鳥教程", url: "www.runoob.com", alexa: 10000} var vm = new Vue({ el: '#vue_det', data: data }) document.write(vm.$data === data) // true document.write("<br>") // true document.write(vm.$el === document.getElementById('vue_det')) // true </script>
<div id="app"> <p>{{ message }}</p> </div>
<div id="app"> <p>{{ message }}</p> </div>
<div id="app"> <div v-html="message"></div> </div> <script> new Vue({ el: '#app', data: { message: '<h1>菜鳥教程</h1>' } }) </script>
<div id="app"> <div v-html="message"></div> </div> <script> new Vue({ el: '#app', data: { message: '<h1>菜鳥教程</h1>' } }) </script>
<div id="app"> <label for="r1">修改顏色</label><input type="checkbox" v-model="class1" id="r1"> <br><br> <div v-bind:class="{'class1': cls1}"> v-bind:class 指令 </div> </div> <script> new Vue({ el: '#app', data:{ cls1: false } }); </script>
<div id="app"> <label for="r1">修改顏色</label><input type="checkbox" v-model="class1" id="r1"> <br><br> <div v-bind:class="{'class1': cls1}"> v-bind:class 指令 </div> </div> <script> new Vue({ el: '#app', data:{ cls1: false } }); </script>
<div id="app"> {{5+5}}<br> {{ ok ? 'YES' : 'NO' }}<br> {{ message.split('').reverse().join('') }} <div v-bind:id="'list-' + id">菜鳥教程</div> </div> <script> new Vue({ el: '#app', data: { ok: true, message: 'RUNOOB', id : 1 } }) </script>
<div id="app"> {{5+5}}<br> {{ ok ? 'YES' : 'NO' }}<br> {{ message.split('').reverse().join('') }} <div v-bind:id="'list-' + id">菜鳥教程</div> </div> <script> new Vue({ el: '#app', data: { ok: true, message: 'RUNOOB', id : 1 } }) </script>
v- 前綴
的特殊屬性。<div id="app"> <p v-if="seen">現在你看到我了</p> </div> <script> new Vue({ el: '#app', data: { seen: true } }) </script>
<div id="app"> <p v-if="seen">現在你看到我了</p> </div> <script> new Vue({ el: '#app', data: { seen: true } }) </script>
這裏, v-if 指令將根據表達式 seen 的值(true 或 false )來決定是否插入 p 元素。
6. 參數
參數在指令後以冒號指明。例如, v-bind 指令被用來響應地更新 HTML 屬性:
<div id="app"> <pre><a v-bind:href="url">菜鳥教程</a></pre> </div> <script> new Vue({ el: '#app', data: { url: 'http://www.runoob.com' } }) </script>
<div id="app"> <pre><a v-bind:href="url">菜鳥教程</a></pre> </div> <script> new Vue({ el: '#app', data: { url: 'http://www.runoob.com' } }) </script>
在這裏 href 是參數,告知 v-bind 指令將該元素的 href 屬性與表達式 url 的值綁定。
另一個例子是 v-on 指令,它用於監聽 DOM 事件:
<a v-on:click="doSomething"> 在這裏參數是監聽的事件名。
<a v-on:click="doSomething"> 在這裏參數是監聽的事件名。
<form v-on:submit.prevent="onSubmit"></form>
<form v-on:submit.prevent="onSubmit"></form>
<div id="app"> <p>{{ message }}</p> <input v-model="message"> </div> <script> new Vue({ el: '#app', data: { message: 'Runoob!' } }) </script>
<div id="app"> <p>{{ message }}</p> <input v-model="message"> </div> <script> new Vue({ el: '#app', data: { message: 'Runoob!' } }) </script>
v-model 指令
用來在 input、select、text、checkbox、radio 等表單控件元素上創建雙向數據綁定,根據表單上的值,自動更新綁定的元素的值。
v-model用在表單控件上的,用於實現雙向數據綁定,所以如果你用在除了表單控件以外的標籤是沒有任何效果的
。
按鈕的事件我們可以使用 v-on 監聽事件,並對用戶的輸入進行響應。
以下實例在用戶點擊按鈕後對字符串進行反轉操作:
<div id="app"> <p>{{ message }}</p> <button v-on:click="reverseMessage">反轉字符串</button> </div> <script> new Vue({ el: '#app', data: { message: 'Runoob!' }, methods: { reverseMessage: function () { this.message = this.message.split('').reverse().join('') } } }) </script>
<div id="app"> <p>{{ message }}</p> <button v-on:click="reverseMessage">反轉字符串</button> </div> <script> new Vue({ el: '#app', data: { message: 'Runoob!' }, methods: { reverseMessage: function () { this.message = this.message.split('').reverse().join('') } } }) </script>
<!-- 在兩個大括號中 --> {{ message | capitalize }} <!-- 在 v-bind 指令中 --> <div v-bind:id="rawId | formatId"></div>
<!-- 在兩個大括號中 --> {{ message | capitalize }} <!-- 在 v-bind 指令中 --> <div v-bind:id="rawId | formatId"></div>
過濾器函數接受表達式的值作爲第一個參數。
以下實例對輸入的字符串第一個字母轉爲大寫
<div id="app"> {{ message | capitalize }} </div> <script> new Vue({ el: '#app', data: { message: 'runoob' }, filters: { capitalize: function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) } } }) </script>
<div id="app"> {{ message | capitalize }} </div> <script> new Vue({ el: '#app', data: { message: 'runoob' }, filters: { capitalize: function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) } } }) </script>
過濾器可以串聯:
{{ message | filterA | filterB }}
過濾器是 JavaScript 函數,因此可以接受參數:
{{ message | filterA('arg1', arg2) }}
這裏,message 是第一個參數,字符串 ‘arg1’ 將傳給過濾器作爲第二個參數, arg2 表達式的值將被求值然後傳給過濾器作爲第三個參數。
v-bind 縮寫
<!-- 完整語法 --> <a v-bind:href="url"></a> <!-- 縮寫 --> <a :href="url"></a>
<!-- 完整語法 --> <a v-bind:href="url"></a> <!-- 縮寫 --> <a :href="url"></a>
v-on 縮寫
<!-- 完整語法 --> <a v-on:click="doSomething"></a> <!-- 縮寫 --> <a @click="doSomething"></a>
<!-- 完整語法 --> <a v-on:click="doSomething"></a> <!-- 縮寫 --> <a @click="doSomething"></a>
<div id="app"> <p v-if="seen">現在你看到我了</p> <template v-if="ok"> <h1>菜鳥教程</h1> <p>學的不僅是技術,更是夢想!</p> <p>哈哈哈,打字辛苦啊!!!</p> </template> </div> <script> new Vue({ el: '#app', data: { seen: true, ok: true } }) </script>
<div id="app"> <p v-if="seen">現在你看到我了</p> <template v-if="ok"> <h1>菜鳥教程</h1> <p>學的不僅是技術,更是夢想!</p> <p>哈哈哈,打字辛苦啊!!!</p> </template> </div> <script> new Vue({ el: '#app', data: { seen: true, ok: true } }) </script>
這裏, v-if 指令將根據表達式 seen 的值(true 或 false )來決定是否插入 p 元素。
在字符串模板中,如 Handlebars ,我們得像這樣寫一個條件塊:
<!-- Handlebars 模板 --> {{#if ok}} <h1>Yes</h1> {{/if}}
<!-- Handlebars 模板 --> {{#if ok}} <h1>Yes</h1> {{/if}}
<div id="app"> <div v-if="Math.random() > 0.5"> Sorry </div> <div v-else> Not sorry </div> </div> <script> new Vue({ el: '#app' }) </script>
<div id="app"> <div v-if="Math.random() > 0.5"> Sorry </div> <div v-else> Not sorry </div> </div> <script> new Vue({ el: '#app' }) </script>
<div id="app"> <div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <div v-else> Not A/B/C </div> </div> <script> new Vue({ el: '#app', data: { type: 'C' } }) </script>
<div id="app"> <div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <div v-else> Not A/B/C </div> </div> <script> new Vue({ el: '#app', data: { type: 'C' } }) </script>
<h1 v-show="ok">Hello!</h1>
<h1 v-show="ok">Hello!</h1>
v-for 指令需要以 site in sites 形式的特殊語法, sites 是源數據數組並且 site 是數組元素迭代的別名。
v-for 可以綁定數據到數組來渲染一個列表:
<div id="app"> <ol> <li v-for="site in sites"> {{ site.name }} </li> </ol> </div> <script> new Vue({ el: '#app', data: { sites: [ { name: 'Runoob' }, { name: 'Google' }, { name: 'Taobao' } ] } }) </script>
<div id="app"> <ol> <li v-for="site in sites"> {{ site.name }} </li> </ol> </div> <script> new Vue({ el: '#app', data: { sites: [ { name: 'Runoob' }, { name: 'Google' }, { name: 'Taobao' } ] } }) </script>
模板中使用 v-for:
<ul> <template v-for="site in sites"> <li>{{ site.name }}</li> <li>--------------</li> </template> </ul>
<ul> <template v-for="site in sites"> <li>{{ site.name }}</li> <li>--------------</li> </template> </ul>
<div id="app"> <ul> <li v-for="value in object"> {{ value }} </li> </ul> </div> <script> new Vue({ el: '#app', data: { object: { name: '菜鳥教程', url: 'http://www.runoob.com', slogan: '學的不僅是技術,更是夢想!' } } }) </script>
<div id="app"> <ul> <li v-for="value in object"> {{ value }} </li> </ul> </div> <script> new Vue({ el: '#app', data: { object: { name: '菜鳥教程', url: 'http://www.runoob.com', slogan: '學的不僅是技術,更是夢想!' } } }) </script>
你也可以提供第二個的參數爲鍵名
:
<div id="app"> <ul> <li v-for="(value, key) in object"> {{ key }} : {{ value }} </li> </ul> </div>
<div id="app"> <ul> <li v-for="(value, key) in object"> {{ key }} : {{ value }} </li> </ul> </div>
第三個參數爲索引
:
<div id="app"> <ul> <li v-for="(value, key, index) in object"> {{ index }}. {{ key }} : {{ value }} </li> </ul> </div>
<div id="app"> <ul> <li v-for="(value, key, index) in object"> {{ index }}. {{ key }} : {{ value }} </li> </ul> </div>
v-for 迭代整數
v-for 也可以循環整數
<div id="app"> <ul> <li v-for="n in 10"> {{ n }} </li> </ul> </div>
<div id="app"> <ul> <li v-for="n in 10"> {{ n }} </li> </ul> </div>
計算屬性在處理一些複雜邏輯時是很有用的。
可以看下以下反轉字符串的例子:
實例1
<div id="app"> {{ message.split('').reverse().join('') }} </div>
<div id="app"> {{ message.split('').reverse().join('') }} </div>
實例 1 中模板變的很複雜起來,也不容易看懂理解。
接下來我們看看使用了計算屬性的實例:
<div id="app"> <p>原始字符串: {{ message }}</p> <p>計算後反轉字符串: {{ reversedMessage }}</p> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Runoob!' }, computed: { // 計算屬性的 getter reversedMessage: function () { // `this` 指向 vm 實例 return this.message.split('').reverse().join('') } } }) </script>
<div id="app"> <p>原始字符串: {{ message }}</p> <p>計算後反轉字符串: {{ reversedMessage }}</p> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Runoob!' }, computed: { // 計算屬性的 getter reversedMessage: function () { // `this` 指向 vm 實例 return this.message.split('').reverse().join('') } } }) </script>
實例 2 中聲明瞭一個計算屬性 reversedMessage 。
提供的函數將用作屬性 vm.reversedMessage 的 getter 。
vm.reversedMessage 依賴於 vm.message,在 vm.message 發生改變時,vm.reversedMessage 也會更新。
但是 computed 是基於它的依賴緩存,只有相關依賴發生改變時纔會重新取值
。而使用 methods ,在重新渲染的時候,函數總會重新調用執行。methods: { reversedMessage2: function () { return this.message.split('').reverse().join('') } }
可以說使用 computed 性能會更好,但是如果你不希望緩存,你可以使用 methods 屬性。
var vm = new Vue({ el: '#app', data: { name: 'Google', url: 'http://www.google.com' }, computed: { site: { // getter get: function () { return this.name + ' ' + this.url }, // setter set: function (newValue) { var names = newValue.split(' ') this.name = names[0] this.url = names[names.length - 1] } } } }) // 調用 setter, vm.name 和 vm.url 也會被對應更新 vm.site = '菜鳥教程 http://www.runoob.com'; document.write('name: ' + vm.name); document.write('<br>'); document.write('url: ' + vm.url);
本章節,我們將爲大家介紹 Vue.js 監聽屬性 watch,我們可以通過 watch 來響應數據的變化。
<div id = "app"> <p style = "font-size:25px;">計數器: {{ counter }}</p> <button @click = "counter++" style = "font-size:25px;">點我</button> </div> <script type = "text/javascript"> var vm = new Vue({ el: '#app', data: { counter: 1 } }); vm.$watch('counter', function(nval, oval) { alert('計數器值的變化 :' + oval + ' 變爲 ' + nval + '!'); }); </script>
<div id = "app"> <p style = "font-size:25px;">計數器: {{ counter }}</p> <button @click = "counter++" style = "font-size:25px;">點我</button> </div> <script type = "text/javascript"> var vm = new Vue({ el: '#app', data: { counter: 1 } }); vm.$watch('counter', function(nval, oval) { alert('計數器值的變化 :' + oval + ' 變爲 ' + nval + '!'); }); </script>
<div id = "computed_props"> 千米 : <input type = "text" v-model = "kilometers"> 米 : <input type = "text" v-model = "meters"> </div> <p id="info"></p> <script type = "text/javascript"> var vm = new Vue({ el: '#computed_props', data: { kilometers : 0, meters:0 }, methods: { }, computed :{ }, watch : { kilometers:function(val) { this.kilometers = val; this.meters = val * 1000; }, meters : function (val) { this.kilometers = val/ 1000; this.meters = val; } } }); // $watch 是一個實例方法 vm.$watch('kilometers', function (newValue, oldValue) { // 這個回調將在 vm.kilometers 改變後調用 document.getElementById ("info").innerHTML = "修改前值爲: " + oldValue + ",修改後值爲: " + newValue; }) </script>
<div id = "computed_props"> 千米 : <input type = "text" v-model = "kilometers"> 米 : <input type = "text" v-model = "meters"> </div> <p id="info"></p> <script type = "text/javascript"> var vm = new Vue({ el: '#computed_props', data: { kilometers : 0, meters:0 }, methods: { }, computed :{ }, watch : { kilometers:function(val) { this.kilometers = val; this.meters = val * 1000; }, meters : function (val) { this.kilometers = val/ 1000; this.meters = val; } } }); // $watch 是一個實例方法 vm.$watch('kilometers', function (newValue, oldValue) { // 這個回調將在 vm.kilometers 改變後調用 document.getElementById ("info").innerHTML = "修改前值爲: " + oldValue + ",修改後值爲: " + newValue; }) </script>
class 與 style 是 HTML 元素的屬性,用於設置元素的樣式,我們可以用 v-bind 來設置樣式屬性。
Vue.js v-bind 在處理 class 和 style 時, 專門增強了它。表達式的結果類型除了字符串之外,還可以是對象或數組
。
<div v-bind:class="{ active: isActive }"></div>
<div v-bind:class="{ active: isActive }"></div>
以上實例 div class 爲:
<div class="active"></div>
<div class="active"></div>
我們也可以在對象中傳入更多屬性用來動態切換多個 class 。
text-danger 類背景顏色覆蓋了 active 類的背景色:
<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"> </div> <script> new Vue({ el: '#app', data: { isActive: true, hasError: true } }) </script>
<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"> </div> <script> new Vue({ el: '#app', data: { isActive: true, hasError: true } }) </script>
以上實例 div class 爲:
<div class="static active text-danger"></div>
<div class="static active text-danger"></div>
我們也可以直接綁定數據裏的一個對象:
text-danger 類背景顏色覆蓋了 active 類的背景色:
<div id="app"> <div v-bind:class="classObject"></div> </div> <script> new Vue({ el: '#app', data: { classObject: { active: true, 'text-danger': true } } }) </script>
<div id="app"> <div v-bind:class="classObject"></div> </div> <script> new Vue({ el: '#app', data: { classObject: { active: true, 'text-danger': true } } }) </script>
此外,我們也可以在這裏綁定返回對象的計算屬性。這是一個常用且強大的模式:
new Vue({ el: '#app', data: { isActive: true, error: null }, computed: { classObject: function () { return { active: this.isActive && !this.error, 'text-danger': this.error && this.error.type === 'fatal', } } } })
<div v-bind:class="[activeClass, errorClass]"></div>
<div v-bind:class="[activeClass, errorClass]"></div>
以上實例 div class 爲:
<div class="active text-danger"></div>
<div class="active text-danger"></div>
我們還可以使用三元表達式來切換列表中的 class :
errorClass 是始終存在的
,isActive 爲 true 時添加 activeClass 類:
<div v-bind:class="[errorClass ,isActive ? activeClass : '']"></div>
<div v-bind:class="[errorClass ,isActive ? activeClass : '']"></div>
v-bind:style
直接設置樣式:<div id="app"> <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">菜鳥教程</div> </div>
<div id="app"> <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">菜鳥教程</div> </div>
以上實例 div style 爲:
<div style="color: green; font-size: 30px;">菜鳥教程</div>
<div style="color: green; font-size: 30px;">菜鳥教程</div>
也可以直接綁定到一個樣式對象,讓模板更清晰:
<div id="app"> <div v-bind:style="styleObject">菜鳥教程</div> </div>
<div id="app"> <div v-bind:style="styleObject">菜鳥教程</div> </div>
v-bind:style 可以使用數組將多個樣式對象應用到一個元素上:
<div id="app"> <div v-bind:style="[baseStyles, overridingStyles]">菜鳥教程</div> </div> <script> new Vue({ el: '#app', data: { baseStyles: { color: 'green', fontSize: '30px' }, overridingStyles: { 'font-weight': 'bold' } } }) </script>
<div id="app"> <div v-bind:style="[baseStyles, overridingStyles]">菜鳥教程</div> </div> <script> new Vue({ el: '#app', data: { baseStyles: { color: 'green', fontSize: '30px' }, overridingStyles: { 'font-weight': 'bold' } } }) </script>
事件監聽可以使用 v-on 指令:
<div id="app"> <button v-on:click="counter += 1">增加 1</button> <p>這個按鈕被點擊了 {{ counter }} 次。</p> </div> <script> new Vue({ el: '#app', data: { counter: 0 } }) </script>
<div id="app"> <button v-on:click="counter += 1">增加 1</button> <p>這個按鈕被點擊了 {{ counter }} 次。</p> </div> <script> new Vue({ el: '#app', data: { counter: 0 } }) </script>
通常情況下,我們需要使用一個方法來調用 JavaScript 方法。
v-on 可以接收一個定義的方法來調用。
<div id="app"> <!-- `greet` 是在下面定義的方法名 --> <button v-on:click="greet">Greet</button> </div> <script> var app = new Vue({ el: '#app', data: { name: 'Vue.js' }, // 在 `methods` 對象中定義方法 methods: { greet: function (event) { // `this` 在方法裏指當前 Vue 實例 alert('Hello ' + this.name + '!') // `event` 是原生 DOM 事件 if (event) { alert(event.target.tagName) } } } }) // 也可以用 JavaScript 直接調用方法 app.greet() // -> 'Hello Vue.js!' </script>
<div id="app"> <!-- `greet` 是在下面定義的方法名 --> <button v-on:click="greet">Greet</button> </div> <script> var app = new Vue({ el: '#app', data: { name: 'Vue.js' }, // 在 `methods` 對象中定義方法 methods: { greet: function (event) { // `this` 在方法裏指當前 Vue 實例 alert('Hello ' + this.name + '!') // `event` 是原生 DOM 事件 if (event) { alert(event.target.tagName) } } } }) // 也可以用 JavaScript 直接調用方法 app.greet() // -> 'Hello Vue.js!' </script>
除了直接綁定到一個方法,也可以用內聯 JavaScript 語句:
<div id="app"> <button v-on:click="say('hi')">Say hi</button> <button v-on:click="say('what')">Say what</button> </div> <script> new Vue({ el: '#app', methods: { say: function (message) { alert(message) } } }) </script>
<div id="app"> <button v-on:click="say('hi')">Say hi</button> <button v-on:click="say('what')">Say what</button> </div> <script> new Vue({ el: '#app', methods: { say: function (message) { alert(message) } } }) </script>
Vue.js通過由點(.)表示的指令後綴來調用修飾符。
<!-- 阻止單擊事件冒泡 --> <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> <!-- click 事件只能點擊一次,2.1.4版本新增 --> <a v-on:click.once="doThis"></a>
<!-- 阻止單擊事件冒泡 --> <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> <!-- click 事件只能點擊一次,2.1.4版本新增 --> <a v-on:click.once="doThis"></a>
<!-- 只有在 keyCode 是 13 時調用 vm.submit() --> <input v-on:keyup.13="submit">
<!-- 只有在 keyCode 是 13 時調用 vm.submit() --> <input v-on:keyup.13="submit">
記住所有的 keyCode 比較困難,所以 Vue 爲最常用的按鍵提供了別名:
<!-- 同上 --> <input v-on:keyup.enter="submit"> <!-- 縮寫語法 --> <input @keyup.enter="submit">
<!-- 同上 --> <input v-on:keyup.enter="submit"> <!-- 縮寫語法 --> <input @keyup.enter="submit">
全部的按鍵別名:
<p><!-- Alt + C --> <input @keyup.alt.67="clear"> <!-- Ctrl + Click --> <div @click.ctrl="doSomething">Do something</div>
<p><!-- Alt + C --> <input @keyup.alt.67="clear"> <!-- Ctrl + Click --> <div @click.ctrl="doSomething">Do something</div>
這節我們爲大家介紹 Vue.js 表單上的應用。
你可以用 v-model 指令在表單控件元素上創建雙向數據綁定。
v-model 會根據控件類型自動選取正確的方法來更新元素。
<div id="app"> <p>input 元素:</p> <input v-model="message" placeholder="編輯我……"> <p>消息是: {{ message }}</p> <p>textarea 元素:</p> <p style="white-space: pre">{{ message2 }}</p> <textarea v-model="message2" placeholder="多行文本輸入……"></textarea> </div> <script> new Vue({ el: '#app', data: { message: 'Runoob', message2: '菜鳥教程\r\nhttp://www.runoob.com' } }) </script>
<div id="app"> <p>input 元素:</p> <input v-model="message" placeholder="編輯我……"> <p>消息是: {{ message }}</p> <p>textarea 元素:</p> <p style="white-space: pre">{{ message2 }}</p> <textarea v-model="message2" placeholder="多行文本輸入……"></textarea> </div> <script> new Vue({ el: '#app', data: { message: 'Runoob', message2: '菜鳥教程\r\nhttp://www.runoob.com' } }) </script>
<div id="app"> <p>單個複選框:</p> <input type="checkbox" id="checkbox" v-model="checked"> <label for="checkbox">{{ checked }}</label> <p>多個複選框:</p> <input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames"> <label for="runoob">Runoob</label> <input type="checkbox" id="google" value="Google" v-model="checkedNames"> <label for="google">Google</label> <input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames"> <label for="taobao">taobao</label> <br> <span>選擇的值爲: {{ checkedNames }}</span> </div> <script> new Vue({ el: '#app', data: { checked : false, checkedNames: [] } }) </script>
<div id="app"> <p>單個複選框:</p> <input type="checkbox" id="checkbox" v-model="checked"> <label for="checkbox">{{ checked }}</label> <p>多個複選框:</p> <input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames"> <label for="runoob">Runoob</label> <input type="checkbox" id="google" value="Google" v-model="checkedNames"> <label for="google">Google</label> <input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames"> <label for="taobao">taobao</label> <br> <span>選擇的值爲: {{ checkedNames }}</span> </div> <script> new Vue({ el: '#app', data: { checked : false, checkedNames: [] } }) </script>
<div id="app"> <input type="radio" id="runoob" value="Runoob" v-model="picked"> <label for="runoob">Runoob</label> <br> <input type="radio" id="google" value="Google" v-model="picked"> <label for="google">Google</label> <br> <span>選中值爲: {{ picked }}</span> </div> <script> new Vue({ el: '#app', data: { picked : 'Runoob' } }) </script>
<div id="app"> <input type="radio" id="runoob" value="Runoob" v-model="picked"> <label for="runoob">Runoob</label> <br> <input type="radio" id="google" value="Google" v-model="picked"> <label for="google">Google</label> <br> <span>選中值爲: {{ picked }}</span> </div> <script> new Vue({ el: '#app', data: { picked : 'Runoob' } }) </script>
<div id="app"> <select v-model="selected" name="fruit"> <option value="">選擇一個網站</option> <option value="www.runoob.com">Runoob</option> <option value="www.google.com">Google</option> </select> <div id="output"> 選擇的網站是: {{selected}} </div> </div> <script> new Vue({ el: '#app', data: { selected: '' } }) </script>
<div id="app"> <select v-model="selected" name="fruit"> <option value="">選擇一個網站</option> <option value="www.runoob.com">Runoob</option> <option value="www.google.com">Google</option> </select> <div id="output"> 選擇的網站是: {{selected}} </div> </div> <script> new Vue({ el: '#app', data: { selected: '' } }) </script>
.lazy
在默認情況下, v-model 在 input 事件中同步輸入框的值與數據,但你可以添加一個修飾符 lazy ,從而轉變爲在 change 事件中同步:
<!-- 在 "change" 而不是 "input" 事件中更新 --> <input v-model.lazy="msg" >
<!-- 在 "change" 而不是 "input" 事件中更新 --> <input v-model.lazy="msg" >
.number
如果想自動將用戶的輸入值轉爲 Number 類型(如果原值的轉換結果爲 NaN 則返回原值),可以添加一個修飾符 number 給 v-model 來處理輸入值:
這通常很有用,因爲在 type=「number」 時 HTML 中輸入的值也總是會返回字符串類型。
.trim
如果要自動過濾用戶輸入的首尾空格,可以添加 trim 修飾符到 v-model 上過濾輸入:
<input v-model.trim="msg">
<input v-model.trim="msg">
組件(Component)
是 Vue.js 最強大的功能之一。
組件可以擴展 HTML 元素,封裝可重用的代碼。
組件系統讓我們可以用獨立可複用的小組件來構建大型應用,幾乎任意類型的應用的界面都可以抽象爲一個組件樹。
註冊一個全局組件語法格式如下
:
Vue.component(tagName, options)
tagName 爲組件名,options 爲配置選項。註冊後,我們可以使用以下方式來調用組件:
<tagName></tagName>
<tagName></tagName>
<div id="app"> <runoob></runoob> </div> <script> // 註冊 Vue.component('runoob', { template: '<h1>自定義組件!</h1>' }) // 創建根實例 new Vue({ el: '#app' }) </script>
<div id="app"> <runoob></runoob> </div> <script> // 註冊 Vue.component('runoob', { template: '<h1>自定義組件!</h1>' }) // 創建根實例 new Vue({ el: '#app' }) </script>
<div id="app"> <runoob></runoob> </div> <script> var Child = { template: '<h1>自定義組件!</h1>' } // 創建根實例 new Vue({ el: '#app', components: { // <runoob> 將只在父模板可用 'runoob': Child } }) </script>
<div id="app"> <runoob></runoob> </div> <script> var Child = { template: '<h1>自定義組件!</h1>' } // 創建根實例 new Vue({ el: '#app', components: { // <runoob> 將只在父模板可用 'runoob': Child } }) </script>
prop 是父組件用來傳遞數據的一個自定義屬性。
父組件的數據需要通過 props 把數據傳給子組件,子組件需要顯式地用 props 選項聲明 「prop」:
<div id="app"> <child message="hello!"></child> </div> <script> // 註冊 Vue.component('child', { // 聲明 props props: ['message'], // 同樣也可以在 vm 實例中像 "this.message" 這樣使用 template: '<span>{{ message }}</span>' }) // 創建根實例 new Vue({ el: '#app' }) </script>
<div id="app"> <child message="hello!"></child> </div> <script> // 註冊 Vue.component('child', { // 聲明 props props: ['message'], // 同樣也可以在 vm 實例中像 "this.message" 這樣使用 template: '<span>{{ message }}</span>' }) // 創建根實例 new Vue({ el: '#app' }) </script>
<div id="app"> <div> <input v-model="parentMsg"> <br> <child v-bind:message="parentMsg"></child> </div> </div> <script> // 註冊 Vue.component('child', { // 聲明 props props: ['message'], // 同樣也可以在 vm 實例中像 "this.message" 這樣使用 template: '<span>{{ message }}</span>' }) // 創建根實例 new Vue({ el: '#app', data: { parentMsg: '父組件內容' } }) </script>
<div id="app"> <div> <input v-model="parentMsg"> <br> <child v-bind:message="parentMsg"></child> </div> </div> <script> // 註冊 Vue.component('child', { // 聲明 props props: ['message'], // 同樣也可以在 vm 實例中像 "this.message" 這樣使用 template: '<span>{{ message }}</span>' }) // 創建根實例 new Vue({ el: '#app', data: { parentMsg: '父組件內容' } }) </script>
注意: prop 是單向綁定的:當父組件的屬性變化時,將傳導給子組件,但是不會反過來。
prop 是一個對象而不是字符串數組時,它包含驗證要求:
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 可以是下面原生構造器:
type 也可以是一個自定義構造器,使用 instanceof 檢測。
父組件是使用 props 傳遞數據給子組件,但如果子組件要把數據傳遞回去,就需要使用自定義事件!
我們可以使用 v-on 綁定自定義事件, 每個 Vue 實例都實現了事件接口(Events interface),即:
另外,父組件可以在使用子組件的地方直接用 v-on 來監聽子組件觸發的事件。
以下實例中子組件已經和它外部完全解耦了。它所做的只是觸發一個父組件關心的內部事件。
<div id="app"> <div id="counter-event-example"> <p>{{ total }}</p> <button-counter v-on:increment="incrementTotal"></button-counter> <button-counter v-on:increment="incrementTotal"></button-counter> </div> </div> <script> Vue.component('button-counter', { template: '<button v-on:click="incrementHandler">{{ counter }}</button>', data: function () { return { counter: 0 } }, methods: { incrementHandler: function () { this.counter += 1 this.$emit('increment') } }, }) new Vue({ el: '#counter-event-example', data: { total: 0 }, methods: { incrementTotal: function () { this.total += 1 } } }) </script>
<div id="app"> <div id="counter-event-example"> <p>{{ total }}</p> <button-counter v-on:increment="incrementTotal"></button-counter> <button-counter v-on:increment="incrementTotal"></button-counter> </div> </div> <script> Vue.component('button-counter', { template: '<button v-on:click="incrementHandler">{{ counter }}</button>', data: function () { return { counter: 0 } }, methods: { incrementHandler: function () { this.counter += 1 this.$emit('increment') } }, }) new Vue({ el: '#counter-event-example', data: { total: 0 }, methods: { incrementTotal: function () { this.total += 1 } } }) </script>
如果你想在某個組件的根元素上監聽一個原生事件。可以使用 .native 修飾 v-on 。例如:
<my-component v-on:click.native="doTheThing"></my-component>
<my-component v-on:click.native="doTheThing"></my-component>
除了默認設置的核心指令( v-model 和 v-show ), Vue 也允許註冊自定義指令。
下面我們註冊一個全局指令
v-focus, 該指令的功能是在頁面加載時,元素獲得焦點:
<div id="app"> <p>頁面載入時,input 元素自動獲取焦點:</p> <input v-focus> </div> <script> // 註冊一個全局自定義指令 v-focus Vue.directive('focus', { // 當綁定元素插入到 DOM 中。 inserted: function (el) { // 聚焦元素 el.focus() } }) // 創建根實例 new Vue({ el: '#app' }) </script>
<div id="app"> <p>頁面載入時,input 元素自動獲取焦點:</p> <input v-focus> </div> <script> // 註冊一個全局自定義指令 v-focus Vue.directive('focus', { // 當綁定元素插入到 DOM 中。 inserted: function (el) { // 聚焦元素 el.focus() } }) // 創建根實例 new Vue({ el: '#app' }) </script>
我們也可以在實例使用 directives 選項來註冊局部指令
,這樣指令只能在這個實例中使用:
<div id="app"> <p>頁面載入時,input 元素自動獲取焦點:</p> <input v-focus> </div> <script> // 創建根實例 new Vue({ el: '#app', directives: { // 註冊一個局部的自定義指令 v-focus focus: { // 指令的定義 inserted: function (el) { // 聚焦元素 el.focus() } } } }) </script>
<div id="app"> <p>頁面載入時,input 元素自動獲取焦點:</p> <input v-focus> </div> <script> // 創建根實例 new Vue({ el: '#app', directives: { // 註冊一個局部的自定義指令 v-focus focus: { // 指令的定義 inserted: function (el) { // 聚焦元素 el.focus() } } } }) </script>
鉤子函數
指令定義函數提供了幾個鉤子函數(可選):
bind
: 只調用一次,指令第一次綁定到元素時調用,用這個鉤子函數可以定義一個在綁定時執行一次的初始化動作。
inserted
: 被綁定元素插入父節點時調用(父節點存在即可調用,不必存在於 document 中)。
update
: 被綁定元素所在的模板更新時調用,而不論綁定值是否變化。通過比較更新前後的綁定值,可以忽略不必要的模板更新(詳細的鉤子函數參數見下)。
componentUpdated
: 被綁定元素所在模板完成一次更新週期時調用。
unbind
: 只調用一次, 指令與元素解綁時調用。
鉤子函數的參數有:
el
: 指令所綁定的元素,可以用來直接操作 DOM 。
binding
: 一個對象,包含以下屬性:
以下實例演示了這些參數的使用:
<div id="app" v-runoob:hello.a.b="message"> </div> <script> Vue.directive('runoob', { bind: function (el, binding, vnode) { var s = JSON.stringify el.innerHTML = 'name: ' + s(binding.name) + '<br>' + 'value: ' + s(binding.value) + '<br>' + 'expression: ' + s(binding.expression) + '<br>' + 'argument: ' + s(binding.arg) + '<br>' + 'modifiers: ' + s(binding.modifiers) + '<br>' + 'vnode keys: ' + Object.keys(vnode).join(', ') } }) new Vue({ el: '#app', data: { message: '菜鳥教程!' } }) </script>
<div id="app" v-runoob:hello.a.b="message"> </div> <script> Vue.directive('runoob', { bind: function (el, binding, vnode) { var s = JSON.stringify el.innerHTML = 'name: ' + s(binding.name) + '<br>' + 'value: ' + s(binding.value) + '<br>' + 'expression: ' + s(binding.expression) + '<br>' + 'argument: ' + s(binding.arg) + '<br>' + 'modifiers: ' + s(binding.modifiers) + '<br>' + 'vnode keys: ' + Object.keys(vnode).join(', ') } }) new Vue({ el: '#app', data: { message: '菜鳥教程!' } }) </script>
有時候我們不需要其他鉤子函數,我們可以簡寫函數,如下格式:
Vue.directive('runoob', function (el, binding) { // 設置指令的背景顏色 el.style.backgroundColor = binding.value.color })
指令函數可接受所有合法的 JavaScript 表達式,以下實例傳入了 JavaScript 對象:
<div id="app"> <div v-runoob="{ color: 'green', text: '菜鳥教程!' }"></div> </div> <script> Vue.directive('runoob', function (el, binding) { // 簡寫方式設置文本及背景顏色 el.innerHTML = binding.value.text el.style.backgroundColor = binding.value.color }) new Vue({ el: '#app' }) </script>
<div id="app"> <div v-runoob="{ color: 'green', text: '菜鳥教程!' }"></div> </div> <script> Vue.directive('runoob', function (el, binding) { // 簡寫方式設置文本及背景顏色 el.innerHTML = binding.value.text el.style.backgroundColor = binding.value.color }) new Vue({ el: '#app' }) </script>
過渡
Vue 在插入、更新或者移除 DOM 時,提供多種不同方式的應用過渡效果。
Vue 提供了內置的過渡封裝組件
,該組件用於包裹要實現過渡效果的組件。
語法格式
<transition name = "nameoftransition"> <div></div> </transition>
<transition name = "nameoftransition"> <div></div> </transition>
我們可以通過以下實例來理解 Vue 的過渡是如何實現的:
<style> /* 可以設置不同的進入和離開動畫 */ /* 設置持續時間和動畫函數 */ .fade-enter-active, .fade-leave-active { transition: opacity 2s } .fade-enter, .fade-leave-to /* .fade-leave-active, 2.1.8 版本以下 */ { opacity: 0 } </style> <div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition name = "fade"> <p v-show = "show" v-bind:style = "styleobj">動畫實例</p> </transition> </div> <script type = "text/javascript"> var vm = new Vue({ el: '#databinding', data: { show:true, styleobj :{ fontSize:'30px', color:'red' } }, methods : { } }); </script>
<style> /* 可以設置不同的進入和離開動畫 */ /* 設置持續時間和動畫函數 */ .fade-enter-active, .fade-leave-active { transition: opacity 2s } .fade-enter, .fade-leave-to /* .fade-leave-active, 2.1.8 版本以下 */ { opacity: 0 } </style> <div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition name = "fade"> <p v-show = "show" v-bind:style = "styleobj">動畫實例</p> </transition> </div> <script type = "text/javascript"> var vm = new Vue({ el: '#databinding', data: { show:true, styleobj :{ fontSize:'30px', color:'red' } }, methods : { } }); </script>
實例中通過點擊 「點我」 按鈕將變量 show 的值從 true 變爲 false。如果爲 true 顯示子元素 p 標籤的內容。
下面這段代碼展示了 transition 標籤包裹了 p 標籤:
<transition name = "fade"> <p v-show = "show" v-bind:style = "styleobj">動畫實例</p> </transition>
<transition name = "fade"> <p v-show = "show" v-bind:style = "styleobj">動畫實例</p> </transition>
過渡其實就是一個淡入淡出的效果。Vue在元素顯示與隱藏的過渡中,提供了 6 個 class 來切換:
v-enter:定義進入過渡的開始狀態。在元素被插入之前生效,在元素被插入之後的下一幀移除
。
v-enter-active:定義進入過渡生效時的狀態。在整個進入過渡的階段中應用,在元素被插入之前生效,在過渡/動畫完成之後移除
。這個類可以被用來定義進入過渡的過程時間,延遲和曲線函數。
v-enter-to: 2.1.8版及以上 定義進入過渡的結束狀態。在元素被插入之後下一幀生效 (與此同時 v-enter 被移除),在過渡/動畫完成之後移除
。
v-leave: 定義離開過渡的開始狀態。在離開過渡被觸發時立刻生效,下一幀被移除
。
v-leave-active:定義離開過渡生效時的狀態。在整個離開過渡的階段中應用,在離開過渡被觸發時立刻生效,在過渡/動畫完成之後移除
。這個類可以被用來定義離開過渡的過程時間,延遲和曲線函數。
v-leave-to: 2.1.8版及以上 定義離開過渡的結束狀態。在離開過渡被觸發之後下一幀生效 (與此同時 v-leave 被刪除),在過渡/動畫完成之後移除
。
對於這些在過渡中切換的類名來說,如果你使用一個沒有名字的 ,則 v- 是這些類名的默認前綴。如果你使用了 ,那麼 v-enter 會替換爲 my-transition-enter。
v-enter-active 和 v-leave-active 可以控制進入/離開過渡的不同的緩和曲線,在下面章節會有個示例說明。
CSS 過渡
通常我們都使用 CSS 過渡來實現效果。
如下實例:
<div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition name="slide-fade"> <p v-if="show">hello</p> </transition> </div> <script type = "text/javascript"> new Vue({ el: '#databinding', data: { show: true } }) </script>
<div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition name="slide-fade"> <p v-if="show">hello</p> </transition> </div> <script type = "text/javascript"> new Vue({ el: '#databinding', data: { show: true } }) </script>
CSS 動畫
CSS 動畫用法類似 CSS 過渡,但是在動畫中 v-enter 類名在節點插入 DOM 後不會立即刪除,而是在 animationend 事件觸發時刪除。
<div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition name="bounce"> <p v-if="show">菜鳥教程 -- 學的不僅是技術,更是夢想!!!</p> </transition> </div> <script type = "text/javascript"> new Vue({ el: '#databinding', data: { show: true } }) </script>
<div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition name="bounce"> <p v-if="show">菜鳥教程 -- 學的不僅是技術,更是夢想!!!</p> </transition> </div> <script type = "text/javascript"> new Vue({ el: '#databinding', data: { show: true } }) </script>
自定義過渡的類名
我們可以通過以下特性來自定義過渡類名:
<div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition name="custom-classes-transition" enter-active-class="animated tada" leave-active-class="animated bounceOutRight" > <p v-if="show">菜鳥教程 -- 學的不僅是技術,更是夢想!!!</p> </transition> </div> <script type = "text/javascript"> new Vue({ el: '#databinding', data: { show: true } }) </script>
<div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition name="custom-classes-transition" enter-active-class="animated tada" leave-active-class="animated bounceOutRight" > <p v-if="show">菜鳥教程 -- 學的不僅是技術,更是夢想!!!</p> </transition> </div> <script type = "text/javascript"> new Vue({ el: '#databinding', data: { show: true } }) </script>
同時使用過渡和動畫
Vue 爲了知道過渡的完成,必須設置相應的事件監聽器。它可以是 transitionend 或 animationend ,這取決於給元素應用的 CSS 規則。如果你使用其中任何一種,Vue 能自動識別類型並設置監聽。
但是,在一些場景中,你需要給同一個元素同時設置兩種過渡動效,比如 animation 很快的被觸發並完成了,而 transition 效果還沒結束。在這種情況中,你就需要使用 type 特性並設置 animation 或 transition 來明確聲明你需要 Vue 監聽的類型。
顯性的過渡持續時間
在很多情況下,Vue 可以自動得出過渡效果的完成時機。默認情況下,Vue 會等待其在過渡效果的根元素的第一個 transitionend 或 animationend 事件。然而也可以不這樣設定——比如,我們可以擁有一個精心編排的一系列過渡效果,其中一些嵌套的內部元素相比於過渡效果的根元素有延遲的或更長的過渡效果。
在這種情況下你可以用 組件上的 duration 屬性定製一個顯性的過渡持續時間 (以毫秒計):
<transition :duration="1000">...</transition>
<transition :duration="1000">...</transition>
你也可以定製進入和移出的持續時間:
<transition :duration="{ enter: 500, leave: 800 }">...</transition>
<transition :duration="{ enter: 500, leave: 800 }">...</transition>
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>
<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>
JavaScript 代碼:
// ... 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 使用,也可以單獨使用。
當只用 JavaScript 過渡的時候,在 enter 和 leave 中必須使用 done 進行回調。否則,它們將被同步調用,過渡會立即完成。
推薦對於僅使用 JavaScript 過渡的元素添加 v-bind:css=「false」,Vue 會跳過 CSS 的檢測。這也可以避免過渡過程中 CSS 的影響。
一個使用 Velocity.js 的簡單例子:
<div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:leave="leave" v-bind:css="false" > <p v-if="show">菜鳥教程 -- 學的不僅是技術,更是夢想!!!</p> </transition> </div> <script type = "text/javascript"> new Vue({ el: '#databinding', 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 }) } } }) </script>
<div id = "databinding"> <button v-on:click = "show = !show">點我</button> <transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:leave="leave" v-bind:css="false" > <p v-if="show">菜鳥教程 -- 學的不僅是技術,更是夢想!!!</p> </transition> </div> <script type = "text/javascript"> new Vue({ el: '#databinding', 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 }) } } }) </script>
初始渲染的過渡
可以通過 appear 特性設置節點在初始渲染的過渡
<transition appear> <!-- ... --> </transition>
<transition appear> <!-- ... --> </transition>
這裏默認和進入/離開過渡一樣,同樣也可以自定義 CSS 類名。
<transition appear appear-class="custom-appear-class" appear-to-class="custom-appear-to-class" (2.1.8+) appear-active-class="custom-appear-active-class" > <!-- ... --> </transition>
<transition appear appear-class="custom-appear-class" appear-to-class="custom-appear-to-class" (2.1.8+) appear-active-class="custom-appear-active-class" > <!-- ... --> </transition>
自定義 JavaScript 鉤子:
<transition appear v-on:before-appear="customBeforeAppearHook" v-on:appear="customAppearHook" v-on:after-appear="customAfterAppearHook" v-on:appear-cancelled="customAppearCancelledHook" > <!-- ... --> </transition>
<transition appear v-on:before-appear="customBeforeAppearHook" v-on:appear="customAppearHook" v-on:after-appear="customAfterAppearHook" v-on:appear-cancelled="customAppearCancelledHook" > <!-- ... --> </transition>
多個元素的過渡
我們可以設置多個元素的過渡,一般列表與描述:
需要注意的是當有相同標籤名的元素切換時,需要通過 key 特性設置唯一的值來標記以讓 Vue 區分它們,否則 Vue 爲了效率只會替換相同標籤內部的內容。
<transition> <table v-if="items.length > 0"> <!-- ... --> </table> <p v-else>抱歉,沒有找到您查找的內容。</p> </transition>
<transition> <table v-if="items.length > 0"> <!-- ... --> </table> <p v-else>抱歉,沒有找到您查找的內容。</p> </transition>
如下實例:
<transition> <button v-if="isEditing" key="save"> Save </button> <button v-else key="edit"> Edit </button> </transition>
<transition> <button v-if="isEditing" key="save"> Save </button> <button v-else key="edit"> Edit </button> </transition>
在一些場景中,也可以通過給同一個元素的 key 特性設置不同的狀態來代替 v-if 和 v-else,上面的例子可以重寫爲:
<transition> <button v-bind:key="isEditing"> {{ isEditing ? 'Save' : 'Edit' }} </button> </transition>
<transition> <button v-bind:key="isEditing"> {{ isEditing ? 'Save' : 'Edit' }} </button> </transition>
使用多個 v-if 的多個元素的過渡可以重寫爲綁定了動態屬性的單個元素過渡。例如:
<transition> <button v-if="docState === 'saved'" key="saved"> Edit </button> <button v-if="docState === 'edited'" key="edited"> Save </button> <button v-if="docState === 'editing'" key="editing"> Cancel </button> </transition>
<transition> <button v-if="docState === 'saved'" key="saved"> Edit </button> <button v-if="docState === 'edited'" key="edited"> Save </button> <button v-if="docState === 'editing'" key="editing"> Cancel </button> </transition>
可以重寫爲:
<transition> <button v-bind:key="docState"> {{ buttonMessage }} </button> </transition> // ... computed: { buttonMessage: function () { switch (this.docState) { case 'saved': return 'Edit' case 'edited': return 'Save' case 'editing': return 'Cancel' } } }
<transition> <button v-bind:key="docState"> {{ buttonMessage }} </button> </transition> // ... computed: { buttonMessage: function () { switch (this.docState) { case 'saved': return 'Edit' case 'edited': return 'Save' case 'editing': return 'Cancel' } } }
混入 (mixins)
定義了一部分可複用的方法或者計算屬性。混入對象可以包含任意組件選項。當組件使用混入對象時,所有混入對象的選項將被混入該組件本身的選項。
來看一個簡單的實例:
var vm = new Vue({ el: '#databinding', data: { }, methods : { }, }); // 定義一個混入對象 var myMixin = { created: function () { this.startmixin() }, methods: { startmixin: function () { document.write("歡迎來到混入實例"); } } }; var Component = Vue.extend({ mixins: [myMixin] }) var component = new Component();
選項合併
當組件和混入對象含有同名選項時,這些選項將以恰當的方式混合。
比如,數據對象在內部會進行淺合併 (一層屬性深度),在和組件的數據發生衝突時以組件數據優先。
以下實例中,Vue 實例與混入對象包含了相同的方法。從輸出結果可以看出兩個選項合併了。
var mixin = { created: function () { document.write('混入調用' + '<br>') } } new Vue({ mixins: [mixin], created: function () { document.write('組件調用' + '<br>') } });
輸出結果爲:
混入調用
組件調用
如果 methods 選項中有相同的函數名,則 Vue 實例優先級會較高。如下實例,Vue 實例與混入對象的 methods 選項都包含了相同的函數:
var mixin = { methods: { hellworld: function () { document.write('HelloWorld 方法' + '<br>'); }, samemethod: function () { document.write('Mixin:相同方法名' + '<br>'); } } }; var vm = new Vue({ mixins: [mixin], methods: { start: function () { document.write('start 方法' + '<br>'); }, samemethod: function () { document.write('Main:相同方法名' + '<br>'); } } }); vm.hellworld(); vm.start(); vm.samemethod();
輸出結果爲:
HelloWorld 方法
start 方法
Main:相同方法名
以上實例,我們調用了以下三個方法:
vm.hellworld(); vm.start(); vm.samemethod();
從輸出結果 methods 選項中如果碰到相同的函數名則 Vue 實例有更高的優先級會執行輸出。
全局混入
也可以全局註冊混入對象。注意使用! 一旦使用全局混入對象,將會影響到 所有 之後創建的 Vue 實例。使用恰當時,可以爲自定義對象注入處理邏輯。
// 爲自定義的選項 'myOption' 注入一個處理器。 Vue.mixin({ created: function () { var myOption = this.$options.myOption if (myOption) { console.log(myOption) } } }) new Vue({ myOption: 'hello!' }) // => "hello!"
謹慎使用全局混入對象,因爲會影響到每個單獨創建的 Vue 實例 (包括第三方模板)。