You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
lettext,rest,nextif(textEnd>=0){rest=html.slice(textEnd)while(!endTag.test(rest)&&!startTagOpen.test(rest)&&!comment.test(rest)&&!conditionalComment.test(rest)){// < in plain text, be forgiving and treat it as textnext=rest.indexOf('<',1)if(next<0)breaktextEnd+=nextrest=html.slice(textEnd)}text=html.substring(0,textEnd)advance(textEnd)}if(textEnd<0){text=htmlhtml=''}if(options.chars&&text){options.chars(text)}
chars(text: string){// 如果没有父节点if(!currentParent){if(process.env.NODE_ENV!=='production'){// 只有template时报错if(text===template){warnOnce('Component template requires a root element, rather than just text.')}elseif((text=text.trim())){warnOnce(`text "${text}" outside root element will be ignored.`)}}return}// IE textarea placeholder bug/* istanbul ignore if */if(isIE&¤tParent.tag==='textarea'&¤tParent.attrsMap.placeholder===text){return}constchildren=currentParent.childrentext=inPre||text.trim()
? isTextTag(currentParent) ? text : decodeHTMLCached(text)// only preserve whitespace if its not right after a starting tag
: preserveWhitespace&&children.length ? ' ' : ''if(text){letresif(!inVPre&&text!==' '&&(res=parseText(text,delimiters))){children.push({type: 2,// 包含表达式的文本expression: res.expression,tokens: res.tokens,
text
})}elseif(text!==' '||!children.length||children[children.length-1].text!==' '){children.push({type: 3,// 纯文本
text
})}}}
最近工作中遇到一个问题,就是 filter 中的函数无法使用绑定在
Vue.prototype
的函数。都知道,在created
、mounted
、methods
中,this
绑定的都是当前Vue
实例。偏偏filter
函数this
指向的是Window
?直接上 🌰
上面的代码我们注册了一个全局

filter
和一个局部filter
,打印出来的结果如下:可以看到,都是全局
window
对象。下面就进入filter
的源码分析一下为什么没有绑定当前Vue
实例。我们从模板编译开始看。编译入口这里省略,想要了解的童鞋可以点击链接查看。直接来到src\compiler\parser\html-parser.js
的parseHTML
函数,这里会遍历整个模板,filter
属于文本部分:判断
textEnd
是否大于 0,是的话说明当前位置到textEnd
都是文本内容。并且如果<
是纯文本中的字符,就继续找到真正的文本结束的位置,然后前进到结束的位置。接着判断textEnd
是否小于零,是的话则说明整个template
解析完毕了,把剩余的html
都赋值给了text
。到这里我们就拿到了 🌰 中的文本内容{{ myArr | filtersOdd | filtersOverFour }}
。接下来执行chars
回调,这个函数在src\compiler\parser\index.js
:上面代码先对一些特殊情况做判断,比如文本是否直接写在
template
中,是不是placeholder
的文本、是不是script
或者style
里面的文本等等。执行完判断如果不是空字符串且包含表达式,执行parseText
函数,定义在src\compiler\parser\text-parser.js
:defaultTagRE
匹配两个大括号中间的内容。然后再循环匹配文本,遇到普通文本就 push 到rawTokens
和tokens
中,如果是表达式就转换成_s(${exp})
push 到tokens
中,以及转换成{@binding:exp}
push 到rawTokens
中。对于我们这个:chestnut:,我们最后得到的表达式:_f
是什么呢?我们一起来分析下。上述代码中,parseFilters
函数就是我们这节的关键,它定义在src\compiler\parser\filter-parser.js
文件中:按照:chestnut:,
parseFilters
的作用就是把整个文本表达式转化成_f("filtersOverFour")(_f("filtersOdd")(myArr))
。_f 定义在src\core\instance\render-helpers\index.js
:resolveFilter
定义在src\core\instance\render-helpers\resolve-filter.js
:截图是
this.$options
对象,可以看到:全局filter
是挂在实例filters
属性原型中的。生成执行代码阶段就不详细分析了,最后生成的
render
函数代码:最后在调用
vm._render
函数时会执行_f
函数。至此,filter
的流程就走完了。下面通过一个简单的:chestnut:来还原一下上面的场景:这就回答了
filter
函数this
为什么指向的是Window
了!欢迎纠正错误!更多内容请乘坐 🚀 前往!!!
The text was updated successfully, but these errors were encountered: