會分兩天去寫常用的 Vue API。在卡斯伯老師的課程上之第八節,提到了以下的常用的 Vue API:
Extend
Filter
Set
Mixin
Directive
這邊我們就先來看看 Extend
和 Filter
可以如何使用吧:
Vue.extend 返回的是一個擴展實例構造器,也就是預設了部分選項的 Vue 實例構造器。其主要用來服務於 Vue.component,用來生成組件。可以簡單的理解為當在模板中遇到該組件名稱作為標籤的自定義元素時,會自動調用擴展實例構造器來生產組件實例,並掛載到自定義元素上。
我們用以下範例來解釋:
<div id="app">
<table class="table">
<tbody>
<tr is="row-component-one"
v-for="(item, key) in data"
v-if="key % 2" :item="item" :key="key">
</tr>
<tr is="row-component-two"
v-for="(item, key) in data"
v-if="(key - 1) % 2" :item="item" :key="key">
</tr>
</tbody>
</table>
</div>
<script type="text/x-template" id="row-component">
<tr>
<td>{{ item.name }}</td>
<td>{{ item.cash | currency | dollarSign }}</td>
<td>{{ item.icash | currency | dollarSign }}</td>
</tr>
</script>
<script type="text/x-template" id="row-component-two">
<tr class="bg-primary text-white">
<td>{{ item.name }}</td>
<td>{{ item.cash | currency | dollarSign }}</td>
<td>{{ item.icash | currency | dollarSign }}</td>
</tr>
</script>
var childOne = {
props: ['item'],
data: function() {
return {
data: {},
extendData: '這段文字是 extend 得到'
}
},
template: '#row-component',
filters: {
dollarSign: function(n) {
return `$ ${n}`
},
currency: function(n) {
return n.toFixed(2).replace(/./g, function(c, i, a) {
return i && c !== "." && ((a.length - i) % 3 === 0) ? ',' + c : c;
});
}
},
mounted: function() {
console.log('Extend:', this)
}
}
var childTwo = {
props: ['item'],
data: function() {
return {
data: {},
extendData: '這段文字是 extend 得到'
}
},
template: '#row-component-two',
filters: {
dollarSign: function(n) {
return `$ ${n}`
},
currency: function(n) {
return n.toFixed(2).replace(/./g, function(c, i, a) {
return i && c !== "." && ((a.length - i) % 3 === 0) ? ',' + c : c;
});
}
},
mounted: function() {
console.log('Extend:', this)
}
}
var app = new Vue({
el: '#app',
data: {
data: [{
name: '小明',
cash: 100,
icash: 500,
}, {
name: '杰倫',
cash: 10000,
icash: 5000,
}, {
name: '漂亮阿姨',
cash: 500,
icash: 500,
}, {
name: '老媽',
cash: 10000,
icash: 100,
}, ]
},
components: {
"row-component-one": childOne,
"row-component-two": childTwo,
},
mounted: function() {
console.log('Vue init:', this)
}
});
假設我們有兩個或多個差不多的元件,差異非常小只有少部分的不同,以上面的範例來看,元件之間的差異只有顏色上的不同而已,我們就可以用 extend
來處理,這裡可以把重複的部分抓取出來,之後要套用的時候可以更為快速。
我們先使用 Vue 的建構子,創建一個子類別,參數是一個包含 Component 選項的物件。這裏我們先把重複的元件剪下貼到 extend
中:
var newExtend = Vue.extend({
data: function() {
return {
data: {},
extendData: '這段文字是 extend 得到'
}
},
template: '#row-component',
filters: {
dollarSign: function(n) {
return `$ ${n}`
},
currency: function(n) {
return n.toFixed(2).replace(/./g, function(c, i, a) {
return i && c !== "." && ((a.length - i) % 3 === 0) ? ',' + c : c;
});
}
},
mounted: function() {
console.log('Extend:', this)
}
})
然後我們在 childOne 上使用 extend:
var childOne = {
props: ['item'],
extends: newExtend
}
這裏 childOne 使用 newExtend 作為基底然後來延伸使用,可以看到跟先前的畫面是一樣的。說到 延伸 這個詞有著可以多做些變化的意思,意思是說我們可以對延伸的元件做些調整,以 childTwo 為例改成以下樣子:
var childTwo = {
props: ['item'],
template: '#row-component-two',
extends: newExtend
}
這個樣子好像看不太出個所以然,那我們多加一個 mounted hook
以及新增 data 上去看看:
var childTwo = {
props: ['item'],
template: '#row-component-two',
extends: newExtend,
mounted() {
console.log('childTwo')
},
}
所以用 extend
它不僅會執行它自己本身的生命週期內的函式之外,如果在生命週期內加入新的函式的話,新的也同時會執行。此外可以看到新加入的 data 並沒有取代 extend
裡面的 data 而是同時並存,extend
不僅可以繼承原本的資料結構外,新的公能也可以不斷的加上去,當然如果更動的變數是 extend
內的 data 也是可以對他做變更的。
var childTwo = {
props: ['item'],
data: function() {
return {
childTwo: "元件2",
extendData: '這段文字是 元件 變更'
}
},
template: '#row-component-two',
extends: newExtend,
mounted() {
console.log('childTwo')
},
}
Vue 提供的 filters
可以讓你自定義過濾器,filters
最主要的功能是將文字資料格式化。
{{ msg | filterA }}
v-bind
表達式(v-bind expressions)<div v-bind:id="msg | filterA"></div>
範例:
<div id="app">
<table class="table">
<tbody>
<tr is="row-component"
v-for="(item, key) in data"
:item="item" :key="key">
</tr>
</tbody>
</table>
{{ data[1].cash }}
</div>
<script type="text/x-template" id="row-component">
<tr>
<td>{{ item.name }}</td>
<td>{{ item.cash }}</td>
<td>{{ item.icash }}</td>
</tr>
</script>
var child = {
props: ['item'],
template: '#row-component',
data: function() {
return {
data: {}
}
},
mounted: function() {
console.log('Component:', this)
}
}
var app = new Vue({
el: '#app',
data: {
data: [{
name: '小明',
cash: 100,
icash: 500,
}, {
name: '杰倫',
cash: 10000,
icash: 5000,
}, {
name: '漂亮阿姨',
cash: 500,
icash: 500,
}, {
name: '老媽',
cash: 10000,
icash: 100,
}, ]
},
components: {
"row-component": child
},
mounted: function() {
console.log('Vue init:', this)
}
});
這邊我們做貨幣轉換格式以及錢符號的 filter
:
<script type="text/x-template" id="row-component">
<tr>
<td>{{ item.name }}</td>
<!-- pipe(|) 的先後順序很重要,有機會影響結果 -->
<td>{{ item.cash | currency | dollarSign}}</td>
<td>{{ item.icash | currency | dollarSign}}</td>
</tr>
</script>
var child = {
props: ['item'],
template: '#row-component',
data: function() {
return {
data: {}
}
},
filters: {
dollarSign: function(n) {
return `$ ${n}`;
},
currency: function(n) {
return n.toString().replace(/^(-?\d+?)((?:\d{3})+)(?=\.\d+$|$)/, function(all, pre, groupOf3Digital) {
return pre + groupOf3Digital.replace(/\d{3}/g, ',$&');
})
}
},
mounted: function() {
console.log('Component:', this)
}
}
<div id="app">
<span>{{ text | toUpperCase }}</span>
</div>
var vm = new Vue ({
el: '#app',
data: {
text: 'hello vue'
},
filters: {
toUpperCase(value) {
return value.toUpperCase();
}
}
});
filters
將資料的第一個字變成大寫,順便練習前面使用過的 v-model
。<div id="app">
<input type="text" v-model="mytext">
<p>{{ mytext | capitalize }}</p>
</div>
Vue.filter('capitalize', function(value) {
return value.charAt(0).toUpperCase() + value.slice(1);
});
var vm = new Vue ({
el: '#app',
data: {
mytext: 'hello'
}
});
filters
可以用 pipe(|)串聯:{{ message | filterA | filterB }}
filters
是 JavaScript 函數,所以可以傳入參數:{{ message | filterA('arg1', 'arg2') }}
用範例理解 Vue.js #17:Global API(extend, nextTick, directive)
Vue 2.0學習筆記:Vue.extend構造器的延伸
Day14 - [Options] filters & computed
Vue.js: Filter 過濾器