过滤器是什么?
过滤器是一种在模板中处理数据的便捷方式, 会经常在其他模板语言中见到, 他们特别适合对字符串和数字进行简单的显示变化.
1. 通过案例理解过滤器
示例: 对于数字价格处理
1.1 结构层中处理价格数字
<div id="app">
<!-- 正常处理 -->
<p>手机:{{ (priceOne/100).toFixed(2) }} 元</p>
<p>电脑:{{ (priceTwo/100).toFixed(2) }} 元</p>
<p>相机:{{ (priceThree/100).toFixed(2) }} 元</p>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
priceOne: 9999,
priceTwo: 19999,
priceThree: 29999,
}
})
</script>
同样的逻辑我们要处理三次,这种处理方案,页面需要使用到多少次价格,我们就需要处理多少次相同的逻辑。 计算属性和侦听器显然不合适,因为都需要检测依赖数据的变化, 有多少数据就需要多少的计算属性,和多少的侦听器, 反而不美, 想来想去,定义一个方法通过接受不同的参数来处理我们的相同的逻辑,每次只要调用这个方法就可以了,挺不错的, 尝试一下
1.2 方法处理相同逻辑
<div id="app">
<!-- 使用方法处理价格 -->
<p>手机:{{ priceHandle(priceOne) }} 元</p>
<p>电脑:{{ priceHandle(priceTwo) }} 元</p>
<p>相机:{{ (priceHandle(priceThree) }} 元</p>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
priceOne: 9999,
priceTwo: 19999,
priceThree: 29999,
},
methods:{
priceHandle(price){
// 可以写相应的逻辑代码
......
return price
}
}
})
</script>
方法也有不美之处,就是寓意化不够明确,所有的事情都需要定义方法来处理, 那么方法的耦合性就会很高
所以对于数据的先期处理, vue给我们提供了过滤器 filters
注意过滤器的方法定义在filters属性中,使用filters的好处很多, 代码重复更少, 可读性更强, 同时呢,维护性也更好, 如果要更改逻辑,只需要修改一次,而不是每个使用的地方都修改
<div id="app">
<!-- 过滤器 filter -->
<p>手机:{{ priceOne | formatPrice}} 元</p>
<p>电脑:{{ priceTwo | formatPrice }} 元</p>
<p>相机:{{ priceThree | formatPrice }} 元</p>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
priceOne: 9999,
priceTwo: 19999,
priceThree: 29999,
},
filters:{
formatPrice(price){
// 可以写相应的逻辑代码
......
return price
}
}
})
</script>
其实这个时候,我们甚至连后面的元 都可以处理到过滤器中,直接把元去掉后在filters的return的参数后面拼接上就可以了。
2. 过滤器传参
通过案例,我们也了解了, 过滤器在使用时会将|前面的内容作为过滤器函数的第一个参数,如果过滤器只需要这一个参数时, 过滤器本身不需要加括号
如果过滤器需要其他参数来动态改变逻辑怎么办,
这个时候过滤器在使用的时候就可以加括号执行,并传入相应的参数,输入的参数会作为第二个参数传递给过滤器
例如:
<div id="app">
<!-- 过滤器传参 -->
<p>手机:{{ priceOne | formatPrice("¥")}} </p>
<p>电脑:{{ priceTwo | formatPrice("$") }} </p>
<p>相机:{{ priceThree | formatPrice("$") }} </p>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
priceOne: 9999,
priceTwo: 19999,
priceThree: 29999,
},
filters:{
formatPrice(price,symbol){
return symbol+price
}
}
})
</script>
这样我们就可以通过传参的方式来动态的改变过滤逻辑
过滤器还可以通过链式调用的方式在一个表达式中使用多个过滤器.
比如我们给刚才的案例添加一个四舍五入到整数的过滤器
<div id="app">
<!-- 链式调用过滤器 -->
<p>
手机:{{ priceOne | roundPrice | formatPrice("¥")}}
</p>
<p>
电脑:{{ priceTwo | roundPrice | formatPrice("$") }}
</p>
<p>
相机:{{ priceThree | roundPrice | formatPrice("$") }}
</p>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
priceOne: 9999,
priceTwo: 19999,
priceThree: 29999,
},
filters:{
roundPrice(price){
return Math.round(price);
},
formatPrice(price,symbol){
return symbol+price
}
}
})
</script>
这里首先会调用roundPrice 过来器, 会将价格传入到这个过滤器中处理, 然后在将处理后的结果传给第二个过滤器处理,最后输出到页面上
4. 属性使用过滤器
除了在插值,还可以在v-bind中使用过滤器,因为使用了v-bind动态绑定的属性,属性值已经不再是一个字符串,而是一个表达式了
<div id="app">
<!-- 动态绑定的属性使用过滤器 -->
<input type="text" :value="priceOne | roundPrice | formatPrice('¥')">
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
priceOne: 9999,
priceTwo: 19999,
priceThree: 29999,
},
filters:{
roundPrice(price){
return Math.round(price);
},
formatPrice(price,symbol){
return symbol+price
}
}
})
</script>
也就是说现在的过滤器是一个组件级的过滤器
如果我重新new 一个Vue实例, 这个过滤器将不能再另一个实例上使用
例如
<div id="app">
<p>手机:{{ priceOne | roundPrice | formatPrice("¥")}} </p>
<p>电脑:{{ priceTwo | roundPrice | formatPrice("$") }} </p>
<p>相机:{{ priceThree | roundPrice | formatPrice("$") }} </p>
</div>
<div id="example">
<!-- 在第二个vue实例上不能使用第一个实例的过滤器, -->
{{ price | roundPrice }}
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
priceOne: 9999,
priceTwo: 19999,
priceThree: 29999,
},
filters:{
roundPrice(price){
return Math.round(price);
},
formatPrice(price,symbol){
return symbol+price
}
}
})
const vm2 = new Vue({
el:"#example",
data:{
price:8888
}
})
</script>
如果我们在第二个vue实例上使用过滤器就会报错,
所以我们可以注册全局过滤器,所有的组件都能使用
<div id="app">
<p>
手机:{{ priceOne | roundPrice | formatPrice("¥")}}
</p>
<p>
电脑:{{ priceTwo | roundPrice | formatPrice("$") }}
</p>
<p>
相机:{{ priceThree | roundPrice | formatPrice("$") }}
</p>
</div>
<div id="example">
{{ price | formatPrice("$") }}
</div>
<script>
// 注册全局过滤器
Vue.filter("formatPrice",function(price,symbol){
return symbol+price
})
const vm = new Vue({
el: "#app",
data: {
priceOne: 9999,
priceTwo: 19999,
priceThree: 29999,
},
filters:{
roundPrice(price){
return Math.round(price);
}
}
})
const vm2 = new Vue({
el:"#example",
data:{
price:8888
}
})
</script>
注册的全局过滤器,就可以在vue任何地方都可以使用
这种方式适合整个应用都会用到的过滤器,
6. 过滤器注意事项
6.1 过滤器中的this
过滤器是唯一不能使用this来访问数据或者其他方法的地方,这一点是故意设计成这样的, 因为过滤器应该是一个纯函数, 也就是对于同样的输入每次都返回同样的输出,而不涉及任何外部数据, 如果想访问外部数据可以通过参数传递.
6.2 过滤器使用的地方
另一件注意事项就是过滤器只能在插值和v-bind指令中使用过滤器,但是在Vue1 中,可以在任何可以使用表达式的地方使用过滤器