使用kotlinx.html DSL 写前端代码

kotlinx.html是可在 Web 应用程序中用于构建 HTML 的 DSL。 它可以作为传统模板系统(例如JSP、FreeMarker等)的替代品。

kotlinx. html 分别提供了kotlinx-html-jvm 和 kotlinx-html-js库的DSL , 用于在 JVM 和浏览器 (或其他 javascript 引擎) 中直接使用 Kotlin 代码来构建 html, 直接解放了原有的 HTML 标签式的前端代码。这样,我们 也可以使用 Kotlin来先传统意义上的 HTML 页面了。 Kotlin Web 编程将会更加简单纯净。

提示: 更多关于kotlinx.html的相关内容可以参考它的 Github 地址 :https://github.com/Kotlin/kotlinx.html

要使用 kotlinx.html 首先添加依赖

  1. dependencies {
  2. def kotlinx_html_version = "0.6.3"
  3. compile "org.jetbrains.kotlinx:kotlinx-html-jvm:${kotlinx_html_version}"
  4. compile "org.jetbrains.kotlinx:kotlinx-html-js:${kotlinx_html_version}"
  5. ...
  6. }

kotlinx.html 最新版本发布在 https://jcenter.bintray.com/ 仓库上,所以我们添加一下仓库的配置

  1. repositories {
  2. maven { url 'https://jitpack.io' }
  3. mavenCentral()
  4. jcenter() // https://jcenter.bintray.com/ 仓库
  5. maven { url "https://repo.spring.io/snapshot" }
  6. maven { url "https://repo.spring.io/milestone" }
  7. }

我们来写一个极简百度首页示例。这个页面界面如下图所示

Kotlin极简教程

前端 HTML 代码:

  1. <!DOCTYPE html>
  2. <html lang=zh-CN>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name=viewport content="width=device-width,initial-scale=1">
  7. <title>百度一下</title>
  8. <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet">
  9. <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  10. <link href="dsl.css" rel="stylesheet">
  11. <script src="dsl.js"></script>
  12. </head>
  13. <body>
  14. <div class="container">
  15. <div class="ipad center">
  16. ![](http://upload-images.jianshu.io/upload_images/1233356-49a0fecdc8bfa9cf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  17. </div>
  18. <form class="form">
  19. <input id="wd" class="form-control ipad">
  20. <button id="baiduBtn" type="submit" class="btn btn-primary form-control ipad">百度一下</button>
  21. </form>
  22. </div>
  23. </body>
  24. </html>

其中,dsl.css文件内容如下

  1. .ipad {
  2. margin: 10px
  3. }
  4. .center {
  5. text-align: center;
  6. }

dsl.js 文件内容如下

  1. $(function () {
  2. $('#baiduBtn').on('click', function () {
  3. var wd = $('#wd').val()
  4. window.open("https://www.baidu.com/s?wd=" + wd)
  5. })
  6. })

上面我们是通常使用的 HTML+JS+CSS 的方式来写前端页面的方法。现在我们把 HTML 部分的代码用Kotlin 的 DSL kotlinx.html 来重新实现一遍。

我们首先新建 Kotlin + Spring Boot 工程,然后直接来写 Kotlin 视图类HelloDSLView,代码如下:

  1. package com.easy.kotlin.chapter14_kotlin_dsl.view
  2. import kotlinx.html.*
  3. import kotlinx.html.stream.createHTML
  4. import org.springframework.stereotype.Service
  5. @Service
  6. class HelloDSLView {
  7. fun html(): String {
  8. return createHTML().html {
  9. head {
  10. meta {
  11. charset = "utf-8"
  12. httpEquiv = "X-UA-Compatible"
  13. content = "IE=edge"
  14. }
  15. title("百度一下")
  16. link {
  17. href = "https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css"
  18. rel = "stylesheet"
  19. }
  20. script {
  21. src = "https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"
  22. }
  23. link {
  24. href = "dsl.css"
  25. rel = "stylesheet"
  26. }
  27. script {
  28. src = "dsl.js"
  29. }
  30. }
  31. body {
  32. div(classes = "container") {
  33. div(classes = "ipad center") {
  34. img {
  35. src = "https://www.baidu.com/img/bd_logo1.png"
  36. width = "270"
  37. height = "129"
  38. }
  39. }
  40. form(classes = "form") {
  41. input(InputType.text, classes = "form-control ipad") {
  42. id = "wd"
  43. }
  44. button(classes = "btn btn-primary form-control ipad") {
  45. id = "baiduBtn"
  46. type = ButtonType.submit
  47. text("百度一下")
  48. }
  49. }
  50. }
  51. }
  52. }
  53. }
  54. }

相比之下,我们使用 DSL 的风格要比原生 HTML 要简洁优雅。关键是,我们的这个 HTML 是用 Kotlin 写的,这也就意味着,我们的 HTML 代码不再是简单的静态的前端代码了。我们完全可以直接使用后端的接口返回数据来给 HTML 元素赋值,我们也完全具备了(当然是完全超越了)诸如 JSP、Freemarker 这样的视图模板引擎的各种判断、循环等的语法功能,因为我们直接使用的是一门强大的编程语言 Kotlin 来写的 HTML 代码 。

然后,我们就可以直接在控制器层的代码里直接调用我们的 Kotlin 视图代码了:

  1. @Controller
  2. class HelloDSLController {
  3. @Autowired
  4. var helloDSLView: HelloDSLView? = null
  5. @GetMapping("hello")
  6. fun helloDSL(model: Model): ModelAndView {
  7. model.addAttribute("hello", helloDSLView?.html())
  8. return ModelAndView("hello")
  9. }
  10. }

为了简单起见,我们借用一下 Freemarker 来做视图解析引擎,但是它只负责原封不动地来传输我们的 Kotlin 视图代码。hello.ftl 代码如下:

  1. ${hello}

我们的源码目录如下

  1. ── src
  2. ├── main
  3. ├── java
  4. ├── kotlin
  5. └── com
  6. └── easy
  7. └── kotlin
  8. └── chapter14_kotlin_dsl
  9. ├── Chapter14KotlinDslApplication.kt
  10. ├── controller
  11. └── HelloDSLController.kt
  12. └── view
  13. └── HelloDSLView.kt
  14. └── resources
  15. ├── application.properties
  16. ├── banner.txt
  17. ├── static
  18. ├── dsl.css
  19. ├── dsl.js
  20. └── hello.html
  21. └── templates
  22. └── hello.ftl
  23. └── test
  24. ├── java
  25. ├── kotlin
  26. └── com
  27. └── easy
  28. └── kotlin
  29. └── chapter14_kotlin_dsl
  30. └── Chapter14KotlinDslApplicationTests.kt
  31. └── resources

然后,启动运行 SpringBoot 应用,浏览器访问 http://127.0.0.1:8888/hello , 我们可以看到如下输出界面:

Kotlin极简教程

这就是 DSL 的精妙之处。我们后面可以尝试使用 kotlinx.html 来写Kotlin 语言的前端代码了。在做 Web 开发的时候,我们通常是使用 HTML + 模板引擎(Velocity、JSP、Freemarker 等)来集成前后端的代码,这让我们有时候感到很尴尬,要学习模板引擎的语法,还得应对 前端HTML代码中凌乱的模板引擎标签、变量等片段代码。

使用 Kotlin DSL 来写 HTML 代码的情况将完全不一样了,我们将重拾前后端集成编码的乐趣(不再是模板引擎套前端 HTML,各种奇怪的 #、<#>、${} 模板语言标签),我们直接把 更加优雅简单的 DSL 风格的HTML 代码搬到了后端,同时HTML中的元素将直接跟后端的数据无缝交互,而完成这些的只是 Kotlin(当然,相应领域的 DSL 基本语义模型还是要学习一下)。

提示:本节项目源码:https://github.com/EasyKotlin/chapter14_kotlin_dsl