使用KotlinJs编写JavaScript代码时,我们通常需要仔细处理this
。
所以我们通常需要这个功能:
inline fun <T> thisAs() = js("this")
并在某处使用它:
this.click = {
thisAs<MyVueComponent.Data>().username = "changed"
}
由于VueJs&#39;内在逻辑,我必须生成JavaScript代码this.username
(this
是硬编码),但这很难看,我不想在每次需要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
)不再内联,代码无法正常工作。
有什么方法可以解决这个问题吗?
更新:
答案 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")
}
}
}