VueStudyNote
VueStudyNote copied to clipboard
23 实现filter
实现的目标就是把filter的语句生成渲染函数,如 message | capitalize | wrap('-')
会编译成 _f("wrap")(_f("capitalize")(message),'-')
。
实现
没有看vue怎么实现的,自己实现的,估计有不少bug,但还算宝刀未老啊!
util/text-parser 中,表达式的地方都处理一下!如果有|的,表示有filter。然后拆分成数据,防止再递归。代码写起来就容易很多,也有要考虑有参数的filter。
当前应该没有绑定当前实例
/**
* 处理filter表达式
* 如:message | capitalize | wrap('===')
* @param {*} exp
*/
export function createExpressStr(exp: string): string {
// 数组反转,然后递归生成嵌套函数调用表达式
return wrapExpressStr(exp.split('|').reverse())
}
function wrapExpressStr(arr: Array<string>): string {
let str = arr[0].trim()
if (arr.length == 1) {
return str
}
// 如果是有参数的filter, 如 wrap('===')
let i = str.indexOf('(')
if (i == -1) {
return `_f("${str}")(` + wrapExpressStr(arr.slice(1)) + ')'
} else {
return `_f("${str.substr(0, i)}")(` + wrapExpressStr(arr.slice(1)) + ',' + str.substr(i + 1)
}
}
实现filter注册
我们只支持全局注册,这就很简单了!
在框架主类里面
// 全局Filter
const globalFilter: Object = Object.create(null)
class Xiao{
/**
* 拿到filter的调用方法
*
* @param {*} filtername
*/
_f(filtername: string) {
return Xiao.filter(filtername)
}
/**
* 全局注册filter
*
* @param {*} filtername
* @param {*} fn
*/
static filter(filtername: string, fn: ?Function): ?Function {
log('注册filter', filtername)
if (globalFilter[filtername]) {
return globalFilter[filtername]
}
globalFilter[filtername] = fn
return fn
}
}//Xiao
测试代码
<h1>多重filter,带参数的filter测试</h1>
<div id="demo">
<!-- 在双花括号中 -->
{{ message | capitalize | wrap('-') }}
<!-- 在 `v-bind` 中 -->
<div :title="message | capitalize | wrap('===')">看他的提示{{message | capitalize}}</div>
</div>
<script>
Xiao.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
/**
* 带参数的Filter
*/
Xiao.filter('wrap', function (value, str) {
value = value.toString()
return str + value + str;
})
var app = new Xiao({
el: '#demo',
data:{
message : 'hello'
}
})
</script>