注射可能なコリンスタイル


カスタムコンポーネントを注入kotlinスタイルのCSS


skalableで我々はkotlinが大好き!我々はフロントエンドとバックエンドの両方でそれを操作します.
我々が潜在的に潜在的に興奮しているKotlinの1つの面は、Kotlin Multiplatform(KMM)です.我々は最近KLTINを使用したWebアプリの構築に取り組んでいるエンジニアのためのフレンドリーな環境を作成する方法でKMMのユーザビリティを改善するいくつかの作業を行ってきました.この記事は我々が構築したものを説明するのに役立つ.
コンポーネントの再利用は、初心者のための簡単な妙技ではない、それは様々なフレームワークと開発のパターンの深い理解を取ることができます.ほとんどのWebフレームワークでコンポーネントのルックアンドフィールを変更できるジェネリック型システムを構築するときは、通常は.ccs or .scss ファイル.これらのスタイルは、必要に応じてインポートされますが、同じ言語でそれをすべて維持したい場合はどうですか?このシナリオの周りにはたくさんの例がありますが、信じられないこともありませんKotlin-Styled フレームワーク.
我々が何を達成したいかを概説しましょう

理論上、我々はちょうど我々のスタイルの名前を注入することができます.css カスタムに適用したいファイルKotlinJS コンポーネントString . オブジェクト自体に直接アクセスすることで、同じ利点や機能を得ることはできません.このアプローチに続いて、スタイル名の定数文字列を管理し、再利用性を減らすことから、より多くのboilerplateを作成します.
我々のkotlinスタイルシートがどのように造られるかについて見ましょう.
object CustomComponentStyles : StyleSheet("CustomComponentStyles") {
   /**
    * A custom style declared directly in Kotlin using styled!
    */
   val cool by css {
      //Custom style
   }
}
最初に何をする必要があるかを理解するにはcss kotlinのスタイルは、スタイルを整えました.
fun css(vararg parents: RuleSet, builder: RuleSet) = CssHolder(this, *parents, builder)
これはちょうどaを返しますCssHolder , 実際に我々が得るものはRuleSet . を使用すると、委任が発生しますby 我々のkotlinスタイルシートのキー.これにより、css 値を適用するときにゲッターcool 変数.
深く見ることCssHolder 状況の真相を明らかにする.でオーバーロードされた演算子getValue 我々が見ることができる機能RuleSet . あなたが期待したときにあるおかしい状況CssHolder 知らないうちに.
operator fun getValue(thisRef: Any?, property: KProperty<*>): RuleSet = {}

拡張機能は、救助に!


この新たに発見された知識によって、私たちはコードをスケールして、よく読めるようになり、誰にとっても混乱が少なくなります.
開始するには、どのようなタイプのCustomStyledProps 期待するcss
external interface CustomStyledProps : RProps {
   var css: ArrayList<RuleSet>?
}
我々は得るArrayList 活字RuleSet どれが許容できないか、我々の問題は、それが許容できないということです.いくつかの言うかもしれないが、なぜそれが問題ですか?読みやすさ.そういうわけです.
ビルをつくりましょう!
個人的には私のすべてを保つ傾向があるextension functions インutil ディレクトリ.では、ファイルを作成しましょうCssExt.kt . これは私たちのカスタムCSSの拡張機能が住んでいるところです.
このファイルの中にRuleSet 自身.この関数はRuleSet それ自体ArrayList<Ruleset> それを使用するのにNULLでないオブジェクトは常に存在しなければなりません.この例では関数toCss() より直感的にコードを読むこと.
fun RuleSet.toCss(): ArrayList<RuleSet> {
   return arrayListOf(this)
}
我々には、加える方法がありますArrayList<RuleSet> リストとしてプロパティに、我々はまた、単一のRuleSet . これは私たちの無効問題に私たちをもたらします.2番目の拡張子を作成する前にCssExt.kt ファイルを作成するGlobalStyles ファイル内の単一の空のスタイル.
object GlobalStyles : StyleSheet("GlobalStyles") {

   /**
    * Rather than setting null we will use an empty style.
    */
   val empty by css {}

}
現在、我々は力を使うことができますElvis operator ?: (エルヴィスを見るために横にあなたの頭を回す)我々は保証を与えるために別の拡張機能を追加することができますRuleSet は、拡張子の中で有効な値を持ちます.これはCustomStyledProps インタフェースそのもの.
fun CustomStyledProps.css(): RuleSet {
   return this.css?.first() ?: GlobalStyles.empty
}

カスタムコンポーネントの作成


我々の新しい拡大と使用をする前にCustomSyledProps ただし、カスタムKintLinksコンポーネントを作成する必要があります.(この例ではstate ここでは、将来の拡張性の目的です
import react.*
import styled.CustomStyledProps
import styled.css
import styled.styledDiv
import util.css

/**
 * We use an interface to inject in props. It allows us to create
 * clean DSL builders for our custom components.
 *
 * By extending form CustomStyledProps we can benefit from adding CSS
 * directly through our props.
 */
external interface CustomComponentProps : CustomStyledProps {
   var name: String
}

/**
 * An interface is also used as a state
 * so we can maintain the state of a component.
 */
external interface CustomComponentState : RState {
   var name: String
}

/**
 * We extend from RComponent and tell it the types of Props and State to expect internally.
 *
 * This is our custom component.
 */
@JsExport
class CustomComponent(props: CustomComponentProps) : RComponent<CustomComponentProps, CustomComponentState>(props) {

   /**
    * To begin, we set the initial state to the name in the prop we injected.
    */
   override fun CustomComponentState.init(props: CustomComponentProps) {
      name = props.name
   }

   override fun RBuilder.render() {
      styledDiv {
         css {
            /**
             * We make use of our CustomStyledProps extension function by
             * setting the from the returned value RuleSet.
             */
            +props.css()
         }
         +"Hello there ${state.name} from your very own custom component!"
      }
   }
}

/**
 * Using an extension function on RBuilder we can construct our DSL.
 *
 * Here we apply each variable within the props to the child class of our Custom component,
 * Setting each as an attribute of the component.
 *
 */
fun RBuilder.customComponent(handler: CustomComponentProps.() -> Unit) = child(CustomComponent::class) {
   attrs(handler)
}
内部styledDiv があるcss セクション.ここでは任意のカスタムスタイルを埋め込むことができます.拡張モジュールの使用css() また、必要に応じて小道具を呼び出すこともできますRuleSet 私たちが注入した.

結果


ファイルの下部にある拡張機能は、カスタムコンポーネントを構築するクリーンな方法を提供します.我々の新しいユーティリティ機能を見ましょう.
/**
 * Our custom DSL to create the CustomComponent.
 * Here we use the cool style
 * @see CustomComponentStyles.cool
 */
customComponent {
   /**
    * Using our extension function we can create the desired list
    * that the CustomStyledProps requires.
    * @see CustomComponentProps.css
    */
   css = CustomComponentStyles.cool.toCss()
   name = "Sean"
}
/**
 * The same component but this time
 * we use the cooler style
 * @see CustomComponentStyles.cooler
 */
customComponent {
   css = CustomComponentStyles.cooler.toCss()
   name = "Seb"
}
呼び出し.toCss() 拡張モジュールを使用して、CustomStyledProps .
レンダリングすると、次の結果が得られます.

つのコンポーネント、2つの異なるスタイル、文字列なし、すべての直接Kollinの力とリンク!
このアプローチのサンプルプロジェクトをホストする@here
オール・オブ・ラック😎