首页 > 技术文章 > 读vue-0.6-filters.js源码

pssp 2017-04-22 23:25 原文

'abc' => 'Abc'

function capitalize (value) {
    if (!value && value !== 0) return ''
    value = value.toString()
    return value.charAt(0).toUpperCase() + value.slice(1)
}

一开始在想作者为什么不直接if(value),后来发现如果这样写的话0就会被返回空字符串了,看到下面这么一句

'abc' => 'ABC'

uppercase: function (value) {
        return (value || value === 0)
            ? value.toString().toUpperCase()
            : ''
}

这个是用来将所有字母转换成大写的,很明显这句比上面一句更加简洁,那么作者为什么不用第二种写法来实现第一种呢?我觉得主要还是因为第一种不太适合使用三元表达式。

function capitalize(value) {
    return value || value === 0 ? (value = value.toString()).charAt(0).toUpperCase() + value.slice(1) : '';
}

虽然说以上代码确实简洁了许多,但是不太直观,尤其是代码中的value.slice(1)这一句,而这个value此时已经变成了字符串,三元表达式对于需要赋值或代码比较长的情况下就不太合适了,很快验证了我的这种猜测是对的,再看下面这段代码

12345 => $12,345.00

currency: function (value, args) {
        if (!value && value !== 0) return ''
        var sign = (args && args[0]) || '$',
            s = Math.floor(value).toString(),
            i = s.length % 3,
            h = i > 0 ? (s.slice(0, i) + (s.length > 3 ? ',' : '')) : '',
            f = '.' + value.toFixed(2).slice(-2)
        return sign + h + s.slice(i).replace(/(\d{3})(?=\d)/g, '$1,') + f
}

可以看到作者又用了第一种写法,那么作者为什么用的是第一种写法而不是第二种value || value === 0呢,原因就在于这段代码中的逻辑判断比较多,如果使用第二种那么代码就会是类似下面这样的

function currency (value, args) {
            if (value || value === 0){
                var sign = (args && args[0]) || '$',
                s = Math.floor(value).toString(),
                i = s.length % 3,
                h = i > 0 ? (s.slice(0, i) + (s.length > 3 ? ',' : '')) : '',
                f = '.' + value.toFixed(2).slice(-2)
            return sign + h + s.slice(i).replace(/(\d{3})(?=\d)/g, '$1,') + f
            }
            return "";
        }

而估计作者是希望将简单的逻辑先搞定,再写复杂的逻辑,菜鸟和大牛的差距往往也在这,什么时候该用什么,什么时候不该用什么,而不是死机硬背一些所谓的最佳实践。

来看看这段代码是做啥的吧

function currency(value, args) {
            if (!value && value !== 0) return ''
            var sign = (args && args[0]) || '$',
                s = Math.floor(value).toString(),
                i = s.length % 3,
                h = i > 0 ? (s.slice(0, i) + (s.length > 3 ? ',' : '')) : '',
                f = '.' + value.toFixed(2).slice(-2)
            return sign + h + s.slice(i).replace(/(\d{3})(?=\d)/g, '$1,') + f
        }

一开始想不明白作者为什么判断了args还要判断args[0],还以为是个数组,但实验了几次发现这样做是有原因的,如果第二个参数错误的传了一个数字,如果不加args[0],那么开始位置就是这个数字了,很显然这是错误的,而取args[0]只有是字符串或者数组的情况下才有用,这样说来如果我传的是一个数组这个代码也是有问题的,另外一点就是如果传的是多个字符串只会取第1个。

作者的整体思路是将数字拆成3部分,先将小数点过滤,第一部分就是那个显示符$,第二部分求余数%3,第三部分将不是余数的每3个值后面加,号,第4部分取通过toFixed转换后的后两位,最后把它们想加。

找复数

function pluralize(value, args) {
            return args.length > 1
            // 如果args的长度大于1,则查找value所对应的值,从1开始,如果找不到返回数组最后一个值,如果args的长度小于1并且找不到则返回数组第0个加上s。
                ? (args[value - 1] || args[args.length - 1])
                : (args[value - 1] || args[0] + 's')
}

如果只有一个参数,复数形式只是简单地在末尾添加一个 “s”。如果有多个参数,参数被当作一个字符串数组,对应一个、两个、三个…复数词。如果值的个数多于参数的个数,多出的使用最后一个参数。

按键过滤器

var keyCodes = {
            enter    : 13,
            tab      : 9,
            'delete' : 46,
            up       : 38,
            left     : 37,
            right    : 39,
            down     : 40,
            esc      : 27
        };
        function key(handler, args) {
            if (!handler) return
            var code = keyCodes[args[0]]
            if (!code) {
                code = parseInt(args[0])
            }
            return function (e) {
                if (e.keyCode === code) {
                    handler.call(this, e)
                }
            }
        }

当args在keyCodes对象中,则获取keyCodes中的code值,如果不在其中则将args值转成10进制(用户可能传递的是其他进制),赋给code,当code值与keyCode一样时,再执行相应的函数。

推荐阅读