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

Is it possible to pass inline functions in Kotlin?

在使用 KotlinJs 为 JavaScript 编写代码时,我们通常需要小心处理 this

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

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

并在某处使用它:

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

由于VueJs的内在逻辑,我不得不生成JavaScript代码this.usernamethis是hardcode),但是很难看,我不想写thisAs<MyVueComponent.Data>().username 每次我需要一个 JavaScript this.

所以我尝试通过定义函数 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 仍然是一个内联函数,即使我将它作为 ::thisAs 传递给 block,所以我可以这样重写代码:

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

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

有什么办法可以解决吗?


更新:

我遇到了同样的问题。我有一个类似的函数来转换 Javascript 的 this 对象。但是,我用 lambda function with a receiver 扩展了它(与 Kotlin 中用于类型安全构建器的东西相同,除了我的函数 returns Unit 并且是内联)。

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

它可以很容易地用于方法以及生命周期钩子(createdmounted,等等)。它需要一行额外的代码,但它很干净,并且在从 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")
    }
  }

}