Как включить / отключить отображение элемента в Fable? - PullRequest
0 голосов
/ 25 декабря 2018

Я хочу иметь тривиальное отображение / скрытие поведения контента в Fable.Нечто подобное это .

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

<div id="myDIV">
  This is my DIV element.
</div>

Какой самый подходящий способ сделать это?

Ответы [ 2 ]

0 голосов
/ 26 декабря 2018

Это гораздо больший вопрос, чем вы думаете, потому что под ним стоит вопрос «как мне лучше организовать мое приложение Fable»?Подход, использованный вами в ответе, примерно параллелен использованию JQuery в приложении Javascript: вы пишете код, который напрямую манипулирует 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 ]
        ]

Это позволит вам повторно использовать эту функцию в таких функциях, как toggleLink или toggleCheckbox, если вы нуждаетесь в них.

Теперь я упоминал ранее, что рекомендую другую архитектуру, если ваше веб-приложение станет большим.Я рекомендую архитектуру Elmish .Он основан на архитектуре, используемой в Elm ;если вы не знакомы с ним, основная идея похожа на React.Это модель / обновление / просмотр архитектуры.Модель является неизменной структурой данных.Также определен тип сообщения ;в Elmish это, вероятно, дискриминационный союз F #.Функция update принимает модель и сообщение в качестве двух параметров и возвращает новую модель.Функция view принимает модель и функцию " dispatch " в качестве двух параметров (функция "dispatch" будет предоставлена ​​Elmish, вам не нужно ее писать) ивозвращает абстрактное дерево HTML-подобных элементов.Затем Elmish передает эти элементы чему-то вроде React для фактического обновления DOM.(Реакция, по сути, будет отличать «старое» дерево DOM и «новое» дерево DOM, в соответствии с процессом, очень похожим на описанный здесь для Elm).

Все, что естьнемного много, чтобы принять, поэтому давайте посмотрим на простой пример, который просто переключает видимость div. ВНИМАНИЕ: Я не проверял это, просто набрал его в поле ответа переполнения стека.Там могут быть ошибки в коде ниже;это предназначено как иллюстративный пример, а не рабочий пример.(ОЧЕНЬ подробный рабочий пример Elmish в действии см. https://mangelmaxime.github.io/fulma-demo/ - хотя обратите внимание, что этот пример имеет продвинутую архитектуру, включающую несколько «слоев» иерархии родитель-потомок в модели данных, и его может быть сложно обернутьс первого взгляда).

Начнем с определения модели данных.Поскольку это тривиальный пример, модель аналогично тривиальна;на самом деле настолько тривиально, что я собираюсь добавить к нему некоторые дополнительные данные, чтобы иметь смысл использовать тип записи вместо одного bool:

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

(более продвинутая модель можетзадействовать тип Map<string, bool> для отслеживания видимого состояния нескольких div с.

Тип сообщения также тривиален, поэтому, чтобы сделать его немного интереснее, мы разрешим "Показать", «Hide» и «Toggle» сообщения:

type Msg =
    | Show
    | Hide
    | Toggle

(более продвинутая версия будет Show of string и т. Д. С передачей идентификатора div для отображения).

Функция 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 }

Наконец, функция 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" ]
        ]

Или потянув 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"
        ]

Обратите внимание, как мне нужно было передать функцию 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"
        ]
0 голосов
/ 25 декабря 2018

Моя лучшая попытка - тупо перевести JavaScript по ссылке в вопросе:

module Markup

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

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

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

    div [] 
        [
            button [ OnClick toggle ] [ str text ]
            div [ Id id ] [ str content ]
        ]

Используется как Markup.toggleButton "title" "a lot of content"

...