mustache之dart

前言

Mustache 是一个 logic-less (轻逻辑)模板解析引擎,可以应用在 js、PHP、Python、Perl 等多种编程语言中。这里主要是看dart中的应用。

模板语法很简单 看这里

1
2
3
4
5
6
7
{{keyName}} 
{{#keyName}} {{/keyName}}
{{^keyName}} {{/keyName}}
{{.}}
{{>partials}}
{{{keyName}}}
{{!comments}}

使用

在flutter项目中,使用annation router注解的方式生成路由表管理类 RouterManager ,以及业务相关的类文件(ios android)
在使用mustache之前,是通过stringbuff 的方式拼接字符串,也可以完成,但是阅读性比较差。

之前

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

/// 生成路由表类
StringBuffer sb = new StringBuffer();
sb..write(_createImport())..write(_createClazz(element.name));
return sb.toString();

/// 生成路由表类的 import 信息
String _createImport() {
StringBuffer sb = new StringBuffer();
sb
..writeln("import 'package:flutter/material.dart';")
..writeln("import 'package:hybrid_router/hybrid_router.dart';");
/// import page
collector.importClazzList.forEach((clazz) {
sb.writeln("import '$clazz';");
});
return sb.toString();
}
/// 生成路由表类的 clazz 信息
String _createClazz(String className) {
StringBuffer sb = new StringBuffer();
/// start class
sb.writeln("class \$$className {");
/// generateRoute function
sb
..writeln(" Map<String, HybridWidgetBuilder> generateRoutes(){")
..writeln(" return {");
collector.routeMap.forEach((key, value) {
String flutterPath = value.flutterPath;
sb
..writeln(" '$flutterPath': (BuildContext context, Object args) {")
..writeln(" ${_createInstance(value)}")
..writeln(" },");
});
sb..writeln(" };")..writeln(" }");
/// generateSpm function
sb
..writeln(" Map<String, String> generateSpm() {")
..writeln(" return {");
collector.routeMap.forEach((key, value) {
String flutterSpm = value.flutterSpm;
String flutterPath = value.flutterPath;
if (flutterSpm?.isNotEmpty == true) {
sb.writeln(" '$flutterPath': '$flutterSpm',");
}
});
sb..writeln(" };")..writeln(" }");
/// end class
sb.writeln("}");
return sb.toString();
}

之后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/// 生成路由表类
_createRouteManager(element.name);

String _createRouteManager(String className) {

return VDTemplate.routerManagerTemplate().renderString({
'classname':className,
'classes':collector.importClazzList,
'routes':collector.routeMap.values,
'createInstance':(LambdaContext ctx) {
CollectorItem item = ctx.lookup('.');
return _createInstance(item);
}
});
}

static Template routerManagerTemplate() {
var source = '''
{{> import}}
{{> clazz}}
''';

Map<String,Template> map = {
"import":VDTemplate.importTemplate(),
"clazz":VDTemplate.claszzTemplate()
};

return new Template(source,partialResolver: (String name) => map[name]);
}

static Template importTemplate() {
var source = '''
import 'package:flutter/material.dart';
import 'package:hybrid_router/hybrid_router.dart';
{{# classes }}
import '{{{.}}}';
{{/ classes }}

''';

return new Template(source);

}

static Template claszzTemplate() {
var source = '''
class \${{classname}} {
Map<String, HybridWidgetBuilder> generateRoutes(){
return {
{{#routes}}
'{{flutterPath}}': (BuildContext context, Object args) {
{{createInstance}}
},
{{/routes}}
};
}

Map<String, String> generateSpm() {
return {
{{#routes}}
{{# flutterSpm}}
'{{flutterPath}}': '{{flutterSpm}}',
{{/ flutterSpm}}
{{/routes}}
};
}
}
''';

return new Template(source);
}

对比看下,使用mustache之后,可读性好很多,基本保持了代码结构

总结

  • 字符串数组,可以使用{{.}}
  • 对象数据,可以跟普通的hash一样,直接用{{对象的属性}},mustache内部通过dart反射拿到属性值
  • 使用partials 拆分template 增加可读性
  • 通过lambda函数执行dart方法,也可以做到拆分的作用
  • lambdaContext.loopup(".") 可以获取对象实例,进而可以参数传递
  • mustache内部renderstring也是通过stringbuff的方式实现

参考链接

mustache 1.1.1
Flutter路由管理