在Rust中尝试描述html/css
在通常情况下要在Rust中生成html除了手动拼字符串外最常用的方式是使用模板引擎,但这会带来2个主要问题
1.需要学习模板语法,且不同模板引擎之间语法可能差异很大
2.在模板中难以利用Rust类型系统,以及在IDE中支持可能不佳
那有没有可能在Rust实现html那样可以比较方便地展示文档树形结构,同时又能充分利用Rust的类型系统呢,rtml正是这个想法的一次尝试.
使用先看一个简单例子
usertml::tags::*;fnmain(){letpage=html(h1("helloworld!"));println!("{}",page);}
生成html
htmlh1helloworld!/h1/html
可以看到在rtml中,html,h1和html的html,h1标签对应,往html传入的参数是html/html的children,html(h1(...))就如同往html标签中间放入h1标签一样.
注意,在rtml中,h1,div,和title等都是普通的函数(以下简称标签函数),没有使用任何过程宏,对于有LSP支持的IDE来说,悬浮显示,智能补全,跳转定义等都没有问题.而且rtml对于标准html标签都提供了详细的文档,方便使用.
灵活的children传入对于rtml中任意一个标签函数,其参数虽然只有一个,但可传入其中,作为children的类型非常多.
常见的字面类型//布尔值span(true)//浮点数span(1.1f64)//字符串span("hello")//format!也OKletname="Rookie";span(format!("hello{name}"))//整数span(usize)更多类型
//任意一个实现Tagtrait的结构体div(h1("hello"))//元组也OK//div传入的参数是一个(H1,Hr,P)元组div((h1("hello"),hr(()),p("thisissomedesc")))//Vec也行//ul传入的是一个ul([1,2,3].iter().map(
i
li(format!("item{i}"))).collect::Vec_())//constgenericarray也可以,如传入[Span;2]div([span(1),span(2)])设置属性,样式和绑定事件处理函数
在html标签上,用户可以设置id,class样式等.为了兼容html风格,样式设置格式,rtml提供了style!,和prop!两个宏以方便属性设置.而且rtml传入属性的方式也非常灵活.
如果查看rtml文档里某个标签函数参数结构体xxArgs的文档,你会发现它实现很多Fromxxx方法.
正是这些实现让rtml的构造函数很灵活.
对于meta等标签,通常我们不关系他的children,而是要传入charset等属性,这时候你可以这样传参.
meta(prop!{charset="utf-8"})
对于某些标签来说,属性,样式和children都需要设置,除了要求children必须在最后一个位置外,属性和样式可以乱序
//注意,传入的一个三元素元组div((style!{color:"red"},prop!{id="app"},p("hello")))
下面是一个更复杂的例子
usertml::prop;usertml::style;usertml::tags::*;fnmain(){letpage=html((prop!{lang="zh-cn"},(header((meta(prop!{charset="utf-8"}),title("htmlfilegeneratedbyRust!"),)),body((style!{color:"olive";text-align:"center"},(h1("WOW"),hr(()),h2("循环"),pre((style!{},code(r#"[1,2,3].iter().map(
i
p(format!("paragraph{}",i))).collect::Vec_()"#,),)),div([1,2,3].iter().map(
i
p(format!("paragraph{}",i))).collect::Vec_()),hr(()),h2("任意字面量"),div((style!{color:"black"},(span(true),span(false),span(1u8),span(1.30f32)),)),hr(()),footer(b("powerbyRust!")),),)),),));println!("{}",page);}
生成的html
htmllang=zh-cnheadermetacharset=utf-8/metatitlehtmlfilegeneratedbyRust!/title/headerbodystyle="color:olive;text-align:center;"h1WOW/h1hr/hrh2循环/h2precode[1,2,3].iter().map(
i
p(format!("paragraph{}",i))).collect::Vec_()/code/predivpparagraph1/ppparagraph2/ppparagraph3/p/divhr/hrh2任意字面量/h2divstyle="color:black;"spantrue/spanspanfalse/spanspan1/spanspan1.3/span/divhr/hrfooterbpowerbyRust!/b/footer/body/html
浏览器打开效果如下.
TODO事件函数绑定预览时标签不可点收录于合集#个上一篇下一篇