如何静态编译HTML?

 

对HTML的残缺支持以前我们使用其他前端框架,比如Cycle.js 、Widok、ScalaTags时,由于...



对HTML的残缺支持

以前我们使用其他前端框架,比如Cycle.js 、Widok、ScalaTags时,由于框架不支持 HTML语法,前端工程师被迫浪费大量时间,手动把HTML改写成代码,然后慢慢调试。

就算是支持HTML语法的框架,比如ReactJS,支持状况也很残缺不全。

比如,在ReactJS中,你不能这样写:

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

classBrokenReactComponent extendsReact.Component{

render(){

return(

不支持class属性

不支持style属性

不支持for属性

);

}

}

前端工程师必须手动把 
class
 和 
for
 属性替换成 
className
 和 
htmlFor
,还要把内联的
style
 样式从CSS语法改成JSON语法,代码才能运行:

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

classWorkaroundReactComponent extendsReact.Component{

render(){

return(

被迫把class改成className

被迫把样式表改成JSON

被迫把for改成htmlFor

);

}

}

这种开发方式下,前端工程师虽然可以把HTML原型复制粘贴到代码中,但还需要大量改造才能实际运行。比Cycle.js、Widok或者ScalaTags省不了太多事。

不兼容原生DOM操作

此外,ReactJS等一些前端框架,会生成虚拟DOM。虚拟DOM无法兼容浏览器原生的DOM API ,导致和jQuery、D3等其他库协作时困难重重。比如ReactJS更新DOM对象时常常会破坏掉jQuery控件。

Reddit很多人讨论了这个问题。他们没有办法,只能弃用jQuery。我司的某客户在用了ReactJS后也被迫用ReactJS重写了大量jQeury控件。

Binding.scala中的XHTML

现在有了Binding.scala ,可以在
@dom
方法中,直接编写XHTML。比如:

JavaScript

1

2

3

4

5

6

7

8

9

@dom def introductionDiv={

Binding.scala的优点

简单

概念少功能多

}

以上代码会被编译,直接创建真实的DOM对象,而没有虚拟DOM。

Binding.scala对浏览器原生DOM的支持很好,你可以在这些DOM对象上调用DOM API,与 D3、jQuery等其他库交互也完全没有问题。

ReactJS对XHTML语法的残缺不全。相比之下,Binding.scala支持完整的XHTML语法,前端工程师可以直接把设计好的HTML原型复制粘贴到代码中,整个网站就可以运行了。

Binding.scala中XHTML的类型

@dom
方法中XHTML对象的类型是Node的派生类。

比如,
 的类型就是HTMLDivElement,而 
 的类型就是 HTMLButtonElement。

此外, 
@dom
 注解会修改整个方法的返回值,包装成一个Binding。

JavaScript

1

2

3

@dom def typedButton:Binding[HTMLButtonElement]={

按钮

}

注意
typedButton
是个原生的
HTMLButtonElement
,所以可以直接对它调用 DOM API。比如:

JavaScript

1

2

3

4

@dom val autoPrintln:Binding[Unit]={

println(typedButton.bind.innerHTML)// 在控制台中打印按钮内部的 HTML

}

autoPrintln.watch()

这段代码中,
typedButton.bind.innerHTML
 调用了 DOM API HTMLButtonElement.innerHTML。通过
autoPrintln.watch()
,每当按钮发生更新,
autoPrintln
中的代码就会执行一次。

其他HTML节点

Binding.scala支持HTML注释:

JavaScript

1

2

3

@dom def comment={

}

Binding.scala也支持CDATA块:

JavaScript

1

2

3

4

5

6

7

8

9

10

@dom def inlineStyle={

Binding.scala真好用!



}

内嵌Scala代码

除了可以把XHTML内嵌在Scala代码中的 
@dom
 方法中,Binding.scala 还支持用 
{ ... }
语法把 Scala 代码内嵌到XHTML中。比如:

JavaScript

1

2

3

@dom def randomParagraph={

生成一个随机数:{math.random.toString}

}

XHTML中内嵌的Scala代码可以用 
.bind
 绑定变量或者调用其他 
@dom
 方法,比如:

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

val now=Var(newDate)

window.setInterval(1000){now:=newDate}

@dom def render={

现在时间:{now.bind.toString}

{introductionDiv.bind}

{inlineStyle.bind}

{typedButton.bind}

{comment.bind}

{randomParagraph.bind}

}

上述代码渲染出的网页中,时间会动态改变。

强类型的 XHTML

Binding.scala中的XHTML 都支持静态类型检查。比如:

JavaScript

1

2

3

4

5

@dom def typo={

val myDiv=content

myDiv.typoMethod()

myDiv

}

由于以上代码有拼写错误,编译器就会报错:

JavaScript

1

2

3

4

5

6

typo.scala:23:value typoProperty isnotamember of org.scalajs.dom.html.Div

val myDiv=content

^

typo.scala:24:value typoMethod isnotamember of org.scalajs.dom.html.Div

myDiv.typoMethod()

^

内联CSS属性

用 
style
 属性设置内联样式时,
style
 的值是个字符串。比如:

JavaScript

1

2

3

@dom def invalidInlineStyle={

}

以上代码中设置的 
typoStyleName
 样式名写错了,但编译器并没有报错。

要想让编译器能检查内联样式,可以用 
style:
 前缀而不用 
style
 属性。比如:

JavaScript

1

2

3

@dom def invalidInlineStyle={

}

那么编译器就会报错:

JavaScript

1

2

3

typo.scala:28:value typoStyleName isnotamember of org.scalajs.dom.raw.CSSStyleDeclaration

^

这样一来,可以在编写代码时就知道属性有没有写对。不像原生JavaScript / HTML / CSS那样,遇到bug也查不出来。

自定义属性

如果你需要绕开对属性的类型检查,以便为HTML元素添加定制数据,你可以属性加上 
data:
 前缀,比如:

JavaScript

1

2

3

@dom def myCustomDiv={

}

这样一来Scala编译器就不会报错了。

结论

从这些示例可以看出,Binding.scala 一方面支持完整的XHTML ,可以从高保真HTML 原型无缝移植到动态网页中,开发过程极为顺畅。另一方面,Binding.scala 可以在编译时静态检查XHTML中出现语法错误和语义错误,从而避免bug 。

以下表格对比了ReactJS和Binding.scala对HTML语法的支持程度:

ReactJSBinding.scala是否支持HTML语法?残缺支持完整支持是否支持标准的
style
属性?不支持,必须改用 JSON 语法支持,既支持标准的
style
属性也支持
style:
前缀是否支持标准的
class
属性?不支持,必须改用
className
支持,既支持
class
也支持
className
是否支持标准的
for
属性?不支持,必须改用
htmlFor
支持,既支持
for
也支持
htmlFor
是否支持HTML注释?不支持支持是否兼容原生DOM操作?不兼容兼容是否兼容jQuery?不兼容兼容能否在编译时检查出错误?不能能

专注IT, 专注创新,更多资讯和最新动态,请您关注该微信号!
微信扫一扫


    关注 IT专家


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册