こんにちは、
この問題は、私の経験をFelizおよびFeliz.Bulmaと共有するためのものです。
このフィードバックは、からフェイブルREPL変換に基づいているFable.React + Fulmaにフェリス+ Feliz.Bulma 。
最初のセクションでは、Felizを使用するときに気に入ったものや問題があったものをすべてリストします。 Fable.ReactとFulmaについても同様のことをします。なぜなら、それらは良い部分と悪い部分を免除されていないからです。
次に、もう一度、FelizとFeliz.Bulmaでの私の経験がどのように進んだかを説明しようと思います。 目標は、私の視点が時間の経過とともにどのように変化したか、そしてその理由をあなたと共有することです。
重要
私が分析している主題は敏感であり、私を恐れている何かがあることを私は知っています。 ただし、コメントセクションは前向きに保つことを忘れないでください。
フィードバックを整理する方法を見つけようとしましたが、古典的な「長所と短所」は制限が多すぎて攻撃的だと感じました。
代わりに、記号を使用します。
同じエントリに複数の記号を含めることができます:)
✔️FelizはFable.Reactの上にあるレイヤーであるため、FelizとFable.Reactを混在させることができます
✔️リストが1つしかないため、コードはFable.Reactに比べてインデントしやすくなっています。 集計に従う方が簡単です。
詳細はこちら
** Fable.React + Fulma **
div [ ]
[ Hero.hero [ Hero.IsFullHeight ]
[ Hero.body [ ]
[ Container.container [ ]
[ img [ Src "img/fable-ionide.png"
Style [ Display DisplayOptions.Block
Width "auto"
Margin "auto" ] ]
br [ ]
Heading.h3 [ Heading.Modifiers [ Modifier.TextAlignment (Screen.All, TextAlignment.Centered) ] ]
[ str "Fable REPL" ]
Heading.p [ Heading.IsSubtitle
Heading.Is5
Heading.Modifiers [ Modifier.TextAlignment (Screen.All, TextAlignment.Centered) ] ]
[ str "is only available on desktop" ] ] ] ] ]
** Feliz + Feliz.Bulma **Html.div [
Bulma.hero [
hero.isFullHeight
prop.children [
Bulma.heroBody [
Bulma.container [
Html.img [
prop.src "img/fable-ionide.png"
prop.style [
style.display.block
style.width length.auto
style.margin length.auto
]
]
Html.br [ ]
Bulma.title3 [
text.hasTextCentered
prop.text "Fable REPL"
]
Bulma.subtitle5 [
text.hasTextCentered
prop.text "is only available on desktop"
]
]
]
]
]
]
✔️前のポイントのおかげで、コードを移動することも簡単です
✔️DOMプロパティ用の強く型付けされたAPI
✔️ ICSSUnits
介したCSSおよびCSSユニット用の強く型付けされたAPI
style.marginLeft (length.em 0.5)
style.width (length.percent (model.PanelSplitRatio * 100.))
✔️コンテキストを汚染しません。ほとんどのものはHtml.*
またはProp.*
✔️⚠️Felizは、コード内のノイズを回避する可能性を提供します
詳細はこちら
Html.span "Fable REPL"
// instead of
// Feliz verbose version
span [
str "Fable REPL"
]
// Fable.React
span [ ]
[ str "Fable REPL" ]
// --------------------
Bulma.title4 "Fable REPL"
// instead of
// Feliz.Bulma verbose version
Bulma.title4 [
prop.text "Fable REPL"
]
// Fable.React
Headings.h4 [ ]
[ str "Fable REPL" ]
同じコードを書く方法はいくつかあるので、コードを単に「読み取る」ことはできません。 外側の文脈を理解するために、一歩後退する必要がある場合があります。 また、すべてが同じように記述されているわけではないため、コードの「一貫性」が低下します。Html.tr [
Html.th "Steps"
Html.th [
prop.className "has-text-right"
prop.text "ms"
]
]
⚠️(まだ)SSRをサポートしていません
⚠️メソッド/プロパティのオーバーロードを発見するのは簡単ではありません(これはおそらく私が知らないIonideの制限です)
そうしなければならなかった:
prop.text 2.0
がサポートされているかどうかをテストします。⚠️複数のパラメータを使用するコールバックの使用を難しくします。 Fable.REPLでは、 System.Func<_,_,_>
を使用してアンカリーを強制する必要がありました。
詳細はこちら
[<Erase>]
type editor =
/// <summary>Triggered when the Editor has been mounted</summary>
static member inline editorDidMount (f : System.Func<Monaco.Editor.IStandaloneCodeEditor, Monaco.IExports, unit>) = Interop.mkAttr "editorDidMount" f
これにより、呼び出し側でこのコードが得られます。let private registerCompileCommand dispatch =
System.Func<_,_,_>(
fun (editor : Monaco.Editor.IStandaloneCodeEditor) (monacoModule : Monaco.IExports) ->
let triggerCompile () = StartCompile None |> dispatch
editor.addCommand(monacoModule.KeyMod.Alt ||| int Monaco.KeyCode.Enter, triggerCompile, "") |> ignore
editor.addCommand(monacoModule.KeyMod.CtrlCmd ||| int Monaco.KeyCode.KEY_S, triggerCompile, "") |> ignore
)
✔️⚠️Felizは、ユーザーの生活を少し楽にするためのオーバーロードを提供しますが、これにはコストがかかります。
prop.onChange
場合、聞きたいものに応じて6つのオーバーロードのように:
static member inline onChange (handler: bool -> unit)
static member inline onChange (handler: Event -> unit)
static member inline onChange (handler: File -> unit)
static member inline onChange (handler: File list -> unit)
static member inline onChange (handler: string -> unit)
static member inline onCheckedChange (handler: bool -> unit)
これは、人々が「no」の楽しいコードを書くことを回避するので便利ですが、対応するのは、どのイベントタイプが必要かを明示的に言う必要があるということです。
// Feliz
prop.onChange (fun (e : Types.Event) -> e.Value |> ChangeGistToken |> dispatch)
// Fable.React
prop.onChange (fun e -> e.Value |> ChangeGistToken |> dispatch)
✔️⚠️Felizエコシステムはほとんどタイプセーフですが、無効なコードの記述を妨げることはありません。 FelizとFeliz.Bulmaのようなその拡張機能の1つを使用する場合、プロパティを簡単に混在させることができますが、それを行うときは注意する必要があります。
詳細はこちら
このコードは、FelizとF#コンパイラの観点からは問題ないように見えますが、期待した結果は得られません。
Html.p [
text.isUppercase
text.isItalic
color.hasTextSuccess
prop.text "Hello Feliz"
]
`text.isUppsercase`、` text.isItalic`、 `color.hasTextSuccess`はすべて` ClassName "my-css-class`のようなものを出力します。しかし、Reactでは、最後の1つだけが効果を発揮するため、この場合、コードは生成:<p class="has-text-success">Hello Feliz<\p>
それ以外の<p class="is-uppercase is-italic has-text-success>Hello Feliz</p>
その解決策は、Feliz.Bulmaが提供する `++`を使用することです。open Feliz.Bulma.Operators
Html.p [
text.isUppercase
++ text.isItalic
++ color.hasTextSuccess
prop.text "Hello Feliz"
]
互換性がある場合は、別のFelizライブラリからの動作を「Feliz要素」に追加できることを意味するため、これは依然として良い可能性です。 人々はただそれに注意する必要があります。ℹ最初、FelizはFable.Reactを使用したときに得られるシンタックスシュガーev.Value
を提供していないと思いましたが、そうではありません。
Fable.React.Extension
はシンタックスシュガーをホストしているので、それを開くだけで、すべてのFable.React関数でコンテキストを汚染しないようにすることができます。
open Feliz
open Fable.React.Extensions
ℹ構文はHTMLの考え方を再現していません。 Felizは、HTMLよりもReactAPIの上位にあるシンタックスシュガーです。 children
さえプロパティであるため、Felizはプロパティの観点から考えます。
✔️Felizとうまく統合します
✔️フルマに比べてインデントが簡単
詳細はこちら
// Fulma
Card.card [ ]
[ Card.header [ Common.Props [ OnClick (fun _ -> ToggleWidget title |> dispatch ) ] ]
[ Card.Header.title [ ]
[ Icon.icon [ Icon.Props [ Style [ MarginRight ".5em" ] ] ]
[ Fa.i [ icon; Fa.Size Fa.FaLarge ] [] ]
str title ]
Card.Header.icon [ ]
[ Icon.icon [ ] [ Fa.i [ headerIcon ; Fa.Size Fa.FaLarge ] [] ] ] ]
ofOption content ]
// Feliz.Bulma
Bulma.card [
Bulma.cardHeader [
prop.onClick (fun _ -> ToggleWidget title |> dispatch )
prop.children [
Bulma.cardHeaderTitle [
Bulma.icon [
prop.style [
style.marginRight (length.em 0.5)
]
prop.children [
Fa.i [ icon; Fa.Size Fa.FaLarge ] []
]
]
Html.text title
]
Bulma.cardHeaderIcon [
Bulma.icon [
Fa.i [ headerIcon ; Fa.Size Fa.FaLarge ] []
]
]
]
]
Html.ofOption content
]
✔️ Bulma
プレフィックスのおかげで、 Bulma
コンポーネントを簡単に識別できます
✔️⚠️プロパティはアクセス可能ですが、コンテキストbutton.*
、 help.*
、 columns.*
汚染します。
理論的には、CSSフレームワークは1つだけ使用する必要があるため、 button.*
、 columns.*
などの一般的なプロパティで衝突することはないと思います。
✔️コンポーネントの階層は簡単に把握できるようです
Bulma.card
> Bulma.cardHeader
> Bulma.cardHeaderTitle
たとえば、ここをクリックしてください
Bulma.card [
Bulma.cardHeader [
prop.onClick (fun _ -> ToggleWidget title |> dispatch )
prop.children [
Bulma.cardHeaderTitle [
// ...
]
Bulma.cardHeaderIcon [
// ...
]
]
]
]
⚠️しかし、一部のコンポーネントは同じ規則に従っていません
Bulma.passwordInput
代わりにBulma.inputPassword
この場合、同じ「プレフィックス」で始まらないため、さまざまなタイプの入力を簡単に調べることはできません。
✔️⚠️Feliz.Bulmaを使用すると、コンポーネントの動作を簡単に組み合わせることができます。
詳細はこちら
Bulma.button [
// Properties specific to a button coming from Feliz.Bulma
button.isOutlined
// Properties specific to a tooltip coming from Feliz.Bulma
tooltip.hasTooltipRight
tooltip.text tooltipText
// General properties coming from Feliz
prop.disabled isCompiling
prop.onClick (fun _ -> dispatch msg)
prop.children [
Bulma.icon [
icon.isLarge
prop.children faIcon
]
]
]
ご覧のとおり、既存のコンポーネントに新しい動作を簡単に追加できるので、これはすばらしいことです。 ここでは、動作ツールチップをボタンに追加しました。 ただし、これは、次のような無効なコードを記述できることも意味します。Html.select [
select.isFullwidth
]
それ以外のBulma.select [
select.isFullwidth
]
Fulmaはコンポーネントの分離についてより厳密であり、 `CustomClass`プロップを介してCSSクラスを渡さない限り、動作を混在させることはできません。✔️⚠️Feliz.Bulmaは、出力するHTML要素を制御する方法を提供していません。
たとえば、 div
を生成するBulma.field
しかありません。 ただし、出力としてp
要素が必要な場合があります。
✔️⚠️Feliz.BulmaはBulmaの正確なマッピングです
スリムなのでいいですね。
しかし、それはまた意味します:
たとえば、 Bulma.tabs
コンポーネントを作成する場合、ガイドはなく、 tabs
はul
が必要であり、その後にli
とa
が必要であることを知っておく必要があります。
コードを表示するには、ここをクリックしてください
// Feliz + Feliz.Bulma
Bulma.tabs [
tabs.isCentered
tabs.isMedium
tabs.isToggle
prop.children [
Html.ul [
Html.li [
if (activeTab = CodeTab.FSharp) then
prop.className "is-active"
prop.onClick (fun _ -> SetCodeTab CodeTab.FSharp |> dispatch)
prop.children [
Html.a [
prop.text "F#"
]
]
]
Html.li [
if (activeTab = CodeTab.Html) then
prop.className "is-active"
prop.onClick (fun _ -> SetCodeTab CodeTab.Html |> dispatch)
prop.children [
Html.a [
prop.text "HTML"
]
]
]
Html.li [
if (activeTab = CodeTab.Css) then
prop.className "is-active"
prop.onClick (fun _ -> SetCodeTab CodeTab.Css |> dispatch)
prop.children [
Html.a [
prop.text "CSS"
]
]
]
]
]
]
Fulmaを使用すると、ユーザーは「Bulmaコンポーネント」の観点からより多くのことを考えることができます。// Fable.React + Fulma
Tabs.tabs [ Tabs.IsCentered
Tabs.Size Size.IsMedium
Tabs.IsToggle ]
[ Tabs.tab [ Tabs.Tab.IsActive (activeTab = CodeTab.FSharp)
Tabs.Tab.Props [
OnClick (fun _ -> SetCodeTab CodeTab.FSharp |> dispatch)
] ]
[ a [ ] [ str "F#" ] ]
Tabs.tab [ Tabs.Tab.IsActive (activeTab = CodeTab.Html)
Tabs.Tab.Props [
OnClick (fun _ -> SetCodeTab CodeTab.Html |> dispatch)
] ]
[ a [ ] [ str "HTML" ] ]
Tabs.tab [ Tabs.Tab.IsActive (activeTab = CodeTab.Css)
Tabs.Tab.Props [
OnClick (fun _ -> SetCodeTab CodeTab.Css |> dispatch)
] ]
[ a [ ] [ str "CSS" ] ] ]
ノート:
Fulmaはtab
をコンポーネントと見なし、 Tabs.Tab.*
固有のラッパーを提供します。
Fulmaでは、 a
要素が必要であることを知っておく必要がありますが、デフォルトで追加できます(一部のコンポーネントの場合)。
✔️⚠️Feliz.Bulmaは、小さなプロジェクトのバンドルサイズへの影響は小さくなりますが、プロジェクトサイズが大きくなると、より大きな影響があります。
詳細はこちら
Fulmaは、Bulmaクラスをモデル化するために多くのDUを使用しています。 [Common.fs](https://github.com/Fulma/Fulma/blob/2f99474cd6c793776001d07da009f7211be2f30c/src/Fulma/Common.fs);をご覧ください。 また、各コンポーネントには独自のDUがあります。 これには、FulmaがDUをクラスに変換する関数呼び出し `parseOptions`を実装する必要があります。 Feliz.Bulmaは、Bulmaクラスの上にDSLを作成するのではなく、クラスを直接出力することで、より直接的なアプローチを取ります。
// Fulma
Column.column
[
Column.Width (Screen.Desktop, Column.IsHalf)
Column.Width (Screen.Mobile, Column.IsFull)
]
[
// ...
]
// Feliz
Bulma.column [
column.isHalfDesktop
column.isFullMobile
prop.children [
// ...
]
]
クラスを直接使用し、プロパティリストを操作することで、Feliz.Bulmaは、Fulmaに追加されたすべてのDUとコードのような大きなコストをかけません。 ただし、すべてのクラスに「参加」するには、追加のパスが必要です。 この部分は[Feliz.Bulma.ElementBuilders.Helpersモジュール](https://github.com/Dzoukr/Feliz.Bulma/blob/3ecbba1579d2a26281f24e6a6664b5d9c5222603/src/Feliz.Bulma/ElementBuilders.fs#L6-L23)を介して行われますが、すべてこれらの機能はインライン化されています。 そのため、プロジェクトが大きくなるほど、コードへの影響も大きくなります。⚠️新しいカラーサポートを追加するのは簡単ではありません。
Feliz.Bulmaでは、各コンポーネントはbutton.isWarning
、 help.isWarning
などの独自のカラー実装を保持します。
したがって、色を追加する場合は、すべてのbutton.isMyNewColor
、 help.isMyNewColor
を実装する必要があります。
フルマでは、それらはすべて同じ色タイプを共有します。 ドキュメントを参照してください
✔️プロパティのリストと子のリストと考えると、HTML構造に従います
⚠️インデントルールは、二重リストを整理する必要があるため確立するのが難しく、一般に、多くの例外的なケースを作成します。
詳細な説明はこちら
例:
// When I want to put an empty div
div [ ] [ ]
// When I want to put a div with a single property
div [ ClassName "button" ] [ ]
// or
div [ ClassName "button" ]
[ ]
// When I want to put a div with several property
div [ ClassName "button"; Id "my-button" ]
[ ]
// yes but what if one of my property is not that simple?
div
[
ClassName "button"
OnClick (fun _ ->
// do something
)
]
[ ]
// It's also possible to have consistent indentation if you do something like that
div [ ] [
// Children 1
// Children 2
]
// But if you have non simple property you still have problems, I don't personally don't find it easy to read
// I am not sure if that's how people would write it because I don't use this format personally
div [
ClassName "button"
OnClick (fun _ ->
// do something
)
] [
div [ ] [
str "Children 1"
]
]
// and so on
プロパティリストのいくつかのケースを処理するときにわかるように、いくつかの可能な構文があります。 プロジェクトで一貫した構文を確立する必要がある場合は、次のようになります。div
[
// Property 1 ...
// Property 2 ...
// Property 3 ...
]
[
div
[
// Property 1 ...
// Property 2 ...
// Property 3 ...
]
[
// Children 1 ...
// Children 2 ...
// Children 3 ...
]
div
[
// Property 1 ...
// Property 2 ...
// Property 3 ...
]
[
// Children 1 ...
// Children 2 ...
// Children 3 ...
]
]
// So for an empty element
div
[
]
[
]
// Awesome... 🙄
フェリスでの比較のために、私はします:// Empty div
Html.div [ ]
// Non empty div
Htmldiv [
// Property 1
// Property 2
// Property 3
prop.children [
Html.div [
// Property 1
// Property 2
// Property 3
]
Html.div [
// Property 1
// Property 2
// Property 3
// Complexe property
OnClick (fun _ ->
// Do something
)
]
]
]
したがって、現在2つのケースしかなく、Felizコードを構造化する単一の方法が本当に必要な場合は、ノイズをあまり発生させずに空のバージョンを複数行に書き込むこともできます。⚠️ほとんどのAPIは入力されていません
type HTMLAttr =
| DefaultChecked of bool
| DefaultValue of obj
| Accept of string
| AcceptCharset of string
| AccessKey of string
| Action of string
| AllowFullScreen of bool
| AllowTransparency of bool
✔️⚠️一部のAPIは入力されていますが、すべてではありません。これは、コードに一貫性がないことを意味します。
✔️SSRをサポートしています
✔️タイプセーフAPI
Modifier.TextAlignment (Screen.All, TextAlignment.Centered)
Button.button [ Button.Color IsWhite ]
[ str "White" ]
✔️FulmaAPIは、その構造を理解していれば、インテリセンスを介して簡単に探索できます
✔️Fulmaはあなたにコンポーネントの観点から考えることを強制します
✔️ IsCustomColor
おかげで、サポートされている色を簡単に拡張できます
// All you need to add `custom-purple` support to all your components is this line
let isCustomPurple = IsCustomColor "custom-purple"
✔️⚠️すべてのコンポーネントの例を含む優れたドキュメントがあると思いますが、すべてのコンポーネントに同じレベルの情報が含まれているわけではありません
✔️⚠️バンドルサイズへのフルマの影響は「安定」しています。 この点については、Feliz.Bulmaのセクションで説明しています。
⚠️人々は「特別なヘルパー」を簡単に見つけることができません。
⚠️強い型のDSLがあるため、フルマコードはコードにノイズを追加します
例については、ここをクリックしてください
// Fulma
Heading.p [ Heading.IsSubtitle
Heading.Is5
Heading.Modifiers [ Modifier.TextAlignment (Screen.All, TextAlignment.Centered) ] ]
[ str "is only available on desktop" ]
// Feliz.Bulma
Bulma.subtitle5 [
text.hasTextCentered
prop.text "is only available on desktop"
]
⚠️Fulmaコードは、 Props
、 Modifiers
を組み合わせるとネストされたリストがたくさんあるため、正しくフォーマットするのはそれほど簡単ではありません。
私はこの分析に2〜3週間取り組んできましたが、それでも続行できます。 でも、時間がかかって終わらせないといけないので、状況がよく見えてきたと思います。
言うまでもなく、特にFable.ReactとFulmaについては、もっと良い点や問題を挙げられる可能性がありますが、それは私にとって最も難しい部分でもあります。 私は3年以上使用して設計しているので、客観的に見るのは難しいです。
Fable.ReactからFelizへの変換は簡単に行えました。 FelizはFable.Reactと互換性があり、ファイルごと、コンポーネントごとなど、プログレッシブな方法で変換を行うことができます。
すべてを確実に変換するために、すべてのopen Fable.React
およびopen Fable.React.Props
命令を削除しました。 また、依存関係としてFulmaを削除しました。
もちろん、いくつかのファイルを忘れていたので、コンパイラのエラーを修正して、それが機能していました。
ここで、変換をホストしているマージリクエストを確認でき
フェリスを最初に発見したとき、それは「HTML / JSXの方法」に従わず、それは私が多大な努力を費やしたものの代替プロジェクトであるため、防御的でした。
それから私は、それがイノベーションの仕組みであり、私たちが成長することを可能にするものであることを思い出しました。 たとえば、今日はエルミッシュがいます。
私が覚えているもう1つのことは、JSXは「実際のReact API」ではなく、実際、React APIはReact.createElement
です。 JSXはその上にあるシンタックスシュガーであり、Fable.ReactとFelizにも同じことが言えます。 私にとってそれは私が前進し、それについて好奇心をそそるのを助けたので、私はそれを主張します。
Felizをテストするために、FableREPLである中規模のプロジェクトを使用することにしました。 Fable REPLは複雑なアプリケーションではありませんが、FableとReactの多くの機能を使用しています。
この決定のおかげで私がテストしたものの網羅的ではないリスト:
変換を開始したとき、コードのフォーマットがいかに簡単であるかを本当に嬉しく思いました。 フェリスベースのビューを書くための慣習は本当に従うのが簡単だと思います。 アプリケーションが大きくなるほど、コードのフォーマットが重要になります。
それから途中で、私は何かに悩まされ始めましたが、何を見つけることができませんでした。
Fable REPLをFelizに変換し終えましたが、それが好きかどうかはわかりませんでした。
私が自分の分析を結論付けようとしているのは今だけであり、何が私を妨げているのかを理解しています。 それはFelizとはあまり関係がありませんが、Feliz.Bulmaとはもっと関係があります。
2。5年以上の間、私はFulmaに取り組み、それを改善してきたことを覚えておくことが重要です。 フルマは私の最大のプロジェクトの1つです。 それを使ってコードを書くことは、特にすべてが入力され、コンポーネントの観点から考えることを余儀なくされるので素晴らしいです。
Feliz.Bulmaは別のアプローチを取り、Fulmaよりも若いです。 生後わずか5ヶ月です。
そうは言っても、今こそ私の結論に移る時だと思います:)
フェリスの最大の利点はシングルリストスタイルだと思います。 これは私がよく言及したことですが、コードを簡単にフォーマットでき、次の行をどこから始めるべきかを考える必要がないことは大きなプラスです。
第二に、タイプセーフAPIは必須です。 これはCSSの同等のものよりも冗長ですが、優れた機能だと思います。 私はそれで派手なことをしなかったので、すべてがサポートされているかどうかはわかりませんが、そうでない場合は、いつでもPRを作成してそれを修正できます:)。
Feliz.Bulmaは、Felizを拡張する有望な方法を示していますが、Fulmaと直接同等になるほど成熟していません。 これは私が@Dzoukrでもっと探求したいことであり、Feliz.Bulmaの単純さとFulmaの完全性と冗長性の中間点を見つけることができることを願っています。
3年前、2017年3月8日、Tomas、Eugeneと私は、Fable.ArchとElmishを統合することを決定しました。 これにより、コミュニティとして、今日の素晴らしいエコシステムを構築することができました。
私たちは現在、FelizやFable.Reactと同じような時代を生きていると思います。 フェリスは寓話よりも牽引力が上がると思います。
しかし、両方が共存します。 結局、それらの両方は一緒にうまく機能します。これは、人々が使用したいものを選択できることを意味します。
私の分析を読んでくれてありがとう、そしてコメントセクションであなたとそれについて話し合うことを嬉しく思います:)
素晴らしい分析。
個人的には、ダブルリストのフォーマットが面倒なこともありますが、Fable.Reactコードを見ると、基になるhtmlの構造がよくわかります。 div [..、Html.div [....(など)ではありません。 それは大したことではありませんが、私の脳はFable.Reactをより簡単に解析できるようです。
@MangelMaximeを書いて
私が集めたものから、これの主なポイントは、主にライブラリの拡張方法に関する問題と、最適に行われなかった場合に発生する問題です。
Feliz
ライブラリを作成すると、開発者の作業が大幅に増えることに間違いなく同意できますが、結果のAPIが非常に使いやすい場合は、努力する価値があると思います。
私はFeliz
に対してかなりの数の拡張機能を作成したので、これらの問題の多くを軽減する方法についていくつかの洞察を提供できると思います。
Visual Studioを使用していますが、使用可能なオーバーロードを見つけるのに問題はありません。これは、ionide側で改善できるものでしょうか。
prop.text
、メンバーtoString
を必要とし、任意のタイプを受け入れる単一のインライン関数にすることができますか?
それ以外の:
[<Erase>]
type editor =
/// <summary>Triggered when the Editor has been mounted</summary>
static member inline editorDidMount (f : System.Func<Monaco.Editor.IStandaloneCodeEditor, Monaco.IExports, unit>) = Interop.mkAttr "editorDidMount" f
書く:
[<Erase>]
type editor =
/// <summary>Triggered when the Editor has been mounted</summary>
static member inline editorDidMount (f : Monaco.Editor.IStandaloneCodeEditor -> Monaco.IExports -> unit) = Interop.mkAttr "editorDidMount" (Func<_,_,_> f)
その後、クライアント側で期待するようにプロパティを呼び出すことができます。
私のライブラリのいくつかで私が持っている範囲でこれを完全に適用する人を見たことがなく、 Html
拡張するときに完全に適用できるとは限りません。 これを防ぐ方法は、定義したプロパティにインターフェイスタイプを追加することです。これは、私の最大のFeliz
ライブラリFeliz.Plotly
、次の場合にコンパイラエラーが発生するように設定しています。無効なプロパティを使用してみてください。 唯一の欠点は、ライブラリ開発者にとってかなりの作業になることです。
クリックして展開
[<AutoOpen;EditorBrowsable(EditorBrowsableState.Never)>]
module Types =
type IPlotProperty = interface end
type IModeBarButtonsProperty = interface end
type IAaxisProperty = interface end
type IAggregateProperty = interface end
type IAggregationProperty = interface end
type IAggregationsProperty = interface end
type IAngularaxisProperty = interface end
type IAnimationProperty = interface end
type IAnnotationProperty = interface end
type IAnnotationsProperty = interface end
type IAreaProperty = interface end
type IAspectratioProperty = interface end
type IAxisProperty = interface end
type IBarProperty = interface end
type IBarpolarProperty = interface end
type IBaxisProperty = interface end
type IBorderProperty = interface end
type IBoxProperty = interface end
type IButtonProperty = interface end
type ICameraProperty = interface end
type ICandlestickProperty = interface end
type ICapsProperty = interface end
type ICarpetProperty = interface end
type ICaxisProperty = interface end
type ICellsProperty = interface end
type ICenterProperty = interface end
type IChoroplethProperty = interface end
type IChoroplethmapboxProperty = interface end
type ICircleProperty = interface end
type IColoraxisProperty = interface end
type IColorbarProperty = interface end
type IColorscaleProperty = interface end
type IColorscalesProperty = interface end
type IConcentrationscalesProperty = interface end
type IConeProperty = interface end
type IConfigProperty = interface end
type IConnectorProperty = interface end
type IContourProperty = interface end
type IContourcarpetProperty = interface end
type IContoursProperty = interface end
type ICumulativeProperty = interface end
type ICurrentvalueProperty = interface end
type IDecreasingProperty = interface end
type IDeltaProperty = interface end
type IDensitymapboxProperty = interface end
type IDiagonalProperty = interface end
type IDimensionProperty = interface end
type IDimensionsProperty = interface end
type IDomainProperty = interface end
type IEditsProperty = interface end
type IErrorXProperty = interface end
type IErrorYProperty = interface end
type IErrorZProperty = interface end
type IEyeProperty = interface end
type IFillProperty = interface end
type IFilterProperty = interface end
type IFontProperty = interface end
type IFrameProperty = interface end
type IFramesEntryProperty = interface end
type IFramesProperty = interface end
type IFunnelProperty = interface end
type IFunnelareaProperty = interface end
type IGaugeProperty = interface end
type IGeoProperty = interface end
type IGradientProperty = interface end
type IGridProperty = interface end
type IGroupbyProperty = interface end
type IHeaderProperty = interface end
type IHeatmapProperty = interface end
type IHeatmapglProperty = interface end
type IHistogram2dProperty = interface end
type IHistogram2dcontourProperty = interface end
type IHistogramProperty = interface end
type IHoverlabelProperty = interface end
type IImageProperty = interface end
type IImagesProperty = interface end
type IIncreasingProperty = interface end
type IIndicatorProperty = interface end
type IInsidetextfontProperty = interface end
type IIsosurfaceProperty = interface end
type ILabelfontProperty = interface end
type ILataxisProperty = interface end
type ILayerProperty = interface end
type ILayersProperty = interface end
type ILayoutProperty = interface end
type ILeafProperty = interface end
type ILegendProperty = interface end
type ILightingProperty = interface end
type ILightpositionProperty = interface end
type ILineProperty = interface end
type ILinkProperty = interface end
type ILonaxisProperty = interface end
type IMapboxProperty = interface end
type IMarginProperty = interface end
type IMarkerProperty = interface end
type IMeanlineProperty = interface end
type IMesh3dProperty = interface end
type IModebarProperty = interface end
type INodeProperty = interface end
type INumberProperty = interface end
type IOhlcProperty = interface end
type IOutsidetextfontProperty = interface end
type IPadProperty = interface end
type IParcatsProperty = interface end
type IParcoordsProperty = interface end
type IPathbarProperty = interface end
type IPieProperty = interface end
type IPointcloudProperty = interface end
type IPolarProperty = interface end
type IProjectProperty = interface end
type IProjectionProperty = interface end
type IRadialaxisProperty = interface end
type IRangebreakProperty = interface end
type IRangebreaksProperty = interface end
type IRangefontProperty = interface end
type IRangeselectorProperty = interface end
type IRangesliderProperty = interface end
type IRotationProperty = interface end
type ISankeyProperty = interface end
type IScatter3dProperty = interface end
type IScatterProperty = interface end
type IScattercarpetProperty = interface end
type IScattergeoProperty = interface end
type IScatterglProperty = interface end
type IScattermapboxProperty = interface end
type IScatterpolarProperty = interface end
type IScatterpolarglProperty = interface end
type IScatterternaryProperty = interface end
type ISceneProperty = interface end
type ISelectedProperty = interface end
type IShapeProperty = interface end
type IShapesProperty = interface end
type ISlicesProperty = interface end
type ISliderProperty = interface end
type ISlidersProperty = interface end
type ISortProperty = interface end
type ISpaceframeProperty = interface end
type ISplomProperty = interface end
type IStartsProperty = interface end
type IStepProperty = interface end
type IStepsProperty = interface end
type IStreamProperty = interface end
type IStreamtubeProperty = interface end
type IStyleProperty = interface end
type IStylesProperty = interface end
type ISunburstProperty = interface end
type ISurfaceProperty = interface end
type ISymbolProperty = interface end
type ITableProperty = interface end
type ITernaryProperty = interface end
type ITextfontProperty = interface end
type IThresholdProperty = interface end
type ITickfontProperty = interface end
type ITickformatstopProperty = interface end
type ITickformatstopsProperty = interface end
type ITilingProperty = interface end
type ITitleProperty = interface end
type ITotalsProperty = interface end
type ITracesProperty = interface end
type ITransformsProperty = interface end
type ITransitionProperty = interface end
type ITreemapProperty = interface end
type IUniformtextProperty = interface end
type IUnselectedProperty = interface end
type IUpProperty = interface end
type IUpdatemenuProperty = interface end
type IUpdatemenusProperty = interface end
type IViolinProperty = interface end
type IVolumeProperty = interface end
type IWaterfallProperty = interface end
type IXProperty = interface end
type IXaxisProperty = interface end
type IXbinsProperty = interface end
type IYProperty = interface end
type IYaxisProperty = interface end
type IYbinsProperty = interface end
type IZProperty = interface end
type IZaxisProperty = interface end
type IButtonsProperty = inherit IModeBarButtonsProperty
type IMeasureProperty = interface end
type ITemplateProperty = interface end
同様に、必要に応じて、ライブラリコードに実装して、プロパティを「自動的に」組み合わせることができます。 ただし、自分のライブラリ以外のものを使用する場合、これがどのように機能するかはわかりません。 これの秘訣は、これらのアイテムを単なるIReactProperty
は異なるタイプにすることです。 たとえば、 Feliz.Plotly
では、指定された構成に応じて、ユーザー入力を変更/収集/変更して、実際のコードが必要なものに適切に変換する多くのことを行います。 常に存在するものを削除することは、いくつかの点で本当に素晴らしいです。
あなたが抱えていた苦痛の多くは、「フェリス」の方法で独自のライブラリを作成する方法についてのより良いドキュメントで解決できると思います。 たぶん@ Zaid-Ajajと私は将来それに取り組むことができます。
ありがとう@ l3m
個人的には、ダブルリストのフォーマットが面倒なこともありますが、Fable.Reactコードを見ると、基になるhtmlの構造がよくわかります。 div [..、Html.div [....(など)ではありません。 それは大したことではありませんが、私の脳はFable.Reactをより簡単に解析できるようです。
実際、コードの読み取り方法を切り替えるのは簡単ではありません。そのため、私の場合はHTMLとして表示すべきではないと述べたので、切り替えに役立ちました。
F#5と「静的クラスを開く」機能により、Felizは、Htmlクラスを開くかどうかに応じて、 Html.div
とdiv
両方の構文をサポートできるようになると思います。
コメントをありがとう@Shmew 、そして確かに私はフェリスのための「ライブラリ」のいくつかのタイプがあることを忘れました。
「無効なコードの書き込み」についてはい。ただし、一部のライブラリでは、 Props
などの特別なヘルパーを介して標準プロパティを渡す必要があるFulmaの状況を回避するために、 IReactProperty
タイプを「拡張」する必要があります。 Props
。 その理由は、Bulmaの「コンポーネント」はDOM要素の単なる特殊化であるためです。
これらは、HTML要素にデフォルトでクラスを挿入する単なるコードです。
Bulma.button
は<div class="button">
「実際の」コンポーネントで動作するライブラリの場合(申し訳ありませんが、別の名前を付ける方法がわかりません)、ソリューションは確かに正しいものです。 たとえば、これはFable.ReactLeafletが採用したアプローチであり、各コンポーネントの特定のプロパティを定義しています。 したがって、コンポーネントはすべての標準HTMLプロパティをサポートする必要はありません。
「コールバック」の解決策については、私にはうまくいきませんでした。 しかし、Fableによって渡された関数にはカレー引数があり、 myFunction(arg1)(arg2)
ようなものを書きたくない限り、 System.Func
介してカレーなしのバージョンを強制する必要がありました。
それを機能させる方法を知っているなら、 https://github.com/fable-compiler/repl/pull/108/filesでそれを修正するためにPRが送られるのを見てうれしいです
こんにちは@MangelMaxime 、
まず第一に、プロジェクトでフェリスを試すだけでなく、そのような広範な分析を書くために時間と労力を費やしてくれてありがとう。 寓話のユーザーの多くは、それが非常に有益で有益であると感じると確信しています。
この種のフィードバックとオープン性に本当に感謝しており、このライブラリをそのエコシステムとともに可能な限り最高のものにすることが重要であると信じています:pray:
Feliz.Bulmaはエコシステムの中で特別なものだと思うので、すぐに話します。まず、ライブラリを変更せずにすでに修正できるいくつかの問題に答えます。
onChange
過負荷どのイベントタイプが必要かを明示的に指定する必要があります。
実際には、あなたはしません。 タイプは、メッセージタイプから次のように推測する必要があります。
prop.onChange (ChangeGistToken >> dispatch)
ChangeGistToken
のタイプに応じて、正しい過負荷が推測されます。 DUの場合がChangeGistToken of string
場合、 string -> unit
のオーバーロードが選択されます。 ただし、入力タイプがfile
場合はFileSelected of File
になることもあります。その場合、オーバーロードFile -> unit
が推測されます。 Fable.React
からev.Value
のシンタックスシュガーは必要ありません
onChange
はすでにブールケースを処理しているため、prop.onCheckedChangeは削除されます
@Shmewはすでにこの問題に触れており、実際、これがこれらのタイプのプロパティを解決する方法です。 Feliz拡張機能を実装する場合、プロパティを設定する前に変換を実行できることを理解することが重要です。
type myExtension =
static member inline extenstionProperty value =
// transform value here
let transformedValue = doWeirdStuffWith value
Interop.mkAttr "extenstionProperty" transformedValue
このロジックに従って、 'A -> 'B -> unit
を内部でFunc<'A, 'B, unit>
変換できます。
[<Erase>]
type editor =
/// <summary>Triggered when the Editor has been mounted</summary>
static member inline editorDidMount (f : Monaco.Editor.IStandaloneCodeEditor -> Monaco.IExports -> unit) =
let transformedFunction = System.Func<Monaco.Editor.IStandaloneCodeEditor, Monaco.IExports, unit>(fun editor exported -> f editor exported)
Interop.mkAttr "editorDidMount" transformedFunction
これは、 @ Shmewによって提供されるバージョンよりも明示的なバージョン正しく設定するには、常に少し遊んでおく必要があります)。 これの実用的な例はここにあり
@Shmewが前述したように、適切なFeliz拡張機能では、正しく動作しないコードを記述できず、プロパティのタイプを制約することでそれを実装できます。 Feliz.RechartsのようにIReactProperty
を返すプロパティを構築して、 prop
既存のプロパティとの下位互換性を確保するか、より特殊なタイプISpecialiedProperty
を実装してサポートすることができます。下位互換性を確保するために、一部のプロパティの名前をIReactProperty
から複製している間は、プロパティのサブセットのみを使用します。
type felizExtension =
static member inline specializedProp (value: string) : ISpecializedProperty = unbox (prop.text value)
これは私がFeliz.AntDesignで行っていることです。たとえば、ここではいくつかのプロパティを複製してbutton
エントリポイントから利用できるようにしています(後で、プロパティを厳密な型でより特殊化することもできますが、最初は、下位互換性は最初に開始する場所です)。 Feliz.MaterialUIは、プロパティを特殊化するのではなく、 IReactProperty
を拡張するために同様のことを行うと思います。 これはFeliz.Bulmaの場合になります。
Feliz.Bulmaが実装される前は、CSSのみのフレームワーク用にFeliz拡張機能を構築する必要はyield
を使用すると、さらに簡単になります。 これをTypedCssClassesと組み合わせると、CSSのみのフレームワークを実装する必要がなくなります。 実装とメンテナンスのコストはゼロです。 ドキュメントのWebサイトを自分で作成する代わりに、入力したスタイルシートを使用して、プロジェクト自体のすでに非常に優れたドキュメントを使用するだけです。
ただし、@ DzoukrによるFeliz.Bulmaの実装を見た後は、理に。Bulmaの1つのモジュールからCSSコンポーネントに特定の「エントリポイント」を導入して、 Bulma.button
を取得することで、コードを大幅に簡素化できます。 Bulma.card
など。これらは本当に使いやすいです。 モディファイアに関しては、Romanのアプローチは従い、操作しやすいと思いますが、あなたが言ったように、時にはそれが興味深い結果をもたらす可能性があります。 確かに、その部門にはさらに改善すべき点があります。いずれにせよ、Romanは、Felizのビジョンに従って、習得と使用が簡単なものを構築するのに素晴らしい仕事をしたと思います。
現在のFable.React
とFeliz
大きな違い、つまりパッケージのバージョン管理と管理について指摘したいと思います。 FelizバージョンはすべてのエコシステムライブラリがFemto互換であるため、必要なnpmパッケージを手動でインストールしたり、互換性のあるバージョンを知ったりする必要がなくなります。 これは、すべてではないにしても多くの派生Fable.React
ライブラリや、そうでない場合はFable.React
自体とは異なります。
実際には、あなたはしません。 タイプは、メッセージタイプから次のように推測する必要があります。
prop.onChange (ChangeGistToken >> dispatch)
確かに、私はこの使用法について考えていませんでした。
マルチ引数コールバック
@Shmewはすでにこの問題に触れており、実際、これがこれらのタイプのプロパティを解決する方法です。
申し訳ありませんが、@ Shmewによって提供されたスニペットの終わりが表示されませんでした。 私は署名宣言を見たばかりで、機能しないようでした。
あなたは両方とも正しいです、私たちは値をプロパティに渡す前に変換を行うことができます。
はい、TypedCssClassesは問題ありませんが、FulmaやFeliz.Bulmaと比較すると、同じレベルの機能を提供することはできません。 すべてがCSSファイルに含まれているわけではないからです。
もう1つは、開発モードでは、ファイルが常にディスク上に生成されるとは限らず、TypedCssClassesがこのシナリオをサポートしているかどうかがわかりません。
ローマンは、フェリスのビジョンに従って、学びやすく使いやすいものを構築するのに素晴らしい仕事をしたと思います。
私は同意します。同様にするために、Fulmaで行われた作業を少し追加する必要があると思います。 私が言ったように、私たちはそれらの両方の間の正しい中間点を見つける必要があります。
私が今考えている不足している機能は、出力要素を制御し、サポートされている色のセットを簡単に拡張できるようにすることです。 それほど複雑になるとは思いません。
@ Zaid-Ajajはフィードバックをありがとう、特にFelizの可能性を使用する方法について正しい方向を示してくれてありがとう。
私はFelizのドキュメントを実際に読んでいないことを認めます(それは私が知っているのは悪いことです)ので、おそらくそれらはそこに文書化されています。 そうでない場合は、追加する必要があることがいくつかわかっていると思います:)
@MangelMaximeに感謝しFantomasについて言及したことはありませんが、Fable.ReactまたはFelizのいずれかを使用してFantomasを操作する機会はありましたか?
Fantomasを使用しているFableプロジェクトの1つで、Ionideのファイル保存で自動フォーマットをオンにしました。これは、生産性を大幅に向上させるものであると言わなければなりません。手動フォーマットについて心配する必要はまったくありません。
Fantomasは今勢いを増しており、FableやReact / Felizと組み合わせて、より広く採用されることを望んでいます。
@theimowski私は
主な理由は、コードが混乱していて、読みづらくなったためです。 私の経験から、Fable.ReactとFelizでうまく遊んでいませんでした。
また、デフォルトのFantomasが気に入らないので、コードをインデントする方法がわかったら、後でもう一度確認する必要があります。 しかし、私がリポジトリを見たところ、コンテキストのサイズに応じてコードをフォーマットするFantomasが主な理由で、私のニーズに合うとは思いません。
たとえば、私がそのようなものを書いた場合:
type Test =
{
Prop1 : string
}
1行に収まるからといって、そのままにしてtype Test = { Prop1 : string }
ならないようにしたいと思います。
おそらくレコードは良い例ではありませんが、私が何を意味するのか理解していただければ幸いです:)
@theimowski聞いて
@MangelMaximeあなたの仕事に感謝します。 どういうわけかあなたのフルマプロジェクトは私を寓話の世界に攻撃しました。 そして、私は本当に旅を楽しんでいます。
私は単一のリストも好きですが、クラスのメンバーのオーバーライドよりもDUも好きです。 DUがオーバーライドをサポートしているかどうか疑問に思うことがあります。
私はすでにFable.Reactをたくさん使用していますが、それでも単一のリストが必要なので、演算子>を作成し、次のように使用できます。
let myView =
div </> [
Classes [ ""; ""; "" ]
Children [
...
]
]
演算子は非常にシンプルで、DUも利用できます。ここで、私の大まかな実装を確認できます: //github.com/albertwoo/Fun.LightForm/blob/master/src/Fun.LightForm.Fable/Fable.React。 Extra.fs
@ Zaid-Ajajすばらしい仕事をありがとう、私もいくつかのプロジェクトをFelizとFeliz.Materialに変換し始めました。
ありがとう!
こんにちは@MangelMaxime 、
まずはありがとうございます! 率直に言って、私が主にドッグフーディング自身のプロジェクトのために作成し、副作用として公開したライブラリを誰かがこれほど深く見るとは思っていませんでした。 「ねえ、@ Zaid-AjajがFelizをどのように設計したか、ブルマについても同じことをしよう」という最初の考えが膨らんだのはおかしい。
私はすでにFeliz.Bulma
リポジトリで新しい問題を作成しており、v2をさらに改善する方法について話し合うのが大好きです。 ほとんどの問題について合意しているようですので、 version2
ブランチを開始しても問題はありません。 また、次のメジャーリリースのZaidの計画を確認すると、最新のメジャーバージョン間でAPIを100%互換性を保つのに便利です。
とにかく、もう一度ありがとう-素晴らしい分析!
リスクのある古い議論を再開される(!申し訳ありません)私はインデントの議論に私の2セントを追加したい-これは(多かれ少なかれ)である私たちが素敵な、一貫性のインデントを許容んどの従っスタイリングとFable.Reactのために、以下のスタイル。
ただし、これが完全に当てはまらない1つの場所は、重要なスタイリングです。 しかし、私たちの経験では、これはごく少数の要素(おそらく10〜20%)しか占めていません。
div [ ] [
Hero.hero [ Hero.IsFullHeight ] [
Hero.body [ ] [
Container.container [ ] [
img [ Src "img/fable-ionide.png"
Style [ Display DisplayOptions.Block
Width "auto"
Margin "auto" ]
]
br [ ]
Heading.h3 [ Heading.Modifiers [ Modifier.TextAlignment (Screen.All, TextAlignment.Centered) ] ] [
str "Fable REPL"
]
Heading.p [ Heading.IsSubtitle
Heading.Is5
Heading.Modifiers [ Modifier.TextAlignment (Screen.All, TextAlignment.Centered) ] ] [
str "is only available on desktop"
]
]
]
]
]
また、VSCodeやRainbowBracketsなどを使用している場合は、ブラケットの過負荷を回避するのに役立ちます。
他に考慮すべきこと(おそらく私は上記でこれを見逃した)は、GiraffeViewEngineがFable.Reactスタイル、つまり要素attr-list children-listを使用していることです。したがって、2つの間を移行する人々の観点から考える必要があります。
@ Zaid-AjajはFemtoについて良い点を述べています。 これをFable.Reactスタイルのコンポーネントで実装できなかった理由はありますか、それともFemtoが結合されているFelizスタイルに固有の何かがありますか?
これをFable.Reactスタイルのコンポーネントで実装できなかった理由はありますか、それともFemtoが結合されているFelizスタイルに固有の何かがありますか?
@isaacabraham
Fable.Reactから派生したライブラリは、Femtoメタデータを追加できます(また、追加する必要があります)が、Fable.React自体は、 react
、 react-dom
、およびreact-native
互換性のない組み合わせがあるため、追加できません@MangelMaximeはパッケージの分割に関するいくつかの重大な変更が導入されるでしょう。
Fable.React
から派生したライブラリにとってこれが意味することは、依存関係のnpmメタデータだけでなく、互換性のあるバージョンのreact
とreact-dom
も含める必要があるということです。 ( react
とreact-dom
で始まるFelizとは異なり、Feliz拡張機能は必要なものだけを追加します)。 残念ながら、解決策がかなり前から存在しているとしても、これらのライブラリのいずれかが状況を改善するために主導権を握っているのを見たことがありません。
フォーマットについて:FantomasはまだDSLを適切な方法でフォーマットすることができず、リストのフォーマットを構成可能にするための作業が必要であるか、ReactDSLを適切なデフォルトを使用してフォーマットするための何らかの「Feliz-mode」フラグが必要です(と)
@ Zaid-Ajaj React npmの依存関係の問題も、Femtoを壊すことなく、reactの代わりにpreactを使用できるはずなので、より複雑です。
@ l3m確かに、しかしこの場合、このケースをサポートするためにFemtoに追加することができます。 それは私に何かを覚えているので、おそらくフェムトレポでそれについて問題があります(申し訳ありませんが今チェックする時間がありません^^)
@ l3m Preactは、Femto npmメタデータに関係なく、Reactの代わりに使用できます。既存のReactアプリケーションがある場合は、 Preactへの切り替えのガイドラインに従ってモジュールインポートエイリアスを構成するだけでよいためです。
純粋なPreactバインディング(100%非Reactコード)の構築はFelizの目標ではなく、おそらくPreactのみのバインディングが拡張されるスタンドアロンライブラリ(Feliz.PreactはFelizに依存しない)として実装する必要があります。 preact/compat
から離れたい場合に使用します
@ Zaid-Ajaj現在、Elmishアプリでpreactを使用していますが、うまく機能します。 Femtoがpackages.jsonを変更するのを警戒していたのですが、React depsのあるnugetが表示された場合は、それを強調したいと思いました。 それが問題でなければ、なおさらです。
また、 preact/compat
は、最新のpreactでは不要になり、コアになりました。
危険にさらされているのは、古い議論を再開することです(申し訳ありません!)インデントの議論に2セントを追加したかっただけです-これは(多かれ少なかれ)私たちが従うスタイリングであり、Fable.Reactの素晴らしい一貫した識別とフォローを可能にしますスタイル。
私はIsaacと非常によく似た方法でコードをインデントしており、かなり読みやすくなっています。
物事を行う単一のリストの方法と比較するのは難しいことを私は知っていますが、元の投稿のインデントは、よりよく比較するために彼のコードに似たものを反映している可能性があります。
F#5と「静的クラスを開く」機能により、Felizは、Htmlクラスを開くかどうかに応じて、
Html.div
とdiv
両方の構文をサポートできるようになると思います。
それはとてもクールだろう。 Htmlクラスを静的にして開くことができるようにすることは可能でしょうか?
@ fc1943s Html
、 prop
、およびstyle
はすべて静的クラスです。 ただし、F#5で機能が利用可能になったときにそれらを開くことはお勧めしません。これは、ポイント全体に、その静的クラス内で利用可能な関数へのグループ化と検出のエントリポイントがあるためです。
静的クラスを開くと、検出がどのように妨げられますか? それでもFeliz.Htmlと入力できます。
@MaxWilsonMS 「最終的な」コードを出力するには、追加の手順が必要でした。
そして、 Feliz.Html.div
を書き込んでから、奇妙に思えるFeliz.Html.
部分を消去します。
良い点は、ユーザーが好みに応じて静的クラスを開くかどうかを選択できることです。 :)
上で述べたことを繰り返しているので、これがどれほど役立つかはわかりませんが、完全な初心者としての経験:
インデントにはFelizアプローチが好きです。 Isaacが提案したのと同様のアプローチを試しましたが、インデントがすべて2s / 4sであるとは限らないため、「私は時々それについて考えることに時間を費やします」。 フェリスと一緒に、私はそれについて考えるのに全く時間を費やしません。
カスタム要素を作成する場合は、今のところFable.Reactの方法で作成します。 私は「フェリスの方法」で物事を構築することを検討し、すぐに逃げました(いつか再訪します!)。
ドキュメントが「これがカスタムプロパティを作成する方法です」という側面をより定期的に優先する場合、私は本当に便利だと思います。 ほんの数人の作者だけで、これらのライブラリはCSSで可能なすべてのAPIサーフェスを提供するのに苦労することがよくあることを受け入れるのは公正だと思います(たとえば)。したがって、初心者が「fontSize」を設定できないときに行き詰まった場合「em」にあるか、「grid-template-rows」が見つからないか、「Screen.All」引数を提供することが期待されているかどうかわからない-回避方法を知っていればよいでしょう。
いくつかの潜在的な懸念を削ぎ落とし始めるいくつかの「生活の質」の改善が行われる可能性があると思います...たとえば、フェリスのスタイル小道具の長い垂直リストを見ると、 style.paddingHorizontal
があるかどうか疑問に思い始めますstyle.paddingVertical
。 私は自分でヘルパーを作ることができることを理解していますが、ここは機能をリクエストする場所ではなく、標準ではないものを導入することを避けたいと思うかもしれません:)
新しいF#でHtml
静的クラスを開くというアイデアが好きです。 批判的に-私の同僚は私の肩越しにそれを理解することができるでしょう-そして私はより多くの人々を巻き込むことが重要だと思います。 悪魔の代弁者を演じるには: div
は入力に時間がかからず、それを発見する必要がある場合、これは魔法を実行しているセットアップを使用するときに私が直面するであろう課題の中で最も少ないものです。 Javascript、React、CSSなどを私から隠します。 ただし、一般的に、APIの検出可能性は優れています。
特にスタイルのトランジション/アニメーションの場合、Felizの方法は非常に理にかなっています。
より一般的でおそらく接線的:私が一貫して直面している課題は、エルミッシュの世界がどこで終わり、Reactの世界がどこから始まるのかを理解することです。 これはどちらのライブラリの問題でもありませんが、Reactについて最も曖昧な手がかりがないため、Fable.ReactまたはFelizから関数コンポーネントを取得できるという事実は私を混乱させます。 もちろん、これを学ぶことは私の責任ですが、言及する価値があると思いました。 私は現在、ElmishとReactのアプローチを組み合わせており、これによりすべてのコンポーネントが更新時に再レンダリングされると思いますが、このような完全に構築されたアプリの例は次のとおりであるため、これを回避するための「正しい」方法がわかりません。見つけにくい。 最初にJavascriptでプロダクショングレードのReactアプリを作成し、次にFable / Elmishに移行することを学ぶ必要があるという印象を受けることがありますが、それは参入障壁のかなり重要なように感じます。 免責事項:私はFelizのドキュメントをあまり読んでいませんが、それは本当に良いことです-ですから、これはおそらく私にあります!
これらのライブラリを共有してくれたすべての人に感謝します!
ご入力いただきありがとうございます@ drk-mtr!
カスタム要素を作成する場合は、今のところFable.Reactの方法で作成します。 私は「フェリスの方法」で物事を構築することを検討し、すぐに逃げました(いつか再訪します!)。
ええ、最初はかなり気が遠くなるように見えるかもしれませんが、慣れればかなり簡単です。 そうは言っても、ライブラリを作成するときの開発者にとってはかなりの初期費用です。 大多数のユーザーがライブラリを作成することはないので、これはかなり許容できるトレードオフだと思います。 幸いなことに、作業自体は非常に単純であり、コピーと貼り付けを行うと、多くの作業を高速化できます(または、私たちのように、コードをビルドするためのジェネレーターを作成することもできます)。
ドキュメントが「これがカスタムプロパティを作成する方法です」という側面をより定期的に優先する場合、私は本当に便利だと思います。 ほんの数人の作者だけで、これらのライブラリはCSSで可能なすべてのAPIサーフェスを提供するのに苦労することがよくあることを受け入れるのは公正だと思います(たとえば)。したがって、初心者が「fontSize」を設定できないときに行き詰まった場合「em」にあるか、「grid-template-rows」が見つからないか、「Screen.All」引数を提供することが期待されているかどうかわからない-回避方法を知っていればよいでしょう。
あなたが気付いていない場合に備えて(私はこの文脈からは完全にはわかりませんでした):
prop
style
タイプとcustom
メソッドがあります。
ICssUnit
を受け入れるものはすべて、次のように設定できます: style.fontSize (length.em 1)
ドキュメントの更新は簡単なはずです。
いくつかの潜在的な懸念を削ぎ落とし始めるいくつかの「生活の質」の改善が行われる可能性があると思います...たとえば、フェリスのスタイル小道具の長い垂直リストを見ると、style.paddingHorizontalとstyle.paddingVertical。 私は自分でヘルパーを作ることができることを理解していますが、ここは機能をリクエストする場所ではなく、標準ではないものを導入することを避けたいと思うかもしれません:)
私の本では、ユーザーエクスペリエンスを容易にするのに役立つものは何でも大歓迎です。 私はあなたが気づいたこれらの事柄のいずれかの問題/広報を見たいです!
より一般的でおそらく接線的:私が一貫して直面している課題は、エルミッシュの世界がどこで終わり、Reactの世界がどこから始まるのかを理解することです。 これはどちらのライブラリの問題でもありませんが、Reactについて最も曖昧な手がかりがないため、Fable.ReactまたはFelizから関数コンポーネントを取得できるという事実は私を混乱させます。 もちろん、これを学ぶことは私の責任ですが、言及する価値があると思いました。 私は現在、ElmishとReactのアプローチを組み合わせており、これによりすべてのコンポーネントが更新時に再レンダリングされると思いますが、このような完全に構築されたアプリの例は次のとおりであるため、これを回避するための「正しい」方法がわかりません。見つけにくい。 最初にJavascriptでプロダクショングレードのReactアプリを作成し、次にFable / Elmishに移行することを学ぶ必要があるという印象を受けることがありますが、それは参入障壁のかなり重要なように感じます。 免責事項:私はFelizのドキュメントをあまり読んでいませんが、それは本当に良いことです-ですから、これはおそらく私にあります!
寓話の世界(フェリス以前)での私の経験では、ほとんどの場合、すべてを通常の関数として記述していました(.fsごとに1つのコンポーネントのように)。 その結果、Reactシステムが提供する多くのメリットを失いました。 Felizから始めてから、Reactがどのように機能するかについてもっと深く掘り下げなければなりませんでした(良いことです)。 慣れてきたので、意識的に考えることすらありません。 レンダリングを行う私が作成するすべての関数は、関数コンポーネントです。
Reactを慣用的に書く方法を本当に学びたいのなら、Elmishを使用せず、デモアプリで関数コンポーネント/フックのみを使用するように制限するのと同じくらい簡単だと思います。 APIはほぼ同じであるため、JSで記述されたものを簡単にフォローできます。
Felizで書かれた高品質のオープンソースアプリケーションを持つことは間違いなく有益なことです。私はしばらく前にその問題を作成しました#67。 現在最も近いのは、おそらくドキュメントアプリ自体、または@cmeerenのElectronDemoです。
最も参考になるコメント
こんにちは@MangelMaxime 、
まず第一に、プロジェクトでフェリスを試すだけでなく、そのような広範な分析を書くために時間と労力を費やしてくれてありがとう。 寓話のユーザーの多くは、それが非常に有益で有益であると感じると確信しています。
この種のフィードバックとオープン性に本当に感謝しており、このライブラリをそのエコシステムとともに可能な限り最高のものにすることが重要であると信じています:pray:
Feliz.Bulmaはエコシステムの中で特別なものだと思うので、すぐに話します。まず、ライブラリを変更せずにすでに修正できるいくつかの問題に答えます。
onChange
過負荷実際には、あなたはしません。 タイプは、メッセージタイプから次のように推測する必要があります。
ChangeGistToken
のタイプに応じて、正しい過負荷が推測されます。 DUの場合がChangeGistToken of string
場合、string -> unit
のオーバーロードが選択されます。 ただし、入力タイプがfile
場合はFileSelected of File
になることもあります。その場合、オーバーロードFile -> unit
が推測されます。Fable.React
からev.Value
のシンタックスシュガーは必要ありませんマルチ引数コールバック
@Shmewはすでにこの問題に触れており、実際、これがこれらのタイプのプロパティを解決する方法です。 Feliz拡張機能を実装する場合、プロパティを設定する前に変換を実行できることを理解することが重要です。
このロジックに従って、
'A -> 'B -> unit
を内部でFunc<'A, 'B, unit>
変換できます。これは、 @ Shmewによって提供されるバージョンよりも明示的なバージョン正しく設定するには、常に少し遊んでおく必要があります)。 これの実用的な例はここにあり
フェリスエコシステムにおける型安全性
@Shmewが前述したように、適切なFeliz拡張機能では、正しく動作しないコードを記述できず、プロパティのタイプを制約することでそれを実装できます。 Feliz.Rechartsのように
IReactProperty
を返すプロパティを構築して、prop
既存のプロパティとの下位互換性を確保するか、より特殊なタイプISpecialiedProperty
を実装してサポートすることができます。下位互換性を確保するために、一部のプロパティの名前をIReactProperty
から複製している間は、プロパティのサブセットのみを使用します。これは私がFeliz.AntDesignで行っていることです。たとえば、ここではいくつかのプロパティを複製して
button
エントリポイントから利用できるようにしています(後で、プロパティを厳密な型でより特殊化することもできますが、最初は、下位互換性は最初に開始する場所です)。 Feliz.MaterialUIは、プロパティを特殊化するのではなく、IReactProperty
を拡張するために同様のことを行うと思います。 これはFeliz.Bulmaの場合になります。Feliz.Bulmaの場合
Feliz.Bulmaが実装される前は、CSSのみのフレームワーク用にFeliz拡張機能を構築する必要は
yield
を使用すると、さらに簡単になります。 これをTypedCssClassesと組み合わせると、CSSのみのフレームワークを実装する必要がなくなります。 実装とメンテナンスのコストはゼロです。 ドキュメントのWebサイトを自分で作成する代わりに、入力したスタイルシートを使用して、プロジェクト自体のすでに非常に優れたドキュメントを使用するだけです。ただし、@ DzoukrによるFeliz.Bulmaの実装を見た後は、理に。Bulmaの1つのモジュールからCSSコンポーネントに特定の「エントリポイント」を導入して、
Bulma.button
を取得することで、コードを大幅に簡素化できます。Bulma.card
など。これらは本当に使いやすいです。 モディファイアに関しては、Romanのアプローチは従い、操作しやすいと思いますが、あなたが言ったように、時にはそれが興味深い結果をもたらす可能性があります。 確かに、その部門にはさらに改善すべき点があります。いずれにせよ、Romanは、Felizのビジョンに従って、習得と使用が簡単なものを構築するのに素晴らしい仕事をしたと思います。フェリスのパッケージ管理
現在の
Fable.React
とFeliz
大きな違い、つまりパッケージのバージョン管理と管理について指摘したいと思います。 FelizバージョンはすべてのエコシステムライブラリがFemto互換であるため、必要なnpmパッケージを手動でインストールしたり、互換性のあるバージョンを知ったりする必要がなくなります。 これは、すべてではないにしても多くの派生Fable.React
ライブラリや、そうでない場合はFable.React
自体とは異なります。今後の計画