vue.js学习09之vue2.x实现vue1.x中默认的过滤器

来源:互联网 发布:比较好的淘宝客采集群 编辑:程序博客网 时间:2024/06/06 07:18

        最近在学习vue.js,新版本是2.3.0了。在学习过滤器知识时,网上的一些例子是基于vue1.X官方提供的默认的过滤器,但是在vue2.x中全部取消了,都需要自己实现了。但是在vue.js的1.x版本中可以看到默认的过滤器的实现源码。我们可以把想过过滤器的源码复制出来,结合vue2.x过滤器的要求,做一些简单处理就可以使用了。在vue2.x中仍然可以在文本中使用过滤器,比如{{message | capitalize }} ,但是在v-for中就不能直接使用orderby 等过滤器了。

filter.html做测试,vue.js是2.3.0版本的

<!DOCTYPE html><html><head>    <meta charset="UTF-8">    <title></title>    <link rel="stylesheet" href="bootstrap-3.3.7/dist/css/bootstrap.min.css">    <script src="vue.js"></script>    <script src="filter.js"></script></head><body>    <div id="app">        <table class='table table-bordered'>            <thead>                <tr>                    <th>Name</th>                    <th>Age</th>                    <th>Sex</th>                    <th>Salary</th>                </tr>            </thead>            <tbody>                <tr v-for="person in peopleOderBy ">                    <td>{{ person.name | capitalize }}</td>                    <td>{{ person.age }}</td>                    <td>{{ person.sex }}</td>                    <td>{{ person.salary | currency('¥','0') }}</td>                </tr>            </tbody>        </table>    </div></body><script>    var vm = new Vue({        el: '#app',        data: {            people: [{                name: 'jack',                age: 30,                sex: 'male',                salary: '8000'            }, {                name: 'bill',                age: 26,                sex: 'male',                salary: '7000'            }, {                name: 'Tracy',                age: 22,                sex: 'female',                salary: '4500'            }, {                name: 'chris',                age: 36,                sex: 'male',                salary: '9000'            }]        },        computed: {            peopleLimitBy: function() {                return limitBy(this.people, 2, 1);            },            peopleFilterBy: function() {                return filterBy(this.people, 'r', 'in', 'name', 'sex');            },            peopleOderBy: function() {                return orderBy(this.people, 'age', 1);            }        }    })</script><style>    body {        margin: 0 auto;        margin-left: 30%;        margin-right: 30%;        margin-top: 10px;    }</style></html>


其中filter.js就是从vue.js 1.x版本中复制出来的一些过滤器的代码

/** * 字符串的第一个字母大写 */Vue.filter('capitalize', function(value) {    if (!value && value !== 0) return '';    value = value.toString();    return value.charAt(0).toUpperCase() + value.slice(1);});/** * 将字符串全部转为大写字母 */Vue.filter('uppercase', function(value) {    return value || value === 0 ? value.toString().toUpperCase() : '';});/** * 将字符串全部转为小写字母 */Vue.filter('uppercase', function(value) {    return value || value === 0 ? value.toString().toLowerCase() : '';});/** * 12345 => $12,345.00 * * @param {String} sign * @param {Number} decimals Decimal places */Vue.filter('currency', function(value, _currency, decimals) {    value = parseFloat(value);    if (!isFinite(value) || !value && value !== 0) return '';    _currency = _currency != null ? _currency : '$';    decimals = decimals != null ? decimals : 2;    var stringified = Math.abs(value).toFixed(decimals);    var _int = decimals ? stringified.slice(0, -1 - decimals) : stringified;    var i = _int.length % 3;    var head = i > 0 ? _int.slice(0, i) + (_int.length > 3 ? ',' : '') : '';    var _float = decimals ? stringified.slice(-1 - decimals) : '';    var sign = value < 0 ? '-' : '';    var digitsRE = /(\d{3})(?=\d)/g;    return sign + _currency + head + _int.slice(i).replace(digitsRE, '$1,') + _float;});/** * 'item' => 'items' * * @params *  an array of strings corresponding to *  the single, double, triple ... forms of the word to *  be pluralized. When the number to be pluralized *  exceeds the length of the args, it will use the last *  entry in the array. * *  e.g. ['single', 'double', 'triple', 'multiple'] */Vue.filter('pluralize', function(value) {    var args = toArray(arguments, 1);    return args.length > 1 ? args[value % 10 - 1] || args[args.length - 1] : args[0] + (value === 1 ? '' : 's');});/** * Limit filter for arrays * * @param {Number} n * @param {Number} offset (Decimal expected) */function limitBy(arr, n, offset) {    offset = offset ? parseInt(offset, 10) : 0;    n = toNumber(n);    return typeof n === 'number' ? arr.slice(offset, offset + n) : arr;}/** * Filter filter for arrays * * @param {String} search * @param {String} [delimiter] * @param {String} ...dataKeys */function filterBy(arr, search, delimiter) {    arr = convertArray(arr);    if (search == null) {        return arr;    }    if (typeof search === 'function') {        return arr.filter(search);    }    // cast to lowercase string    search = ('' + search).toLowerCase();    // allow optional `in` delimiter    // because why not    var n = delimiter === 'in' ? 3 : 2;    // extract and flatten keys    var keys = Array.prototype.concat.apply([], toArray(arguments, n));    var res = [];    var item, key, val, j;    for (var i = 0, l = arr.length; i < l; i++) {        item = arr[i];        val = item && item.$value || item;        j = keys.length;        if (j) {            while (j--) {                key = keys[j];                if (key === '$key' && contains(item.$key, search) || contains(getPath(val, key), search)) {                    res.push(item);                    break;                }            }        } else if (contains(item, search)) {            res.push(item);        }    }    return res;};/** * 排序 */function orderBy(arr) {    var comparator = null;    var sortKeys = undefined;    arr = convertArray(arr);    // determine order (last argument)    var args = toArray(arguments, 1);    var order = args[args.length - 1];    if (typeof order === 'number') {        order = order < 0 ? -1 : 1;        args = args.length > 1 ? args.slice(0, -1) : args;    } else {        order = 1;    }    // determine sortKeys & comparator    var firstArg = args[0];    if (!firstArg) {        return arr;    } else if (typeof firstArg === 'function') {        // custom comparator        comparator = function(a, b) {            return firstArg(a, b) * order;        };    } else {        // string keys. flatten first        sortKeys = Array.prototype.concat.apply([], args);        comparator = function(a, b, i) {            i = i || 0;            return i >= sortKeys.length - 1 ? baseCompare(a, b, i) : baseCompare(a, b, i) || comparator(a, b, i + 1);        };    }    function baseCompare(a, b, sortKeyIndex) {        var sortKey = sortKeys[sortKeyIndex];        if (sortKey) {            if (sortKey !== '$key') {                if (isObject(a) && '$value' in a) a = a.$value;                if (isObject(b) && '$value' in b) b = b.$value;            }            a = isObject(a) ? getPath(a, sortKey) : a;            b = isObject(b) ? getPath(b, sortKey) : b;        }        return a === b ? 0 : a > b ? order : -order;    }    // sort on a copy to avoid mutating original array    return arr.slice().sort(comparator);};/** * Convert an Array-like object to a real Array. */function toArray(list, start) {    start = start || 0;    var i = list.length - start;    var ret = new Array(i);    while (i--) {        ret[i] = list[i + start];    }    return ret}function convertArray(value) {    if (Array.isArray(value)) {        return value;    } else if (isPlainObject(value)) {        // convert plain object to array.        var keys = Object.keys(value);        var i = keys.length;        var res = new Array(i);        var key;        while (i--) {            key = keys[i];            res[i] = {                $key: key,                $value: value[key]            };        }        return res;    } else {        if (typeof value === 'number' && !isNaN(value)) {            value = range(value);        }        return value || [];    }}/** * String contain helper * * @param {*} val * @param {String} search */function contains(val, search) {    var i;    if (isPlainObject(val)) {        var keys = Object.keys(val);        i = keys.length;        while (i--) {            if (contains(val[keys[i]], search)) {                return true;            }        }    } else if (Array.isArray(val)) {        i = val.length;        while (i--) {            if (contains(val[i], search)) {                return true;            }        }    } else if (val != null) {        return val.toString().toLowerCase().indexOf(search) > -1;    }}/** * Quick object check - this is primarily used to tell * Objects from primitive values when we know the value * is a JSON-compliant type. */function isObject(obj) {    return obj !== null && typeof obj === 'object'}function isPlainObject(obj) {    return Object.prototype.toString.call(obj) === '[object Object]';}/** * Check and convert possible numeric strings to numbers * before setting back to data * * @param {*} value * @return {*|Number} */function toNumber(value) {    if (typeof value !== 'string') {        return value;    } else {        var parsed = Number(value);        return isNaN(parsed) ? value : parsed;    }}function getPath(obj, path) {    return parseExpression(path).get(obj);}/** * Parse an expression into re-written getter/setters. * * @param {String} exp * @param {Boolean} needSet * @return {Function} */var expressionCache = new Cache(1000);var pathTestRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/;var booleanLiteralRE = /^(?:true|false)$/;function parseExpression(exp, needSet) {    exp = exp.trim();    // try cache    var hit = expressionCache.get(exp);    if (hit) {        if (needSet && !hit.set) {            hit.set = compileSetter(hit.exp);        }        return hit;    }    var res = { exp: exp };    res.get = isSimplePath(exp) && exp.indexOf('[') < 0        // optimized super simple getter        ?        makeGetterFn('scope.' + exp)        // dynamic getter        :        compileGetter(exp);    if (needSet) {        res.set = compileSetter(exp);    }    expressionCache.put(exp, res);    return res;}function Cache(limit) {    this.size = 0;    this.limit = limit;    this.head = this.tail = undefined;    this._keymap = Object.create(null);}var p = Cache.prototype;/** * Put <value> into the cache associated with <key>. * Returns the entry which was removed to make room for * the new entry. Otherwise undefined is returned. * (i.e. if there was enough room already). * * @param {String} key * @param {*} value * @return {Entry|undefined} */p.put = function(key, value) {    var removed;    if (this.size === this.limit) {        removed = this.shift();    }    var entry = this.get(key, true);    if (!entry) {        entry = {            key: key        };        this._keymap[key] = entry;        if (this.tail) {            this.tail.newer = entry;            entry.older = this.tail;        } else {            this.head = entry;        }        this.tail = entry;        this.size++;    }    entry.value = value;    return removed;};/** * Purge the least recently used (oldest) entry from the * cache. Returns the removed entry or undefined if the * cache was empty. */p.shift = function() {    var entry = this.head;    if (entry) {        this.head = this.head.newer;        this.head.older = undefined;        entry.newer = entry.older = undefined;        this._keymap[entry.key] = undefined;        this.size--;    }    return entry;};/** * Get and register recent use of <key>. Returns the value * associated with <key> or undefined if not in cache. * * @param {String} key * @param {Boolean} returnEntry * @return {Entry|*} */p.get = function(key, returnEntry) {    var entry = this._keymap[key];    if (entry === undefined) return;    if (entry === this.tail) {        return returnEntry ? entry : entry.value;    }    // HEAD--------------TAIL    //   <.older   .newer>    //  <--- add direction --    //   A  B  C  <D>  E    if (entry.newer) {        if (entry === this.head) {            this.head = entry.newer;        }        entry.newer.older = entry.older; // C <-- E.    }    if (entry.older) {        entry.older.newer = entry.newer; // C. --> E    }    entry.newer = undefined; // D --x    entry.older = this.tail; // D. --> E    if (this.tail) {        this.tail.newer = entry; // E. <-- D    }    this.tail = entry;    return returnEntry ? entry : entry.value;};function isSimplePath(exp) {    return pathTestRE.test(exp) &&        // don't treat true/false as paths        !booleanLiteralRE.test(exp) &&        // Math constants e.g. Math.PI, Math.E etc.        exp.slice(0, 5) !== 'Math.';}function makeGetterFn(body) {    try {        /* eslint-disable no-new-func */        return new Function('scope', 'return ' + body + ';');        /* eslint-enable no-new-func */    } catch (e) {        'development' !== 'production' && warn('Invalid expression. ' + 'Generated function body: ' + body);    }}