过滤器
插入文本之外的过滤器 移除
现在过滤器只能用在插入文本中 ({{ }}
tags)。我们发现在指令 (如:v-model
,v-on
等) 中使用过滤器使事情变得更复杂。像v-for
这样的列表过滤器最好把处理逻辑作为一个计算属性放在 js 里面,这样就可以在整个模板中复用。
总之,能在原生 js 中实现的东西,我们尽量避免引入一个新的符号去重复处理同样的问题。下面是如何替换 Vue 内置过滤器:
替换 debounce 过滤器
不再这样写
<input v-on:keyup="doStuff | debounce 500">
methods: {
doStuff: function () {
// ...
}
}
请使用 lodash’s debounce
(也有可能是 throttle
) 来直接控制高耗任务。可以这样来实现上面的功能:
<input v-on:keyup="doStuff">
methods: {
doStuff: _.debounce(function () {
// ...
}, 500)
}
这种写法的更多优点详见:v-model
示例。
替换 limitBy 过滤器
不再这样写:
<p v-for="item in items | limitBy 10">{{ item }}</p>
在 computed 属性中使用 js 内置方法:.slice
method:
<p v-for="item in filteredItems">{{ item }}</p>
computed: {
filteredItems: function () {
return this.items.slice(0, 10)
}
}
替换 filterBy 过滤器
不再这样写:
<p v-for="user in users | filterBy searchQuery in 'name'">{{ user.name }}</p>
在 computed 属性中使用 js 内置方法 .filter
method:
<p v-for="user in filteredUsers">{{ user.name }}</p>
computed: {
filteredUsers: function () {
var self = this
return self.users.filter(function (user) {
return user.name.indexOf(self.searchQuery) !== -1
})
}
}
js 原生的 .filter
同样能实现很多复杂的过滤器操作,因为可以在计算 computed 属性中使用所有 js 方法。比如,想要通过匹配用户名字和电子邮箱地址 (不区分大小写) 找到用户:
var self = this
self.users.filter(function (user) {
var searchRegex = new RegExp(self.searchQuery, 'i')
return user.isActive && (
searchRegex.test(user.name) ||
searchRegex.test(user.email)
)
})
替换 orderBy 过滤器
不这样写:
<p v-for="user in users | orderBy 'name'">{{ user.name }}</p>
而是在 computed 属性中使用 lodash’s orderBy
(或者可能是 sortBy
):
<p v-for="user in orderedUsers">{{ user.name }}</p>
computed: {
orderedUsers: function () {
return _.orderBy(this.users, 'name')
}
}
甚至可以字段排序:
_.orderBy(this.users, ['name', 'last_login'], ['asc', 'desc'])
升级方式
运行迁移工具找到指令中使用的过滤器。如果有些没找到,看看控制台错误信息。
过滤器参数符号 变更
现在过滤器参数形式可以更好地与 js 函数调用方式一致,因此不用再用空格分隔参数:
<p>{{ date | formatDate 'YY-MM-DD' timeZone }}</p>
现在用圆括号括起来并用逗号分隔:
<p>{{ date | formatDate('YY-MM-DD', timeZone) }}</p>
升级方式
运行迁移工具找到老式的调用符号,如果有遗漏,请看控制台错误信息。
内置文本过滤器 移除
尽管插入文本内部的过滤器依然有效,但是所有内置过滤器已经移除了。取代的是,推荐在每个区域使用更专业的库来解决。(比如用 date-fns
来格式化日期,用 accounting
来格式化货币)。
对于每个内置过滤器,我们大概总结了下该怎么替换。代码示例可能写在自定义 helper 函数,方法或计算属性中。
替换 json 过滤器
不用一个个改,因为 Vue 已经帮你自动格式化好了,无论是字符串,数字还是数组,对象。如果想用 js 的 JSON.stringify
功能去实现,你也可以把它写在方法或者计算属性里面。
替换 capitalize 过滤器
text[0].toUpperCase() + text.slice(1)
替换 uppercase 过滤器
text.toUpperCase()
替换 lowercase 过滤器
text.toLowerCase()
替换 pluralize 过滤器
NPM 上的 pluralize 库可以很好的实现这个功能。如果仅仅想将特定的词格式化成复数形式或者想给特定的值 (‘0’) 指定特定的输出,也可以很容易地自定义复数格式化过滤器:
function pluralizeKnife (count) {
if (count === 0) {
return 'no knives'
} else if (count === 1) {
return '1 knife'
} else {
return count + 'knives'
}
}
Replacing the currency Filter
对于简单的问题,可以这样做:
'$' + price.toFixed(2)
大多数情况下,仍然会有奇怪的现象 (比如 0.035.toFixed(2)
向上取舍得到 0.04
,但是 0.045
向下取舍却也得到 0.04
)。解决这些问题可以使用 accounting
库来实现更多可靠的货币格式化。
升级方式
运行迁移工具找到舍弃的过滤器。如果有些遗漏,请参考控制台错误信息。
双向过滤器 替换
有些用户已经乐于通过 v-model
使用双向过滤器,以很少的代码创建有趣的输入。尽管表面上很简单,双向过滤器也会暗藏一些巨大的复杂性——甚至促使状态更新变得迟钝影响用户体验。推荐用包裹一个输入的组件取而代之,这样以更显性且功能更丰富的方式创建自定义的输入。
我们现在做一次双向汇率过滤器的迁移作为示范:
它基本工作良好,但是拖延的状态更新会导致奇怪的行为。比如,点击 Result
标签,试着在其中一个输入框中输入 9.999
。当输入框失去焦点的时候,其值将会更新到 $10.00
。然而当我们从整个计算器的角度看时,你会发现存储的数据是 9.999
。用户看到的已经不是真实的同步了!
为了过渡到一个更加健壮的 Vue 2.0 的方案,让我们首先在一个新的 <currency-input>
组件中包裹这个过滤器:
它允许我们添加独立过滤器无法封装的行为,比如选择输入框聚焦的内容。下一步我们从过滤器中提取业务逻辑。接下来是我们把所有的东西放到一个外部的 currencyValidator
对象中:
这会更加模块化,不只是更容易的迁移到 Vue 2,同时也允许汇率间隙和格式化:
- 从你的 Vue 代码中独立出来进行单元测试
- 在你的应用程序的别的部分中使用,比如验证验证一个 API 端的负荷 把这个验证器提取出来之后,我们也可以更舒适的把它构建到更健壮的解决方案中。那些古怪的状态也消除了,用户不再可能会输入错误,就像浏览器原生的数字输入框一样。
然而在 Vue 1.0 的过滤器中,我们仍然是受限的,所以还是完全升级到 Vue 2.0 吧:
你可能注意到了:
- 我们的输入框的各方面都更显性,使用生命周期钩子和 DOM 事件以替代双向过滤器的隐藏行为。
- 我们现在可以在自定义输入框中直接使用
v-model
,其不只是固定配合正常的输入框来使用,这也意味着我们的组件是对 Vuex 友好的。 - 因为我们已经不再要求过滤器选项必须要有一个返回值,所以实际上我们的汇率工作可以异步完成。这意味着如果我们有很多应用需要和汇率打交道,我们可以轻松的提炼这个逻辑并成为一个共享的微服务。
升级方式
运行迁移工具找到在例如 v-model
的指令中使用过滤器的例子。如果你错过了,则应该会收到命令行报错。