是否可以在Kotlin中传递内联函数?

时间:2018-04-12 10:41:12

标签: kotlin inline-functions

使用KotlinJs编写JavaScript代码时,我们通常需要仔细处理this

所以我们通常需要这个功能:

inline fun <T> thisAs() = js("this")

并在某处使用它:

this.click = {
    thisAs<MyVueComponent.Data>().username = "changed"
}

由于VueJs&#39;内在逻辑,我必须生成JavaScript代码this.usernamethis是硬编码),但这很难看,我不想在每次需要JavaScript thisAs<MyVueComponent.Data>().username时编写this {1}}。

所以我尝试通过定义函数defineMethods来改进它,如下所示:

external interface VueComponent<DATA, METHODS> {}

fun <DATA, METHODS> VueComponent<DATA, METHODS>.defineMethods(block: M.(() -> DATA) -> Unit): METHODS {
    val methods = jsObj<M>()
    block(methods, ::thisAs)
    return methods
}

我希望内联函数thisAs仍然是内联函数,即使我将其作为block传递给::thisAs,所以我可以像这样重写代码:

this.methods = this.defineMethods { data ->
    this.click = {
        data().username += "changed!"  // I want to write `data()` to generate a JavaScript `this`
    }
}

但遗憾的是,函数data::thisAs)不再内联,代码无法正常工作。

有什么方法可以解决这个问题吗?

更新:

1 个答案:

答案 0 :(得分:1)

我面临同样的问题。我有类似的功能来像你一样强制使用Javascript的这个对象。但是,我用lambda function with a receiver扩展了它(与Kotlin中用于类型安全的构建器相同的东西,除了我的函数返回 Unit 并且内联)。

inline fun <T> withJsThis(body: T.() -> Unit) {
  js("this").unsafeCast<T>().body()
}

它可以轻松地用于方法以及生命周期钩子(创建已安装等)。它需要一行额外的代码,但它很干净,并且在从Kotlin转换为Javascript时会产生与预期的 this.variable 完全相同的内容。

class LoginComponent {

  class Data {
    var username: String = "test@test.com"
    var password: String = ""
  }

  val data = {
    Data()
  }

  val template = """<form>
      <input type="text" v-model="username" placeholder="Email" /><br />
      <input type="password" v-model="password" placeholder="Password" /><br />
      <input type="submit" v-on:click.prevent="showInfo" />
    </form>"""

  val methods = object {

    val showInfo: () -> Unit = {
      withJsThis<Data> {
          console.log("METHOD: USER = $username, PASS = $password")
      }
    }

  }

  fun mounted() {
    withJsThis<Data> {
      console.log("MOUNTED: USER = $username, PASS = $password")
    }
  }

}