Skip to content
This repository was archived by the owner on Apr 9, 2024. It is now read-only.

brix 的模板解析问题二次探讨 #41

@keyapril

Description

@keyapril

上次的讨论在 #39

注释的写法很好的解决了子模板的匹配和提取,却留下了遗憾和不优雅。

在上次的分析中我们已经知道,我们需要的是从一段Html文本中找出特定标签的innerHTML,这里面最大的难点就是,Html标签是支持嵌套的,怎么能够找到指定标签相对应的闭合标签呢?

思路

我们可以这样想,先匹配最前面的起始标签,假设是div吧(<div),接着一旦遇到嵌套div,就“压入堆栈”,后面如果遇到div闭合标签了,就“弹出堆栈”。如果遇到闭合标签的时候,堆栈里面已经没有东西了,那么匹配结束,此结束标签为正确的闭合标签。

之所以这样去思考,是因为正则里有“平衡组”这样的特性能够实现刚才说的“堆栈”操作(平衡组参见),可惜的是js里的正则不支持这样的特性。

回归原始

我们回到原始,不考虑嵌套,我们的正则应该这样写

<([\w]+)\s+[^>]*?bx-tmpl=["']?([^"'\s]+?)["']?\s+[^>]*?bx-datakey=["']?([^"'\s]+)["']?[^>]*?>([\s\S]*?)</\1> 

夹杂在标签中的内容无非两种情况

  • 内容A: 标签,并且此标签内无嵌套div
  • 内容B: 任意其他内容

然后就是这两种内容的不断重复而已。正则表示如下:

(<\1[^>]*>([\s\S]*?)</\1>|[\s\S])*?

这样,我们就能获取最多嵌套一级的正则了

<([\w]+)\s+[^>]*?bx-tmpl=["']?([^"'\s]+?)["']?\s+[^>]*?bx-datakey=["']?([^"'\s]+)["']?[^>]*?>((?:<\1[^>]*>(?:[\s\S]*?)</\1>|[\s\S])*?)</\1> 

以此类推二级、三级

<([\w]+)\s+[^>]*?bx-tmpl=["']?([^"'\s]+?)["']?\s+[^>]*?bx-datakey=["']?([^"'\s]+)["']?[^>]*?>((?:<\1[^>]*>(?:<\1[^>]*>(?:[\s\S]*?)</\1>|[\s\S])*?</\1>|[\s\S])*?)</\1>


<([\w]+)\s+[^>]*?bx-tmpl=["']?([^"'\s]+?)["']?\s+[^>]*?bx-datakey=["']?([^"'\s]+)["']?[^>]*?>((?:<\1[^>]*>(?:<\1[^>]*>(?:<\1[^>]*>(?:[\s\S]*?)</\1>|[\s\S])*?</\1>|[\s\S])*?</\1>|[\s\S])*?)</\1> 

程序构建

所以实际上,只要你的html结构不是特别复杂的话,也就是说嵌套不会很深的话,那么你完全可以使用这种方式来匹配嵌套html标签,幸运的是,因为模板是用户传入的,在传入之前,我们其实就知道同一个标签的嵌套次数,那通过程序动态构建正则,我们也是能够实现无限级标签嵌套的获取,代码如下:

var level = 3;
var r = '<([\\w]+)\\s+[^>]*?bx-tmpl=["\']?([^"\'\\s]+?)["\']?\\s+[^>]*?bx-datakey=["\']?([^"\'\\s]+)["\']?[^>]*?>(@brix@)</\\1>';
while(level--){
    r = r.replace('@brix@','(?:<\\1[^>]*>@brix@</\\1>|[\\s\\S])*?');
}
r = r.replace('@brix@','(?:[\\s\\S]*?)');

欢天喜地

现在,我们终于可以不用再写

<!--bx-tmpl="list" bx-datakey="list"-->
<!--bx-tmpl="list">

更好的建议

你是否有更好的建议?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions