Говоря о Kotlin, первая реакция большинства людей, которые о нем слышали, заключается в том, что это язык для разработки под Android. Нужно сказать, что Google продвигает Kotlin намного больше, чем компания-основатель Kotlin, Jetbrains.
Kotlin может писать не только Android, но и сервер, можно сказать, что пока вы можете писать Java, вы можете использовать Kotlin для его замены. Конечно, Kotlin — это гораздо больше. В настоящее время Kotlin может разрабатывать и использовать следующие платформы. jvm, android, js и родной (бета). Из-за возможности разработки Native Kotlin теперь поддерживает разработку ios, хотя кажется, что эффект не так хорош.
Разработка React с Kotlin сегодня — это всего лишь пробная версия KotlinJs.
окружающая обстановка
- Браузер: Microsoft Edge 77.0.235.5 (официальная сборка) для разработчиков (64-разрядная версия)
- Kotlin: 1.3.12
Среда установки
Давным-давно на официальном сайте kotlin появились две библиотеки, эти две библиотеки в основном для улучшения экологии реакции в kotlin.JetBrains/create-react-kotlin-app, каркас для генерации проектов React; второй —JetBrains/kotlin-wrappers, в котором хранятся экологические компоненты вокруг реакции, такие как маршрутизатор, редукс и т. д.
Согласно документации скаффолдинга, одна строка кода может сгенерировать наш проект.
npx create-react-kotlin-app my-app
После создания проекта откройте проект и используйтеnpm start
илиyarn start
Стартовый проект.
Проект автоматически откроет браузер, а затем увидит наш проект, что означает, что наш проект запущен.
Мы можем посмотреть, что есть в официальной библиотеке оберток, кажется, что во всем отсутствует зрелая библиотека компонентов пользовательского интерфейса. Означает ли это, что мы должны сами писать все стили?
конечно, нет.
kotlinjs может вызывать модули nodejs, но это немного раздражает.
установить муравей
ant — это набор компонентов пользовательского интерфейса, разработанный Ali front-end, который имеет версию React. Сначала установите библиотеку.
пройти черезyarn add antd
Установите и дождитесь завершения установки.
После окончания установки импортируем ant demo в наш проект, открываем index.css и импортируем проект.
@import '~antd/dist/antd.css';
Давайте попробуем ввести кнопку, чтобы увидеть.
Затем мы видим, что на странице это по-прежнему оригинальная кнопка, которая не имеет ничего общего со стилем ant. Это означает, что мы еще не говорили об использовании компонентов ant в нашем проекте.
Привязать элементы управления пользовательского интерфейса
Создать новый пакетui/ant
чтобы сохранить наш класс привязки с компонентом ant.
Как написать наш класс привязки? Это первая трудность, с которой я столкнулся.
Во-первых, найдите каталог antd в наших node_modules и найдите управляющий каталог, который мы хотим связать.
мы используем@file:JsModule("antd/lib/button")
для указания каталога привязки. пройти через@JsName("default")
Для привязки в это время элемент управления должен бытьexport default Button;
@file:JsModule("antd/lib/button")
package ui.ant
import react.RClass
import react.RProps
@JsName("default")
external val button: RClass<RProps>
Снова введите кнопку, которую мы только что написали, в наш Main.kt. Кнопка на данный момент отличается от react.dom.button , объявленная нами кнопка не может напрямую устанавливать какие-либо свойства, методы и т.д. Конечно, мы ему это устроим.
package app
import react.RBuilder
import react.RComponent
import react.RProps
import react.RState
import react.dom.div
class App : RComponent<RProps, RState>() {
override fun RBuilder.render() {
div {
ui.ant.button {
+"Button"
}
}
}
}
fun RBuilder.app() = child(App::class) {}
Дождитесь завершения автоматической компиляции и обновления, загляните на нашу страницу.
Наконец-то увидели нашу кнопку, и стиль соответствует официальной документации Ant.
Это означает, что наша привязка теперь успешна.
Затем выполните те же шаги и привяжите другие элементы управления, которые будут использоваться таким же образом.
Привязываем ввод и поиск.
Эта привязка изменилась с прошлого раза, мы можем установить некоторые значения для этих двух свойств, чтобы мы могли использовать их непосредственно в HTML DSL. Здесь мы реализуемRProps
для повторной настройки свойств, которые мы хотим использовать, правильноInput
установитьplaceholder
,а такжеSeacherRPorps
может быть напрямую унаследованInputRProps
для расширения свойств.
@file:JsModule("antd/lib/input/Input")
package ui.antd
import react.*
external interface InputRProps:RProps {
var placeholder:String
}
@JsName("default")
external val input: RClass<InputProps>
Привязать элемент управления поиском
@file:JsModule("antd/lib/input/Search")
package ui.antd
import org.w3c.dom.events.Event
import react.*
external interface SearchProps : InputRProps {
var onChange: (Event) -> Unit
var value: String
}
@JsName("default")
external val search: RClass<SearchProps>
Создайте новый независимый элемент управления
Мы снова выделяем компонент, называемыйHome.kt
. Вставьте нашу кнопку и используйте Home.kt вместо App.kt.
package home
import react.RBuilder
import react.RComponent
import react.RProps
import react.RState
import react.dom.div
import ui.ant.button
class Home : RComponent<RProps, RState>() {
override fun RBuilder.render() {
div{
button{
+"Button"
}
}
}
}
fun RBuilder.home() = child(Home::class) {}
Ожидание обновления страницы, она все такая же, как и раньше.
Добавить событие клика
Поскольку в нашей кнопке не объявлено событие клика, его нельзя вызвать напрямую, но kotlinjs может вызывать динамические свойства, а через asDynamic мы можем вызывать любые свойства, существующие в html, которые мы хотим использовать.
button {
+"Button"
attrs {
asDynamic().onClick = {
console.log("on click")
}
}
}
На этом этапе событие нажатия кнопки завершено.Когда мы нажимаем на страницу, мы можем увидеть информацию в консоли браузера для печати.
двусторонняя привязка
Поскольку данные, которые мы хотим использовать, хранятся в RState, мы переписываем их для записи RState. Состояние и свойства — два важных свойства в реакции, состояние используется для изменения и обновления внутренних данных, а свойства — для передачи внешних данных.
Настройте HomeState для наследования RState для изменения внутренних данных.
interface HomeState : RState {
var inputValue: Int
}
Наш дом в RState типа HomeState
class Home : RComponent<RProps, HomeState>()
Это позволяет использовать данные в состоянии ниже.
Используйте div для записи наших данных.
div {
+"${state.inputValue}"
}
Незначительные изменения в событии нажатия кнопки и изменения данных в реакции требуют вызова setState.
button {
+"Button"
attrs.asDynamic().onClick ={
setState {
inputValue += 1
}
}
}
Однако после обновления страницы возникает ошибка.TypeError: Cannot read property 'toString' of undefinedМетод toString неопределенного не может быть прочитан.
Получается, что недостаточно объявить только в HomeState, его нужно объявить еще и в HomeStateHomeState.init()
Начальное значение назначается в переопределенном методе.
Дождавшись повторного обновления страницы, появился ожидаемый результат. При каждом нажатии кнопки числа складываются.
Работает с Аксиос
Axios — это широко используемый фреймворк HTTP-запросов во внешнем интерфейсе, и официальный представитель kotlin выполнил для него простую инкапсуляцию. Мы можем использовать его прямо здесь.
Прежде всего, все равно сначала установите axios
yarn add axios
После завершения установки создайте новую папку axios, а затем создайте новый Axios.kt.
package axios
import kotlin.js.Promise
@JsModule("axios")
external fun <T> axios(config: AxiosConfigSettings): Promise<AxiosResponse<T>>
// Type definition
external interface AxiosConfigSettings {
var url: String
var method: String
var baseUrl: String
var timeout: Number
var data: dynamic
var transferRequest: dynamic
var transferResponse: dynamic
var headers: dynamic
var params: dynamic
var withCredentials: Boolean
var adapter: dynamic
var auth: dynamic
var responseType: String
var xsrfCookieName: String
var xsrfHeaderName: String
var onUploadProgress: dynamic
var onDownloadProgress: dynamic
var maxContentLength: Number
var validateStatus: (Number) -> Boolean
var maxRedirects: Number
var httpAgent: dynamic
var httpsAgent: dynamic
var proxy: dynamic
var cancelToken: dynamic
}
external interface AxiosResponse<T> {
val data: T
val status: Number
val statusText: String
val headers: dynamic
val config: AxiosConfigSettings
}
Делаем простое приложение, введя имя, переходим на Github, чтобы найти соответствующий репозиторий.
Сначала определите наш класс данных для хранения данных, которые мы запрашиваем.
data class Result(
val total_count: Int,
val items: Array<Item>
)
data class Item(val id: Long,
val node_id: String,
val name: String,
val full_name: String,
val html_url: String)
Затем объявите классы, используемые в HomeState.
interface HomeState : RState {
var inputValue: String
var repos: Array<Item>
}
Ниже приведен код определения интерфейса.
div(classes = "search-input") {
search {
attrs {
onChange = {
val element = it.target as HTMLInputElement
setState {
inputValue = element.value
}
}
placeholder = "请输入 Github 仓库名称"
}
}
}
button {
+"搜索"
attrs {
asDynamic().onClick = {
}
}
}
div(classes = "list") {
if (state.repos.isNotEmpty()) {
ul {
for ((index, item) in state.repos.withIndex()) {
li {
a(href = item.html_url) {
+"${index + 1} / ${item.full_name}"
}
}
}
}
}
}
Однако, когда мы предварительно просмотрели интерфейс в это время, мы обнаружили, что он снова и снова ошибался, предполагая, что репозитории не могут быть итерированы.
Очевидно, почему нельзя повторить массив? Оказалось, что при создании компонента Home репозитории не были инициализированы. Здесь вам нужно понять жизненный цикл реакции и инициализировать данные до создания компонента.
override fun componentWillMount() {
setState {
repos = emptyArray()
}
}
Теперь страница может отображаться нормально.
Улучшить событие нажатия кнопки.
button {
+"搜索"
attrs {
asDynamic().onClick = {
//https://api.github.com/search/repositories?q=
val config: AxiosConfigSettings = jsObject {
url = "https://api.github.com/search/repositories?q=${state.inputValue}"
}
axios.axios<Result>(config).then { response ->
setState {
repos = response.data.items
}
}.catch { error ->
console.log("error", error)
}
}
}
}
Теперь проект завершен.
Суммировать
В первую очередь заявляю, что автор не профессиональный фронтенд, поэтому надеюсь, что в статье есть ошибки.Более важная цель этой статьи — показать использование и опыт kotlin в других сферах.
Когда kotlin пишет React, его привычки письма должны быть похожи на написание ts, и это дает студентам, работающим с back-end, опыт написания front-end. Однако экология неполная, ни одна библиотека UI-компонентов официально не написана на kt, скорость компиляции низкая, отчет об ошибках иногда не очевиден, информации мало. Однако, если вы хотите стиснуть зубы и развиваться, я лично считаю, что это вполне возможно, но предполагается, что вам придется построить много колес самостоятельно.