Сайтлеты WebSharper: создание двухстраничного вебсайта

Original author: Anton Tayanovskyy
  • Translation
Позвольте показать вам простейший законченный пример использующий сайтлеты WebSharperа, которые будут в релизе 2.1.

Определим вебсайт из двух страниц (и двух действий):
type Action =
    | Home
    | AboutUs


view raw SiteletExample1.fs This Gist brought to you by GitHub.
Теперь давайте смешаем (mash up) шаблон для вебсайта, используя встроенные в F# комбинаторы HTML. Шаблон – это просто функция получающая тело и декорирующая его:

module View =

    let ( => ) a b =
        A [HRef b] -< [Text a]

    let Page title body =
        PageContent <| fun ctx ->
            {
                Page.Default with
                    Title   = Some title
                    Body    =
                        H1 [Text title]
                        ::
                        UL [
                            LI ["Home"    => ctx.Link Home]
                            LI ["AboutUs" => ctx.Link AboutUs]
                        ]
                        ::
                        body
            }


Надо отметить две вещи:
  1. F# позволяет определять ваш собственный синтаксис и пример свободно это использует (=>).
  2. Вместо ручного генерирования URLов, вы просите контекст создать ссылку на действие. Это обеспечивает безопасность: если переименовать действие Home, то проект перестанет компилироваться; если переместить его на другой URL, ссылки останутся корректными.

Теперь определим сайтлеты:
module Site =

    let HomePage =
        View.Page "Home" [
            Div [Text "Welcome to our website!"]
        ]
        |> Sitelet.Content "/" Home

    let AboutUsPage =
        View.Page "About Us" [
            Div [Text "TODO: describe us."]
        ]
        |> Sitelet.Content "/about" AboutUs

    let Main =
        Sitelet.Sum [
            HomePage
            AboutUsPage
        ]

HomePage и AboutUsPage – одностраничные сайтлеты с одним URL и одним действием. Они комбинируются в вебсайт при помощи оператора Sum.
Теперь немножко административного boilerplate:
type Website() =
    interface IWebsite<Action> with
        member this.Actions = []
        member this.Sitelet = Site.Main

[<assembly: WebsiteAttribute(typeof<Website>)>]
do ()

И все! Давайте на это посмотрим:


Пока все хорошо. У страниц те URLы, которые мы ожидали и работают ссылки в меню.
То, что описано выше, может быть выполнено любым достойным вебфреймворком. Давайте раздвинем границы и чуть-чуть это приправим. Добавим несколько строк F#, которые будут компилироваться в JavaScript:
module Client =
    open IntelliFactory.WebSharper.Html

    [<JavaScript>]
    let Button label =
        Button [Text label]
        |>! OnClick (fun button _ ->
            button.Text <- "CLICKED")

    type ButtonControl(label: string) =
        inherit Web.Control()

        new () = new ButtonControl("unlabelled")

        [<JavaScript>]
        override this.Body = Button label :> _



Тут есть кнопка, которая при нажатии меняет надпись на себе. И тут есть элемент управления.
Теперь, несмотря на то, что Кнопка целиком живет на клиенте (фактически, создает узлы DOM), Элемент управления выполняет квантовый переход: конструктор выполняется на сервере, а тело – на клиенте.
Но это означает, что можно воспользоваться Элементом управления, чтобы склеить клиент и сервер. Давайте изменим страницу AboutUs:


    let AboutUsPage =
        View.Page "About Us" [
            Div [Text "TODO: describe us."]
            Div [new Client.ButtonControl("Click me!")]
        ]
        |> Sitelet.Content "/about" AboutUs

Вот оно. Теперь пользователь увидит нажимаемую кнопку с JavaScript, реализованную на F#, прямо там, где вы этого ожидаете. Никакого беспокойства о тегах script, никакой ловли зависимостей, нет беспокойства с “ondocumentready”, все просто работает:


Ниже полный листинг. Как только выйдет версия 2.1, вы сможете запустить это сами. Оставайтесь с нами!
namespace WebSharperSiteletsProject

open System
open System.IO
open System.Web
open IntelliFactory.Html
open IntelliFactory.WebSharper
open IntelliFactory.WebSharper.Sitelets

type Action =
    | Home
    | AboutUs

module View =

    let ( => ) a b =
        A [HRef b] -< [Text a]

    let Page title body =
        PageContent <| fun ctx ->
            {
                Page.Default with
                    Title   = Some title
                    Body    =
                        H1 [Text title]
                        ::
                        UL [
                            LI ["Home"    => ctx.Link Home]
                            LI ["AboutUs" => ctx.Link AboutUs]
                        ]
                        ::
                        body
            }

module Client =
    open IntelliFactory.WebSharper.Html

    [<JavaScript>]
    let Button label =
        Button [Text label]
        |>! OnClick (fun button _ ->
            button.Text <- "CLICKED")

    type ButtonControl(label: string) =
        inherit Web.Control()

        new () = new ButtonControl("unlabelled")

        [<JavaScript>]
        override this.Body = Button label :> _

module Site =

    let HomePage =
        View.Page "Home" [
            Div [Text "Welcome to our website!"]
        ]
        |> Sitelet.Content "/" Home

    let AboutUsPage =
        View.Page "About Us" [
            Div [Text "TODO: describe us."]
            Div [new Client.ButtonControl("Click me!")]
        ]
        |> Sitelet.Content "/about" AboutUs

    let Main =
        Sitelet.Sum [
            HomePage
            AboutUsPage
        ]

type Website() =
    interface IWebsite<Action> with
        member this.Actions = []
        member this.Sitelet = Site.Main

[<assembly: WebsiteAttribute(typeof<Website>)>]
do ()

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 15

    +5
    И нафига такой геморой?
      +3
      А как не геморрой?

      Я вижу тут выгоду в том, что:
      — есть статический контроль согласованности
      — все на одном языке

      Я не вебпрограммист, мне показался этот пост теоретически интересным — как функциональные приёмы используются для реального вебпрограммирования
        0
        Пример создан специально для людей не любящих HTML, JavaScript и статические страницы.
        Зато фреймворк! Его использование позволило не заморачиваться с созданием заголовка, сделать единую навигацию с линками указывающими на текущую страницу. Тот же копипаст, но программно.

        Мне кажется так человечнее gist.github.com/801135
        Отсутсвие абстракций освобождает от проблем возникающих при их протекании.
          0
          — Нет javascript
          — Нет статической проверки
            0
            Бесполезная кнопка меняющая свой текст не нужна. Если очень хочется:

            $('input').click(function() {
            this.text = 'clicked';
            });

            Статическая проверка далеко не всегда нужна. В примере выше она даже мешает — введены несуществующие абстракции различных по назначению страниц. Страница индекса это путеводитель по сайту, страница «о нас» — контент за которым пришел пользователь. В моем примере эти функциональности не пересекаются.

            Чего нельзя сделать статическими файлами, так это обработку непредсказуемых данных. Скажем обработку ввода пользователя или данных датчиков. Хорошие примеры — поиск, голосование.
              0
              >>>Бесполезная кнопка меняющая свой текст не нужна.

              По-моему, совершенно понятно, что это пример. Вам никогда не встречались программы hello, world в учебниках?

              >>> Статическая проверка далеко не всегда нужна.

              Мне сложно придумать сущность, для которой такая фраза была бы неверна

              >>>Чего нельзя сделать статическими файлами, так это обработку непредсказуемых данных

              Это к чему?
                0
                К тому что пример хреновый
        0
        Тут просто не раскрыта самая интересная возможность web# — это взаимодействие с DOM деревом отрендереном в браузере через f#. Всё что помечено аттрибутом JavaScript выполняется на клиенте. У вебшарпера есть адаптеры для JQery и т.п. что позволяет взаимодействовать с js из f# через интерфейсы.
        Преимущество данного подхода написания чего то, что генерирует js не очевидно ровно до момента знакомства с действительно rich web applications типа Appian или Cordys.
        +2
        F# и Web, о боже!
          +2
          Вообще достаточно интересно — такой себе аналог GWT на F#. Смущают только вот какие вещи: разделение на платную и бесплатную версии (с ограниченым фугкционалом конечно же) и привязка к win-платформе (даже если отбросить предвзятость, то цены на win-хостинг обычно выше) — можно ли использовать WebSharper без VS (Mono+Linux например)?
            +1
            Привязка к Windows? Не, вроде планируется отвязка от Asp.Net и IIS с использованием Frack и Frank, если я правильно понимаю. И вообще, сайтлетам точно в последствии должно быть пофиг на каком сервере они лежат, это только сейчас еще какие-то артефакты остались. Впрочем, это будет наверное не в 2.0 а в 2.1 или что-то вроде.
            0
            Чем реально отличается WebSharper Professional от WebSharper Standard? Можно где-то увидеть таблицу различий, что было допилено, какие новые фичи появились?
              +1
              www.websharper.com/Downloads.aspx

              WebSharper Professional Beta, (change log)
              Latest version is 2.0.88 (bundle)

              Includes WebSharper Manager and support for:
              WebSharper formlets
              WebSharper sitelets + templates
              WebSharper reactive extensions
              HTML combinators + DOM
              HTML5 (full)
              EcmaScript (full)
              jQuery (1.4.4, full)
              RPC + JSON
              ASP.NET integration
              Proxies for basic .NET types, core F# standard library, collections, asynchronous control
              — WebSharper Standard
              Latest version is 1.0.28

              Includes support for:
              WebSharper formlets
              WebSharper reactive extensions
              HTML combinators + DOM
              HTML5 Canvas
              EcmaScript (partial)
              jQuery (1.4.2, partial)
              RPC
              ASP.NET integration
              Proxies for basic .NET types, core F# standard library, collections, asynchronous control
                0
                Спасиб.
                А еще, можно ли все Samples в одном архиве где-то скачать?
                  0
                  Не знаю — попробуйте в комменты к исходному посту сходить

            Only users with full accounts can post comments. Log in, please.