xwjie / VueStudyNote

vue学习笔记

Home Page:https://xwjie.github.io/VueStudyNote/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

23 实现filter

xwjie opened this issue · comments

实现的目标就是把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>