Feliz: رأيك في فكرة v2؟

تم إنشاؤها على ١٧ مارس ٢٠٢١  ·  9تعليقات  ·  مصدر: Zaid-Ajaj/Feliz

مرحبا يا صديقي،
باعتباري مستخدمًا يوميًا لـ Feliz (وفيليز بولما بالفعل) ، فأنا دائمًا أعاني من تداخل prop.children مما يجعله أقبح إلى حد ما بالنسبة لي. أود أن أعرف رأيك في اقتراح v2 حيث سيكون لدينا:

Html.div [
    prop.className "myClass"
    Html.div "Nested"
]

ربما شيء من هذا القبيل ليس من الممكن حتى، لكنني رأيتalfonsogarciacaro الصورة العمل على Feliz.Engine ويبدو ذلك مغريا لالدعائم والأطفال على نفس المستوى. 😄

discussion

التعليق الأكثر فائدة

التماس لتغيير العنوان للإشارة إلى موضوع المناقشة؟ 😆

Dzoukr كانت هناك مناقشات سابقة حول هذا - أنا بالتأكيد في

وظائف المساعد ليست مثالية لأنها تعيد صياغة القائمة المزدوجة المحرجة ، مما يلغي بشكل أساسي إحدى الفوائد الرئيسية لهذا lib في المقام الأول ، ولا تساعد في استخدام الدعامة الحقيقي الذي هو أكثر بكثير من مجرد فئة div +.

@ Zaid-Ajaj هل تنفتح على مساحة اسم بديلة لاستكشاف هذه المنطقة؟ مثل فيليز التجريبية أو شيء من هذا القبيل؟ لذا ، فإن مساحة اسم فيليز الرئيسية تحافظ على هدف الطبقة الرقيقة فوق React بينما يمكن للبديل تجربة نهج أكثر إصرارًا.

على أي حال ، أحب شيئًا كهذا للحفاظ على تجميع العناصر:

Html.div [
    props [
        prop.className "myClass"
    ]
    Html.div "Nested"
]

يبدو تداخل العناصر أنظف من تداخل العناصر نظرًا لأن الدعائم لا تخضع للتداخل اللانهائي بالطريقة التي تكون بها العناصر. ستشترك الحاوية props في واجهة مع العناصر Html.* ، مع تصميم كلاهما كعناصر فرعية صالحة للعنصر المحتوي.

سيكون الأداء شيئًا يجب مراقبته ولكن لا أعتقد أن التأثير معروف دون محاولة. من يدري ، ربما يبدو العمل الإضافي مخيفًا فقط ولكنه يتبين أنه غير مهم من الناحية العملية بالنسبة إلى كل شيء آخر يحدث عند التصيير.

ال 9 كومينتر

ستؤدي إضافة هذا النوع من الدعم إلى جعل الاستدلال النوعي أكثر تساهلاً (حتى أنني أقول عديم الفائدة) لأنه بعد ذلك سيكون لدينا Attribute = Properties = ReactElement . في الأساس ، سيتم قبول كل شيء على أنه نفس النوع ...

أيضًا ، لجعل ذلك ممكنًا ، سنحتاج إلى إضافة طبقة إضافية أعلى React لفصل السمات عن العناصر الفرعية "يدويًا" مما سيؤثر على الأداء حيث سيكون لدينا دائمًا خطوات إضافية مطلوبة. سيؤدي هذا أيضًا إلى زيادة حجم الحزمة من أجل تخزين المعلومات اللازمة لإجراء الفصل.

أنا شخصياً لست مع هذه الميزة.

لدي مشاعر مختلطة حول هذا النهج ، ويرجع ذلك أساسًا إلى زيادة وقت التشغيل الذي يضيفه إلى العرض. كما أنني أفضل الاحتفاظ بفكرة ReactElement منفصلة عن ReactAttribute . لذلك أنا شخصياً أفضل واجهة برمجة التطبيقات الحالية أكثر من ذلك بكثير.

في تجربتي ، سمعت عن هذه المشكلة من المستخدمين كثيرًا ولكن _ فقط_ في سياق div مع اسم الفصل والأطفال. التي كانت ردي المعتاد عليها هي كتابة دالة مساعدة صغيرة تتيح لك كتابة شيء كهذا أو ما شابه

div [ "myClass" ] [
  Html.div "nested"
]

يبدو لي أنه لا يوجد سبب لعدم كتابة طرق الامتداد الخاصة بك إذا كانت تتناسب بشكل أفضل مع تأثير تطبيق الفئات أو الخصائص الأخرى المستخدمة بشكل متكرر كما فعلت هنا مع واجهة المستخدم المادية. التركيب سهل للغاية مع F # دون مزيد من إرباك المترجم أو تقليل أمان النوع.

[<AutoOpen>]
module MuiExtensions

open Feliz
open Feliz.MaterialUI

type Mui 
    with
    static member gridItem (children:seq<ReactElement>):ReactElement = 
        Mui.grid [
            grid.item true
            grid.children children
        ]

    static member gridItem (props:seq<IReactProperty>):ReactElement = 
        Mui.grid [
            grid.item true
            yield! props
        ]

شكرا لجميع الآراء ، أردت فقط تدفق المناقشة. 👍 لدي أيضًا مساعدين خاصين بي مثل divClassed "myClass" [ children ] أو نحو ذلك ، لكنني أردت معرفة وجهة نظر الآخرين.

يجب أن يكون هذا ممكنًا بالفعل مع الاحتفاظ بقيود النوع إذا قمنا بتغيير عناصر React من كونها قائمة إلى كونها تعبيرات حسابية:

div {
    className "myClass"

    div { ... }
}

سيزيد تطبيق CE من حجم قاعدة الكود ، وبالتأكيد سيجعل من الصعب صيانته ، والتعامل مع بعض الأشياء مثل العناصر الأولية عند تعريف الدعائم أمر صعب بعض الشيء / يجب أن يفشل في الترجمة وليس أثناء التطوير كما هو الحال الآن:

// Would probably need to make the base builder generic so we can use a type restriction and define this DU for
// each element so we can properly restrict what types are valid as primatives
type ReactBuilderChild =
    | Child of ReactElement
    | Children of ReactElement list
    | Float of float
    | Int of int
    | String of string
    | None

    member this.GetChildren () =
        match this with
        | ReactBuilderChild.Children children -> children
        | _ -> failwith "Cannot combine children with primitive values."

type ReactBuilderState =
    { Children: ReactElement list
      Props: IReactProperty list } 

[<AbstractClass;NoEquality;NoComparison>]
type ReactBuilder () =
    [<EditorBrowsable(EditorBrowsableState.Never)>]
    member _.Yield (x: ReactElement) = { Children = ReactBuilderChild.Child x; Props = [] }
    [<EditorBrowsable(EditorBrowsableState.Never)>]
    member _.Yield (x: ReactElement list) = { Children = ReactBuilderChild.Children x; Props = [] }
    [<EditorBrowsable(EditorBrowsableState.Never)>]
    member _.Yield (x: float) = { Children = ReactBuilderChild.Float x; Props = [] }
    ...
    [<EditorBrowsable(EditorBrowsableState.Never)>]
    member _.Yield (x: unit) = { Children = ReactBuilderChild.None; Props = [] }

    [<EditorBrowsable(EditorBrowsableState.Never)>]
    member _.Combine (state: ReactBuilderState, x: ReactBuilderState) = 
        { Children = (state.Children.GetChildren()) @ (x.Children.GetChildren()); Props = state.Props @ x.Props }

    [<EditorBrowsable(EditorBrowsableState.Never)>]
    member _.Zero () = { Children = ReactBuilderChild.None; Props = [] }

    [<EditorBrowsable(EditorBrowsableState.Never)>]
    member this.For (state: ReactBuilderState, f: unit -> ReactBuilderState) = this.Combine(state, f())

    [<CustomOperation("className")>]
    member _.className (state: ReactBuilderState, value: string) =
        { state with Props = (Interop.mkAttr "className" value)::state.Props }

    [<CustomOperation("children")>]
    member _.children (state: ReactBuilderState, value: ReactElement list) =
        { state with Children = state.Children @ value }

    abstract Run : ReactBuilderState -> ReactElement

[<NoEquality;NoComparison>]
type DivBuilder () =
    inherit ReactBuilder()

    [<EditorBrowsable(EditorBrowsableState.Never)>]
    member _.Run (state: ReactBuilderState) = 
        match state with
        | { Children = ReactBuilderChild.None; Props = props } -> Interop.createElement "div" props
        | { Children = ReactBuilderChild.Children children } -> Interop.reactElementWithChildren "div" children
        | { Children = ReactBuilderChild.Float f } -> Interop.reactElementWithChild "div" f
        | _ -> ...

let div = DivBuilder()

ما لست متأكدًا منه ، هو كيفية جعل Fable يجمع بشكل صحيح أي / كل أنابيب السباكة CE ، بالإضافة إلى جعل العمليات قابلة للاكتشاف (كما هو الحال حاليًا مع النوع prop ).

التماس لتغيير العنوان للإشارة إلى موضوع المناقشة؟ 😆

Dzoukr كانت هناك مناقشات سابقة حول هذا - أنا بالتأكيد في

وظائف المساعد ليست مثالية لأنها تعيد صياغة القائمة المزدوجة المحرجة ، مما يلغي بشكل أساسي إحدى الفوائد الرئيسية لهذا lib في المقام الأول ، ولا تساعد في استخدام الدعامة الحقيقي الذي هو أكثر بكثير من مجرد فئة div +.

@ Zaid-Ajaj هل تنفتح على مساحة اسم بديلة لاستكشاف هذه المنطقة؟ مثل فيليز التجريبية أو شيء من هذا القبيل؟ لذا ، فإن مساحة اسم فيليز الرئيسية تحافظ على هدف الطبقة الرقيقة فوق React بينما يمكن للبديل تجربة نهج أكثر إصرارًا.

على أي حال ، أحب شيئًا كهذا للحفاظ على تجميع العناصر:

Html.div [
    props [
        prop.className "myClass"
    ]
    Html.div "Nested"
]

يبدو تداخل العناصر أنظف من تداخل العناصر نظرًا لأن الدعائم لا تخضع للتداخل اللانهائي بالطريقة التي تكون بها العناصر. ستشترك الحاوية props في واجهة مع العناصر Html.* ، مع تصميم كلاهما كعناصر فرعية صالحة للعنصر المحتوي.

سيكون الأداء شيئًا يجب مراقبته ولكن لا أعتقد أن التأثير معروف دون محاولة. من يدري ، ربما يبدو العمل الإضافي مخيفًا فقط ولكنه يتبين أنه غير مهم من الناحية العملية بالنسبة إلى كل شيء آخر يحدث عند التصيير.

zanaptak أنا أحب هذه الفكرة تمامًا لأنه كما قلت ، لا تميل الدعائم إلى التعشيش بعمق مثل الأطفال.


حول موضوع المساعدين وبناء جملة القائمة المزدوجة

لا يساعدون في استخدام الدعامة الحقيقي الذي هو أكثر بكثير من مجرد فئة div +

let inline withProps elementFunction props (children: #seq<ReactElement>) =
    (prop.children (children :> ReactElement seq))
    :: props
    |> elementFunction

let myDiv = withProps Html.div

myDiv [ prop.className "myClass" ] [
    Html.div "Nested"
]

يمكنك حتى تحديد عامل لاستخدام "القائمة المزدوجة" - مثل بناء الجملة مع أي عنصر إذا كنت تريد:

let inline (@+) elementFunction props =
    fun children -> withProps elementFunction props children

let inline (@++) elementFunction prop =
    fun children -> withProps elementFunction [ prop ] children

Html.div @+ [ prop.className "myClass" ]
<| [ Html.div "nested" ]

Html.div @++ prop.className "myClass"
<| [ Html.div "nested" ]

هذا موضوع صعب لأن ما "يبدو أفضل" يمكن أن يكون ذاتيًا. ربما يكون الشيء الأكثر أهمية هو تجنب تغيير التغييرات ، ولكن إذا كنت ترغب فقط في التجربة ، يمكنك استخدام Feliz.Engine لذلك ، لأنه من السهل جدًا تكييفه مع React. كما هو مذكور في أعداد أخرى ، لا أريد نشر Feliz.Engine.React لأنه سيكون مربكًا أن يكون لديك حزمتان "متنافستان" متشابهتان. لكن على سبيل المثال ، إذا كنت ترغب في الحصول على كل شيء على نفس المستوى ، فأنت تحتاج فقط إلى وحدة مثل هذه (سيكون من السهل تكييفها مع وجود الدعائم في قائمة منفصلة أيضًا):

// Dependencies:
// - Fable.React
// - Feliz.Engine.Event dependencies

open Fable.Core
open Fable.Core.JsInterop
open Feliz
open Fable.React

type Node =
    | El of ReactElement
    | Style of string * string
    | Prop of string * obj
    member this.AsReactEl =
        match this with
        | El el -> el
        | _ -> failwith "not an element"

let private makeNode tag nodes =
    let props = obj()
    let style = obj()
    let children = ResizeArray()
    nodes |> Seq.iter (function
        | El el -> children.Add(el)
        | Style(k, v) -> style?(k) <- v
        | Prop(k, v) -> props?(k) <- v
    )
    if JS.Constructors.Object.keys(style).Count > 0 then
        props?style <- style
    ReactBindings.React.createElement(tag, props, children) |> El

let Html = HtmlEngine(makeNode, str >> El, fun () -> El nothing)

let Svg = SvgEngine(makeNode, str >> El, fun () -> El nothing)

let prop = AttrEngine((fun k v -> Prop(k, v)), (fun k v -> Prop(k, v)))

let style = CssEngine(fun k v -> Style(k, v))

let ev = EventEngine(fun k f -> Prop("on" + k.[0].ToString().ToUpper() + k.[1..], f))

اختبار:

let myEl = // Node
    Html.div [
        prop.className "myClass"
        Html.div "Nested"
    ]

let myElAsReactEl = myEl.AsReactEl // ReactElement 

وظائف المساعد ليست مثالية لأنها تعيد صياغة القائمة المزدوجة المحرجة.

لا تحتاج وظائف مساعد zanaptak إلى أخذ قائمتين كمدخلات ، div [ "class" ] [ ] كان مجرد مثال على سيناريو شائع حدث لأخذ قائمتين. يمكن أن تكون هذه الوظائف مكونات تجعل العرض أكثر بساطة

Todo.List [ for item in items -> Todo.Item item ]

على الرغم من أنه يمكنك من الناحية الفنية إجراء تداخل غير محدود في القوائم ، إلا أن هذه ليست الفكرة. يوجد توازن هناك باستخدام وظائف أو مكونات أصغر في رمز واجهة المستخدم الأكبر.

ومع ذلك ، من الناحية المثالية ، لن تحتاج إلى تفكيك الكود كثيرًا ويجب أن تكون الوظيفة الواحدة قابلة للقراءة قدر الإمكان لأن التفكير في تنظيم الأشياء يزيل التدفق أحيانًا. كانت هذه هي مشكلة DSL الخاصة بـ Fable. رد حيث كان عليك التفكير في كيفية تنسيق الأشياء في كل مرة. يصلح فيليز ذلك بتكلفة مستويين من التداخل children .

لأكون صادقًا ، لا أعرف ما هو الحل الفضي. مثل alfonsogarciacaro قال

هذا موضوع صعب لأن ما "يبدو أفضل" يمكن أن يكون ذاتيًا

حول موضوع التجارب:

هل ستكون منفتحًا على مساحة اسم بديلة لاستكشاف هذه المنطقة؟ مثل فيليز التجريبية أو شيء من هذا القبيل؟ لذا ، فإن مساحة اسم فيليز الرئيسية تحافظ على هدف الطبقة الرقيقة فوق React بينما يمكن للبديل تجربة نهج أكثر إصرارًا.

في هذا الوقت ، لا توجد خطط للحفاظ على DSLs مختلفة في مشروع Feliz. إنني محدود للغاية فيما يتعلق بوقت / سعة برمجيات المصدر المفتوح وآمل أن أوجه الجهود نحو تحسين النهج الحالي: التوثيق ، والعينات ، والمزيد من مكتبات النظام البيئي التي تم اختبارها جيدًا.

ومع ذلك ، لا تتردد في تجربة Feliz.Engine بواسطة alfonsogarciacaro واستخدم DSL الذي يناسبك بشكل أفضل.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

alfonsogarciacaro picture alfonsogarciacaro  ·  11تعليقات

Zaid-Ajaj picture Zaid-Ajaj  ·  8تعليقات

heimeshoff picture heimeshoff  ·  6تعليقات

theimowski picture theimowski  ·  13تعليقات

cmeeren picture cmeeren  ·  13تعليقات