欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Vue.js 源码分析(十一) 基础篇 过滤器 filters属性详解

程序员文章站 2022-07-09 21:10:47
用法 Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,例如: 渲染结果为: 当我们在页面里输出某些数据,需要进行格式转换的时候可以 ......

  用法


 vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 javascript 表达式的尾部,例如:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>document</title>
    <script src="vue.js"></script>
</head>
<body>
    <div id="app"><p>{{no | add(100) }}</p></div>
    <script>
        debugger
        var app = new vue({
            el:"#app",
            data:{no:123},
            filters:{
                add:function(val,i){return val+i}
            }
        })
    </script>     
</body>
</html>

渲染结果为:

Vue.js 源码分析(十一)  基础篇 过滤器 filters属性详解

当我们在页面里输出某些数据,需要进行格式转换的时候可以用这个过滤器

 

源码分析


 parse()解析模板时遇到文本时会执行parsetext()函数,如下:

function parsetext (    //第8575行 解析模板时用于解析文本
  text,
  delimiters
) {
  var tagre = delimiters ? buildregex(delimiters) : defaulttagre;       
  if (!tagre.test(text)) {                                              //匹配是否有表达式,比如:{{message}}  如果没有,则表示是纯文本节点,则直接返回不做处理
    return
  }
  var tokens = [];
  var rawtokens = [];
  var lastindex = tagre.lastindex = 0;
  var match, index, tokenvalue;
  while ((match = tagre.exec(text))) {                                  //用正则tagre去匹配text,此时match就是text里的每个值,对于:{{item}}:{{index}}来说,match等于array["{{item}}","item"] 、 array["{{index}}","index"]
    index = match.index;                                                  //该数据的起始索引
    // push text token
    if (index > lastindex) {                                              //如果index大于lastindex,表明中间还有一段文本,比如:{{item}}:{{index}},中间的:就是文本
      rawtokens.push(tokenvalue = text.slice(lastindex, index));
      tokens.push(json.stringify(tokenvalue));
    }
    // tag token
    var exp = parsefilters(match[1].trim());                               //调用parsefilters对match[1做解析]   ;例如{{no | add(100) }},解析后的格式为:_f("add")(no,100)
    tokens.push(("_s(" + exp + ")"));
    rawtokens.push({ '@binding': exp });
    lastindex = index + match[0].length;                                      //设置下一次开始匹配的位置
  }
  if (lastindex < text.length) {
    rawtokens.push(tokenvalue = text.slice(lastindex));
    tokens.push(json.stringify(tokenvalue));
  }
  return {
    expression: tokens.join('+'),                                             //拼凑成一个 表达式,例如:"_s(item)+":"+_s(index)"
    tokens: rawtokens                                                         //模板信息,例如[{@binding: "item"},":",{@binding: "index"}]
  }
}
parsefilters定义在6436行,就是解析每个字符,最后拼凑出一个_f的字符,例子中执行完后等于

Vue.js 源码分析(十一)  基础篇 过滤器 filters属性详解

最后执行render函数的时候会执行_f函数,也就是vue内部的resolvefilter函数,如下:

function resolvefilter (id) {       //第3774行 过滤器对应的函数
  return resolveasset(this.$options, 'filters', id, true) || identity   //执行resolveasset函数
}

resolveasset会获取对应资源(过滤器、组件、指令等),返回对应函数,如下:

function resolveasset (         //第1498行 options:vue实例的$options对象 type:类型,比如:components、filters id:获取的id
  options,
  type,
  id,
  warnmissing
) {
  /* istanbul ignore if */
  if (typeof id !== 'string') {
    return
  }
  var assets = options[type];
  // check local registration variations first
  if (hasown(assets, id)) { return assets[id] }                         //先从当前实例上找id
  var camelizedid = camelize(id);
  if (hasown(assets, camelizedid)) { return assets[camelizedid] }       //将id转化为驼峰式后再找
  var pascalcaseid = capitalize(camelizedid);
  if (hasown(assets, pascalcaseid)) { return assets[pascalcaseid] }     //如果还没找到则尝试将首字母大写查找
  // fallback to prototype chain
  var res = assets[id] || assets[camelizedid] || assets[pascalcaseid];  //最后通过原型来查找
  if ("development" !== 'production' && warnmissing && !res) {
    warn(
      'failed to resolve ' + type.slice(0, -1) + ': ' + id,
      options
    );
  }
  return res
}

执行完后_f("add")(no,100)里的_f("add")就会变成app实例里的add过滤器对应的函数了