gleam中使用remote data显示数据

gleam简介

gleam是一个强类型语言,可以编译为erlang和javascript,可用作前、后端开发。作为后端,具有高可靠性、高并发特征,可以无缝操作erlang、elixir等语言库;同时作为前端,不用安装太多依赖,直接开箱即用。下面以一个小例子演示gleam的简单用法。

创建工程

gleam new remote

添加依赖

gleam add lustre
gleam add lustre_http
gleam add remote_data
gleam add --dev lustre_dev_tools

创建数据类型

type Quote {
  Quote(author: String, content: String)
}

创建模型

type Model {
  Model(quote: RemoteData(Quote, HttpError))
}

创建消息

pub opaque type Msg {
  UserClickedRefresh
  ApiUpdatedQuote(Result(Quote, HttpError))
}

更新

fn get_quote() -> Effect(Msg) {
  let url = "https://api.quotable.io/random"
  let decoder =
    dynamic.decode2(
      Quote,
      dynamic.field("author", dynamic.string),
      dynamic.field("content", dynamic.string),
    )

  lustre_http.get(url, lustre_http.expect_json(decoder, ApiUpdatedQuote))
}

fn update(_model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
  case msg {
    UserClickedRefresh -> #(Model(quote: rd.Loading), get_quote())
    ApiUpdatedQuote(quote) -> #(
      Model(quote: rd.from_result(quote)),
      effect.none(),
    )
  }
}

视图

fn view(model: Model) -> Element(Msg) {
  let Model(quote) = model
  case quote {
    rd.Success(quote) ->
      html.div([], [
        html.p([on_click(UserClickedRefresh)], [
          element.text("Click to refresh quote of the day..."),
        ]),
        element.text(quote.author <> " once said..."),
        html.p([attribute.style([#("font-style", "italic")])], [
          element.text(quote.content),
        ]),
      ])
    rd.NotAsked ->
      html.p([on_click(UserClickedRefresh)], [
        element.text("Click to fetch quote of the day..."),
      ])
    rd.Loading -> html.p([], [element.text("Fetching quote...")])
    rd.Failure(_) -> html.p([], [element.text("Failed to fetch quote!")])
  }
}

完整代码

import gleam/dynamic
import remote_data.{type RemoteData} as rd
import lustre
import lustre/attribute
import lustre/effect.{type Effect}
import lustre/element.{type Element}
import lustre/element/html
import lustre/event.{on_click}
import lustre_http.{type HttpError}

pub fn main() {
  let app = lustre.application(init, update, view)
  let assert Ok(_) = lustre.start(app, "#app", Nil)
  Nil
}

type Model {
  Model(quote: RemoteData(Quote, HttpError))
}

type Quote {
  Quote(author: String, content: String)
}

fn init(_) -> #(Model, Effect(Msg)) {
  #(Model(quote: rd.NotAsked), effect.none())
}

pub opaque type Msg {
  UserClickedRefresh
  ApiUpdatedQuote(Result(Quote, HttpError))
}

fn update(_model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
  case msg {
    UserClickedRefresh -> #(Model(quote: rd.Loading), get_quote())
    ApiUpdatedQuote(quote) -> #(
      Model(quote: rd.from_result(quote)),
      effect.none(),
    )
  }
}

fn get_quote() -> Effect(Msg) {
  let url = "https://api.quotable.io/random"
  let decoder =
    dynamic.decode2(
      Quote,
      dynamic.field("author", dynamic.string),
      dynamic.field("content", dynamic.string),
    )

  lustre_http.get(url, lustre_http.expect_json(decoder, ApiUpdatedQuote))
}

fn view(model: Model) -> Element(Msg) {
  let Model(quote) = model
  case quote {
    rd.Success(quote) ->
      html.div([], [
        html.p([on_click(UserClickedRefresh)], [
          element.text("Click to refresh quote of the day..."),
        ]),
        element.text(quote.author <> " once said..."),
        html.p([attribute.style([#("font-style", "italic")])], [
          element.text(quote.content),
        ]),
      ])
    rd.NotAsked ->
      html.p([on_click(UserClickedRefresh)], [
        element.text("Click to fetch quote of the day..."),
      ])
    rd.Loading -> html.p([], [element.text("Fetching quote...")])
    rd.Failure(_) -> html.p([], [element.text("Failed to fetch quote!")])
  }
}

编译及运行

gleam run -m lustre/dev start
posted @ 2024-04-11 09:41  卓能文  阅读(102)  评论(0)    收藏  举报