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)
最合适的方法是什么?
这是一个比你意识到的更大的问题,因为在它下面是"我应该如何最好地安排我的寓言应用程序"的问题?您在答案中采用的方法与在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)