text-parser | 每天读一点Vue源码
2020/3/30 11:02:43
本文主要是介绍text-parser | 每天读一点Vue源码,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
面试的时候经常被问一些Vue源码相关的问题,通常情况下, 我会在面试前恶补掘金上的面筋来对付面试,什么双向绑定的原理呀,什么虚拟dom树呀,实际上我压根儿就没仔细研究过,其一是自己真的比较菜,其二工作上也用不上,别自己给自己添堵。但后面想一下,很多事情,为之则易,不为则难,给自己设立困难(负重)才能进步,决定每天多一点Vue的源码,在Vue的源码选择上,我选择了最老的版本(0.1)😬(真的怕自己看起来吃力), 阅读的模式为通读,从易到难一个文件一个文件的看,看完一个文件后再看它的单元测试,等完全吃透后复制粘贴代码到本地运行测试用例为代码块写一些中文注释,打上tag推到自己的仓库,开始梳理写文章总结(之前有犹豫过是否应该在掘金上写文章,因为这类Vue源码解析的文章已经很多了,而且还写的很好,我再写一遍是否还存在意义,后面想还是写吧,流水总结也不错💧)。
正文
这是我发的第三篇关于Vue源码的文章, 本文介绍text-parser(文本解析), text-parser在Vue里用于html标签中属性的解析和标签里innerText的解析,比如:
<span class="primary {{test}}">message: {{hello}} {{world | toCapital}}</span> 复制代码
text-parser解析文本函数 TextParser.parse("message: {{hello}} {{world | toCapital}}")
,解析属性函数TextParser.parseAttr("primary {{test}}")
细节过程
text-parser实现思路大致分这几步:
- 通过正则表达式匹配Mustache(双大括号)
// mustache正则, 匹配 {{xxx}} 或 {{{xxxxx}}} function buildInterpolationRegex() { var open = escapeRegex(openChar), end = escapeRegex(endChar) // 正则为: /{{{?(.+?)}?}}/ return new RegExp(open + open + open + '?(.+?)' + end + '?' + end + end) } 复制代码
- 通过parser函数,利用上面大正则循环匹配,分割文本,返回数组。比如 输入:
"abc xb {{a | filterFn}} xbc {{{b}}}"
=> 输出:['abc xb ', {key: 'a | filterFn'}, ' xbc ', {key: 'b', html: true}]
function parse(text) { if (!exports.Regex.test(text)) return null var m, i, token, match, tokens = [] while (m = text.match(exports.Regex)) { i = m.index // 当前匹配到的位置 if (i > 0) tokens.push(text.slice(0, i)) // 这是第一类 plain string token = { key: m[1].trim() } // 第二类 捕获组里面的, 即$1 match = m[0] // 这个匹配的字符, 即$& token.html = match.charAt(2) === openChar && match.charAt(match.length - 3) === endChar// 第三类 匹配 {{{x}}} tokens.push(token) text = text.slice(i + match.length) // 匹配下一段文本,类似于移动光标 } if (text.length) tokens.push(text) // 文本结尾 return tokens } 复制代码
- 再通过inlineFilters把上面返回的数组中的
{key: 'a | filterFn'}
进一步解析成this.$compiler.getOption("filters", "filterFn").call(this,a)
, inlineFilters里面调用Directive.parse, Directive.parse里面调用了Directive.inlineFilters,在Directive.inlineFilters里面拼接好this.$compiler.getOption("filters", "filterFn").call(this,a)
, Directive.parse的代码太长了,就不贴到文章了,可以点击链接查看,下面贴Directive.inlineFilters的实现:
Directive.inlineFilters = function (key, filters) { var args, filter for (var i = 0, l = filters.length; i < l; i++) { filter = filters[i] args = filter.args ? ',"' + filter.args.map(escapeQuote).join('","') + '"' : '' key = 'this.$compiler.getOption("filters", "' + filter.name + '").call(this,' + key + args + ')' } return key } 复制代码
整体过程
以 {{a | filterFn}}为例,说下上面调用整体过程:
// 伪代码 TextParser.parseAttr = function(str){ TextParser.parse(str) .map( (item) => Directive.parse(item) .map( (item) => Directive.inlineFilters(item.key, item.filters) ) ) } 复制代码
-
通过TextParser.parse
输入:{{a | filterFn}}
输出: [{key: 'a | filterFn'}]
-
调用Directive.parse
输入:a | filterFn
,输出: [{key: a, filters: [{name: 'filterFn', args:[]}]}]
-
调用Directive.inlineFilters
输入: a, [{name: 'filterFn', args:[]}]}]
,输出: this.$compiler.getOption("filters", "filterFn").call(this,a)
最后
持续更新...❤️
这篇关于text-parser | 每天读一点Vue源码的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-04package.json 文件位置在哪?-icode9专业技术文章分享
- 2024-10-01Craco.js学习:从入门到实践指南
- 2024-10-01Create-React-App学习:入门与实践指南
- 2024-10-01CSS-in-JS学习:从入门到实践指南
- 2024-09-30JSX语法学习:从入门到初步掌握
- 2024-09-30Mock.js学习:入门教程与实战演练
- 2024-09-30React Hooks学习:从入门到实践
- 2024-09-30受控组件学习:React中的基础入门教程
- 2024-09-29JS定时器教程:初学者必看指南
- 2024-09-29JS对象教程:初学者的全面指南