Vue.js 自定義過濾器

過濾器,本質上就是一個函數。其做用在於用戶輸入數據後,它可以進行處理,並返回一個數據結果。
css


Vue.js 與 AngularJS 中的過濾器語法有些類似,使用管道符(|)進行鏈接,代碼示例以下:html

{{'abc' | uppercase}}    'abc' => 'ABC'


這裏使用了Vue.js 內置的過濾器 uppercase,將字符串中的字母所有轉換成大寫形式。vue


Vue.js 支持在任何出現表達式的地方添加過濾器,除了上面例子中的 雙大括號 表達式以外,還能夠在綁定指令的表達式後調用,代碼示例以下:json

<div id="app">
    <span v-text="message | uppercase"></span>
</div>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    new Vue({
        el:'#app',
        data:{
            message:'hello world!'
        }
    })
</script>


渲染爲: =>  HELLO WORLD!api


Vue 2.x 中,過濾器只能在 mustache 綁定中使用。爲了在指令綁定中實現一樣的行爲,你應該使用計算屬性。數組


過濾器能夠串聯:app

{{ message | filterA | filterB }}


這裏能夠看一個例子:ide

<div id="app">
    <h1>{{'ABCDE' |lowercase | capitalize }}</h1>
</div>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    new Vue({
        el:'#app',
        data:{
            message:''
        }
    })
</script>


lowercase 過濾器:把數據變成小寫形式函數

capitalize過濾器:把首字母變成大寫形式spa

// 'ABCDE' -> 'abcde' -> 'Abcde'


過濾器能夠接受參數,參數跟在過濾器名稱後面,參數之間以空格分隔。代碼示例以下:

{{ message | filterA('arg1', arg2) }}


過濾器函數將始終以表達式的值做爲第一個參數,帶引號的參數會被看成字符串處理,而不帶引號的參數會被看成數據屬性名來處理。


這裏的 message 將做爲第一個參數,字符串arg1 做爲第二個參數,表達式 arg2 的值在計算出來之後做爲第三個參數傳給過濾器。同時,Vue.js 的過濾器支持鏈式調用,上一個過濾器的輸出結果能夠做爲下一個過濾器的輸入


內置過濾器

必須指出的是,在Vue2.0中,刪除了全部的內置過濾器

一、字母操做

Vue.js 內置了 capitalize、uppercase、lowercase 三個過濾器用於處理英文字符。注意:這三個過濾器僅針對英文字符串使用


1-一、capitalize

capitalize 過濾器用於將表達式中的首字母轉換爲大寫形式

{{'abc' | capitalize}}  // 'abc' => 'Abc'


1-二、uppercase

uppercase 過濾器用於將表達式中的全部字母轉換爲大寫形式

{{'abc' | uppercase}}  // 'abc' => 'ABC'


1-3、lowercase

lowercase 過濾器用於將表達式中的全部字母轉換爲小寫形式

{{'ABC' | lowercase}}  // 'ABC' => 'abc'


二、限制

Vue.js 中內置了 limitBy、filterBy、orderBy 三個過濾器用於處理並返回過濾後的數組,好比與v-for搭配使用。

注意:這三個過濾器所處理的表達式的值必須是數組,不然程序會報錯


2-一、limitBy

limitBy 過濾器的做用是限制數組爲開始前的 N 個元素,其中,N 由傳入的第一個參數指定,表示限制幾個,默認爲 0, 即取所有的元素。第二個參數可選,用於指定從哪開始,好比:第一個參數是4,第二個參數是5,則表示取4個元素,從下標爲5的元素開始。代碼示例以下:

<div id="app">
    <ul>
        <!--第二個參數不指定,即取所有,從0開始-->
        <li v-for="item in items | limitBy">`item`</li>
    </ul>
</div>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    new Vue({
        el:'#app',
        data:{
            items:[1,2,3,4,5,6,7,8,9,10]
        }
    })
</script>

wKiom1g1CeHTwSRPAAAEYlPPME4231.png

<div id="app">
    <ul>
        <!--只顯示5個元素,從0開始-->
        <li v-for="item in items | limitBy 5">`item`</li>
    </ul>
</div>

wKioL1g1Ci7D7YYLAAACrj7bsKU561.png


<div id="app">
    <ul>
        <!--顯示4個,從下標爲3的元素開始  注意:下標是從0開始-->
        <li v-for="item in items | limitBy 4 3">`item`</li>
    </ul>
</div>

wKiom1g1Cx7jMoU9AAACTw_saNE033.png

還能夠這麼使用:

<div id="app">
    <ul>
        <!--取6個,從下標爲4的元素開始  注意:數組的長度是arr.length -->
        <li v-for="item in items | limitBy  items.length-4 4">`item`</li>
    </ul>
</div>

wKioL1g1D9uxlQIZAAADuGuwQv4262.png

2-二、filterBy

filterBy過濾器的使用比較靈活,其第一個參數能夠是字符串或者函數,過濾條件是:'string || function' + in + 'optionKeyName'


若是第一個參數是字符串,那麼將在每一個數組元素中搜索它,並返回包含該字符串的元素組成的數組。代碼示例以下:

<div id="app">
    <ul>
        <li v-for="val in arr | filterBy 'a'">`val`</li>
    </ul>
</div>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    new Vue({
        el:'#app',
        data:{
            arr:['pear','orange','cherry','lemon']
        }
    })
</script>

wKiom1g1EnaBWk7gAAACNcjzOkQ032.png

若是數組元素是一個對象,過濾器將遞歸地在它全部屬性中搜索。爲了縮小搜索範圍,能夠指定一個搜索字段。代碼示例以下:

<div id="app">
    <input v-model="uname">
    <ul>
        <li v-for="user in users | filterBy uname in 'uname'">`user`.`uname`</li>
    </ul>
</div>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    new Vue({
        el:'#app',
        data:{
            uname:'',
            users:[
                {uname:'Tom'},
                {uname:'Jerry'},
                {uname:'Kobe'},
                {uname:'James'}
            ]
        }
    })
</script>

wKioL1g1FQKRNt6DAAAEXizhf1w010.png wKiom1g1FQ6jblBaAAAD3aabaZI998.png

若是 filterBy 的第一個參數是函數,則過濾器將根據函數的返回結果進行過濾。此時 filterBy過濾器將調用 Javascript 數組中內置的函數 filter() 對數組進行處理,待過濾數組中的每一個元素都將做爲參數輸入並執行傳入 filterBy 中的函數。

只有函數返回結果爲 true的數組元素才符合條件並將存入一個新的數組,最終返回結果即爲這個新的數組。


2-三、orderBy

 orderBy 過濾器的做用是返回排序後的數組。過濾條件是:'string || array || function' + 'order>=0 爲升序 || order<=0 爲降序'.

第一個參數能夠是字符串、數組或者函數,第二個參數order可選,決定結果爲升序或降序排列,默認爲1,即升序排列


若輸入參數爲字符串,則可同時傳入多個字符串做爲排序鍵名,字符串之間以空格分隔。代碼示例以下:

<ul>
    <li v-for="user in users | orderBy 'lastName' 'firstName' 'age'">
        `user`.`lastName` `user`.`firstName` `user`.`age`
    </li>
</ul>


此時,將按照傳入的排序鍵名的前後順序進行排序。也能夠將排序鍵名按照順序放入一個數組中,而後傳入一個數組參數給 orderBy 過濾器便可。代碼示例以下:

<!--sortKey = ['lastName' 'firstName' 'age'];-->
<ul>
    <li v-for="user in users | orderBy sortKey">
        `user`.`lastName` `user`.`firstName` `user`.`age`
    </li>
</ul>


升序排列:

<div id="app">
    <input type="text" v-model="a">
    <ul>
        <li v-for="val in arr | orderBy 1">
            `val`
        </li>
    </ul>
</div>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    new Vue({
        el:'#app',
        data:{
            a:'',
            arr:['pear','cherry','lemon','orange']
        }
    })
</script>

wKiom1g1GbmhGfZzAAAEDcpGg4I796.png


降序排列:

<div id="app">
    <input type="text" v-model="a">
    <ul>
        <li v-for="val in arr | orderBy -1">
            `val`
        </li>
    </ul>
</div>

wKioL1g1Gd7RC6EuAAAED57FhvM642.png


三、json 過濾器

Vue.js 中的 json 過濾器本質上是 JSON.stringify() 的精簡縮略版,可將表達式的值轉換爲 JSON 字符串,即輸出表達式通過 JSON.stringify() 處理後的結果。

json 可接受一個類型爲 Number 的參數,用於決定轉換後的 JSON 字符串的縮進距離,若是不輸入該參數,則默認爲2。


不輸入參數,默認爲2的示例:

<div id="app">
    <p>{{information | json}}</p>
</div>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    new Vue({
        el:'#app',
        data:{
            information:{'name':'Roger', 'age':26}
        }
    })
</script>

wKiom1g1B1zySNhCAABQH_hsVKo325.png


爲了看到效果,咱們輸入一個參數20:

<div id="app">
    <p>{{information | json 20}}</p> <!-- 以20個空格的縮進打印一個對象 -->
</div>

wKioL1g1B4-QGcUrAABQPI5L4po940.png


四、currency 過濾器

currency 過濾器的做用是將數字值轉換爲貨幣形式輸出。

第一個參數接受類型爲 String 的貨幣符號,若是不輸入,則默認爲美圓符號$。

第二個參數接受類型爲 Number的小數位,若是不輸入,則默認爲2.

注意:若是第一個參數採起默認形式,而須要第二個參數修改小數位,則第一個參數不可省略


不輸入參數,默認形式

<div id="app">
    <h1>{{amount | currency}}</h1>
</div>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    new Vue({
        el:'#app',
        data:{
            amount: '12345'
        }
    })
</script>

wKiom1g1IzSA-QRcAAANRFF7ZKc117.png

使用其它貨幣符號:

<div id="app">
    <h1>{{amount | currency '¥'}}</h1>
</div>

wKiom1g1I2LSPKalAAAMoHPg3c0547.png

將小數調整爲3位:

<div id="app">
    <h1>{{amount | currency '¥' 3}}</h1>
</div>

wKioL1g1I-DD5ifoAAANlVk-zsg324.png


五、debounce 過濾器

debounce 過濾器的做用是延遲處理必定的時間執行。其接受的表達式的值必須是函數,所以,通常與 v-on 等指令結合使用。


debounce 接受一個可選的參數做爲延遲時間,單位爲毫秒。若是沒有該參數,則默認的延遲時間爲300ms,通過 debounce 包裝的處理器在調用以後將至少延遲設定的時間再執行。 若是在延遲結束前再次調用,則延遲時長將重置爲設定的時間。


一般,在監聽用戶 input 事件時使用 debounce 過濾器比較有用,能夠防止頻繁調用方法。debounce 的用法參考以下:

<input @keyup="onKeyup | debounce 500">



自定義過濾器

一、filter語法

在Vue.js 中也存在一個全局函數 Vue.filter 用於構造過濾器:

Vue.filter(filterName, function(input){...})


該函數接受兩個參數,第一個參數爲自定義的過濾器名稱,第二個參數則是具體的過濾器函數,過濾器函數以值爲參數,返回轉換後的值


二、單個參數

註冊一個名爲 reverse 的過濾器,做用是將字符串反轉輸出。代碼示例以下:

<div id="app">
    <input v-model="message">
    <span v-text="message | reverse">`message`</span>
</div>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    Vue.filter('reverse',function(message){
        return message.split('').reverse().join('');
    });
    new Vue({
        el:'#app',
        data:{
            message:''
        }
    })
</script>

wKiom1g1KK6RC32iAAAFTEKiIJU338.png

註冊一個名爲 double 的過濾器,做用是將數字補全成兩位數輸出。代碼示例以下

<div id="app">
    <input v-model="value">
    <p v-text="value | double">`value`</p>
</div>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    Vue.filter('double',function(value){
        return value<10? '0'+value : value
    });
    new Vue({
        el:'#app',
        data:{
            value:''
        }
    })
</script>

wKioL1g1KpmBD2S8AAAC-Q8KLs8796.png


註冊一個名爲 date 的過濾器,做用是將當前時間毫秒數以年月日時分秒的格式輸出。代碼示例以下:

<div id="app">
    <p v-text="message | date">`message`</p>
</div>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    Vue.filter('date',function(message){
        var now = new Date(message);
        return now.getFullYear()+'-'
                +(now.getMonth()+1)+'-'
                +now.getDate()+' '
                +(now.getHours()<12?'0'+now.getHours():now.getHours())+':'
                +(now.getMinutes()<10?'0'+now.getMinutes():now.getMinutes())+':'
                +now.getSeconds();
    });
    new Vue({
        el:'#app',
        data:{
            message:Date.now()
        }
    })
</script>

wKioL1g1MXCjB1EpAAADjHeoDG4303.png


三、多個參數

過濾器函數除了以值做爲參數外,也能夠接受任意數量的參數,參數之間以空格分隔。代碼示例以下:

<div id="app">
    <input v-model="message">
    <p v-text="message | wrap 'before' 'end'">`message`</p>
</div>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    Vue.filter('wrap',function(value, begin, end){
        return begin +' '+ value + ' '+ end
    });
    new Vue({
        el:'#app',
        data:{
            message:''
        }
    })
</script>

wKiom1g1LVmxEn2rAAAEl7hSot0349.png


四、雙向過濾器

上面的過濾器都是在 Model 數據輸出到 View 層以前進行數據轉化的,實際上 Vue.js 還支持把來自視圖(input元素)的值在寫回模型前進行轉化,即雙向過濾器

Vue.filter('filterName',{
    //model ---> view
    //read 函數可選
    read:function(val){
        ...
    },
    
    //view ---> model
    //write 函數將在數據被寫入Model 以前調用
    //兩個參數分別爲表達式的新值和舊值
    write:function(newVal, oldVal){
        ...
    }
})


代碼示例以下:

<div id="app">
    <p>`message`</p>
    <input type="text" v-model="message | twoWayFilter">
</div>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    Vue.filter('twoWayFilter',{
        read:function(val){
            return 'read'+' '+val;
        },
        write:function(newVal, oldVal){
            return oldVal+' '+ 'write';
        }
    });
    new Vue({
        el:'#app',
        data:{
            message:'hello world'
        }
    })
</script>


在初始狀況下,message 表達式的值通過 twoWayFilter 中的 read 函數處理,輸出到 view 層

wKiom1g1NcHhsE1aAAAF2itqCSw188.png

當咱們在 input 框中修改 message 的值時,twoWayFilter 中的 write 函數將在數據輸出到 Model 層以前處理,這裏將返回 message 的舊值 + 'write',而後輸出到 Model層,所以 message的值變動爲'hello world write' 並顯示到頁面上

wKioL1g1Nn-ib8HMAAAIt3AURKk053.png


常見問題解析

一、filterBy/orderBy 過濾後 $index 的索引

在使用 filterBy 或者 orderBy 對錶達式進行過濾時,若是同時須要將 $index 做爲參數,此時的 $index將會根據表達式數組或對象過濾後的值進行索引

<ul id="app">
    <li v-for="item in items | orderBy 'age'">
        `item`.`name` - {{$index}}
    </li>
</ul>

<script src="//cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    new Vue({
        el:'#app',
        data:{
            items:[
                {name:'Roger', age:26},
                {name:'Sarahling', age:27},
                {name:'Daisy', age:1}
            ]
        }
    })
</script>

wKioL1g1ODOgcM4EAAAD1_wRwoA893.png


二、自定義filter 的書寫位置

自定義 filter 能夠寫在全局 Vue下,例如:

Vue.filter('reverse',function(message){
        return message.split('').reverse().join('');
    });


也能夠寫在Vue 實例當中,例如:

var vm = new Vue({
    el:'#example',
    data:{
        
    },
    filters:{
        //自定義 filter 事件的位置
        reverse:function(value){
            return value.split('').reverse().join('');
        }
    }
})


兩者本質上並沒有區別,可任選一種使用。可是,採用Vue.filter 在全局定義時,須要在實例化 Vue 以前定義,不然自定義的 filter 不起做用

相關文章
相關標籤/搜索