如何在寓言中切换显示/隐藏元素?

psf*_*aki 0 html f# togglebutton fable-f#

我希望在寓言中有一个简单的显示/隐藏内容行为.像这样的东西.

function myFunction() {
  var x = document.getElementById("myDIV");
  if (x.style.display === "none") {
    x.style.display = "block";
  } else {
    x.style.display = "none";
  }
}
Run Code Online (Sandbox Code Playgroud)
<button onclick="myFunction()">Click Me</button>

<div id="myDIV">
  This is my DIV element.
</div>
Run Code Online (Sandbox Code Playgroud)

最合适的方法是什么?

rmu*_*unn 5

这是一个比你意识到的更大的问题,因为在它下面是"我应该如何最好地安排我的寓言应用程序"的问题?您在答案中采用的方法与在Javascript应用程序中使用JQuery大致相同:您编写的代码直接操作DOM以实现您想要的结果.如果这是你选择的建筑风格 - 对于非常简单的应用程序,它是一个非常好的选择 - 那么你的答案就无法改善.唯一一次"直接操纵DOM"方法会遇到问题,如果你的应用程序增长到大于平凡的大小.那时,你会想要一个更好的架构.我马上就会推荐一个更好的架构,但首先,我建议你对代码进行一些小调整.将toggle功能移到外面toggleButton会使它更加通用:

module Markup

open System
open Fable.Helpers.React
open Fable.Helpers.React.Props
open Fable.Import

let toggleBlockElem id _ = 
    let contentElement = Browser.document.getElementById id
    let display = if contentElement.style.display = "none" then "block" else "none"
    contentElement.style.display <- display

let toggleButton text content =
    let id = Guid.NewGuid().ToString()

    div [] 
        [
            button [ OnClick (toggleBlockElem id) ] [ str text ]
            div [ Id id ] [ str content ]
        ]
Run Code Online (Sandbox Code Playgroud)

这允许您在函数中重用此函数,toggleLink或者toggleCheckbox如果您发现自己需要这些函数.

现在,我之前提到如果你的网络应用程序变大,我会推荐一个不同的架构.我推荐的建筑是Elmish.它基于Elm中使用的架构; 如果你不熟悉它,基本的想法类似于React.它是一个模型/更新/视图架构.该模型是一个不可变的数据结构.还定义了一种消息类型; 在Elmish,这可能是一个F#歧视联盟.该更新功能需要一个模型和消息作为它的两个参数,并返回一个新的模式.该视图功能需要一个模型和一个" 调度 "功能作为它的两个参数(以下简称"调度"功能将被Elmish提供,你不必把它写),并返回HTML类元素的抽象树.Elmish然后将这些元素传递给像React这样的东西来进行实际的DOM更新.(根据一个类似于Elm 所描述的过程,React将基本上区分"旧"DOM树和"新"DOM树).

所有这一切都需要考虑,所以让我们看一个简单的例子,它只是切换a的可见性div.注意:我没有对此进行测试,只需将其输入Stack Overflow应答框即可.下面的代码中可能存在错误; 它旨在作为说明性示例而非工作示例.(有关Elmish行动的非常详尽的工作示例,请参阅https://mangelmaxime.github.io/fulma-demo/ - 但请注意,该示例具有高级架构,其中包含数据中父子层次结构的多个"层"模型,乍一看可能很难绕过你的脑海.)

让我们从定义您的数据模型开始.由于这是一个微不足道的例子,该模型同样微不足道; 事实上,我将要添加一些额外的数据,以便使用记录类型而不是单个bool实际上是有意义的:

type Model = { Visible: bool;
               DataNotAppearingInThisFilm: int }
Run Code Online (Sandbox Code Playgroud)

(更高级的模型可能涉及一种Map<string, bool>类型来跟踪多个divs 的可见状态).

消息类型也很简单,所以为了使它有点有趣,我们将允许"显示","隐藏" "切换"消息:

type Msg =
    | Show
    | Hide
    | Toggle
Run Code Online (Sandbox Code Playgroud)

(更高级的版本将Show of string等,传递div的ID以显示).

update功能也同样简单:

let update msg model =
    match msg with
    | Show -> { model with Visible = true }
    | Hide -> { model with Visible = false }
    | Toggle -> { model with Visible = not model.Visible }
Run Code Online (Sandbox Code Playgroud)

最后,view函数看起来像这样:

let view model dispatch =
    div [] 
        [
            button [ OnClick (fun _ -> dispatch Toggle) ] [ str (if model.Visible then "Hide" else "Show") ]
            div [ Display (if model.Visible then "block" else "none") ] [ str "content" ]
        ]
Run Code Online (Sandbox Code Playgroud)

或者,拉出toggleButton自己的功能,这样我就可以展示它是如何工作的:

let toggleButton dispatch text content =
    div [] 
        [
            button [ OnClick (fun _ -> dispatch Toggle) ] [ str text ]
            div [ Display (if model.Visible then "block" else "none") ] [ str content ]
        ]

let view model dispatch =
    div []
        [
            str "Other elements might go here"
            toggleButton dispatch (if model.Visible then "Hide" else "Show") "content"
        ]
Run Code Online (Sandbox Code Playgroud)

注意我需要将dispatch函数作为参数传递给toggleButton,以便toggleButton能够为其构造正确的行为OnClick.

把所有这些放在一起看起来像这样:

open ALotOfModules

type Model = { Visible: bool;
               DataNotAppearingInThisFilm: int }

type Msg =
    | Show
    | Hide
    | Toggle

let update msg model =
    match msg with
    | Show -> { model with Visible = true }
    | Hide -> { model with Visible = false }
    | Toggle -> { model with Visible = not model.Visible }

let toggleButton dispatch text content =
    div [] 
        [
            button [ OnClick (fun _ -> dispatch Toggle) ] [ str text ]
            div [ Display (if model.Visible then "block" else "none") ] [ str content ]
        ]

let view model dispatch =
    div []
        [
            str "Other elements might go here"
            toggleButton dispatch (if model.Visible then "Hide" else "Show") "content"
        ]
Run Code Online (Sandbox Code Playgroud)