如何在KotlinJs中使用body中的`this.field = value`生成一个javascript函数

时间:2018-04-11 11:05:46

标签: javascript kotlin kotlin-js-interop

当我将KotlinJS与riot一起使用时,需要像下面这样的函数来定义标记:

function (opts) {
    var self = this
    self.name = "sample"
    self.message = "init-message"

    self.onCreate = fun(opts: dynamic) {
        self.message = opts.message
    }

    self.click = fun() {
        self.message = "Clicked!"
    }
}

虽然我可以像这样编写Kotlin代码:

fun(opts: dynamic) {
    val self = js("this")

    self.name = "sample"
    self.message = "init-message"

    self.onCreate = fun(opts: dynamic) {
        self.message = opts.message
    }

    self.click = fun() {
        self.message = "Clicked!"
    }
}

但你可以看到它有几个问题:

  1. 我们必须使用一些js("this")技巧
  2. self.nameself.message等类似,功能正文中有很多动态代码
  3. 如何避免它们?我想尽可能地编写纯类型安全的Kotlin代码。

    并且,事先可以定义一个具有更清晰结构的类,如:

    class MyTag {
       val name = "sample"
       var message = "init-message"
       fun onCreate() {}
       fun click() {}
    }
    

    我可以接受对该类进行一些转换以生成所需的函数。

1 个答案:

答案 0 :(得分:1)

可能的解决方案可能是将js("this")转换为已知的kotlin类型。 虽然js()仍然存在,但它的用法非常本地,代码实际上是类型安全的。

下面的代码在js中生成你需要的东西

interface MyTag {
    var name: String

    var message: String

    var onCreate: (dynamic) -> Unit

    var click: () -> Unit
}

inline fun <T> builder(block: T.() -> Unit) = block(js("this"))

fun tagFunction(opts: dynamic) = builder<MyTag> {
    name = "sample"

    message = "init-message"

    onCreate = { message = opts.message }

    click = { message = "Clicked!" }
}