tightenco/laravel-elm

此包已被废弃且不再维护。没有建议的替代包。

Elm Laravel 平台

v4.0.1 2021-06-21 20:43 UTC

This package is auto-updated.

Last update: 2024-04-15 16:42:40 UTC


README

Laravel Elm logo

Latest Version on Packagist

Elm on Laravel 的平台

厌倦了前端选择悖论和持续更新吗?

想要一个稳定且具有个人见解的平台来构建吗?

此包使构建变得无缝。

需求

  • Laravel 8

文档

从现在开始需要一些 Elm 知识!

Elm 学习资源

安装

composer require tightenco/laravel-elm
  • 运行 elm:install 命令,这将
    • 添加 Laravel Elm 的 npm 伴随包
    • 设置 Laravel Elm 的 webpack.mix.js
    • 设置 Laravel Elm 的 tailwind.config.js
php artisan elm:install
  • 安装新的 npm 依赖项
npm install

可选认证模板(Tailwind)

  • 运行 elm:auth 命令,这将
    • 添加基本登录/注册的所有路由和 Elm 页面
    • web.php 中添加 Elm::authRoutes()
    • 使用 js 脚本包含设置 app.blade.php
php artisan elm:auth

注意:别忘了运行 php artisan migrate

像处理其他所有内容一样监视你的 elm 文件

注意:Elm 编译速度将比您习惯的要快得多 🔥

npm run watch

然后打开您的本地站点!(valet link && valet open) 尝试访问 /login/register

一般资源注意!

如果您想避免提交这些生成的文件,可以将 public/jspublic/css 添加到 .gitignore 中!

创建页面

php artisan elm:create Welcome

这将在 resources/elm/Example/Welcome.elm 中创建

现在使用 Elm 门面来渲染您的 Elm 页面!

routes/web.php

Route::get('/', function () {
    return Elm::render('Welcome');
});

你好,示例!

从现在开始需要一些 Elm 知识

学习资源

向你的页面传递值

更新您的 Laravel 路由

routes/web.php

Route::get('/', function () {
    return Elm::render('Welcome', ['name' => 'John']);
});

更新您的 Elm 页面

resources/elm/pages/Welcome.elm

  • 在顶部添加解码导入
  • name 字段添加到 Props (String)
  • 使用 name 字段更新 decodeProps
  • view 函数中使用 props.name
module Welcome exposing (..)

import Html exposing (Html, div, text)
import Html.Attributes exposing (class)
import Json.Decode exposing (Decoder, Value, decodeValue, string, succeed)
import Json.Decode.Pipeline exposing (required)
import LaravelElm exposing (Page, page)


type alias Props =
    { name : String }


type alias State =
    {}


type alias Model =
    { props : Props
    , state : State
    }


type Msg
    = NewProps Value
    | NoOp


decodeProps : Decoder Props
decodeProps =
    succeed Props
        |> required "name" string


stateFromProps : Props -> State
stateFromProps props =
    {}


main : Page Model Msg
main =
    page
        { decodeProps = decodeProps
        , stateFromProps = stateFromProps
        , update = update
        , view = view
        , newPropsMsg = NewProps
        }


update : Msg -> Model -> ( Model, Cmd Msg )
update msg { props, state } =
    case msg of
        NewProps newProps ->
            ( { props = Result.withDefault props (decodeValue decodeProps newProps)
              , state = state
              }
            , Cmd.none
            )

        NoOp ->
            ( { props = props
              , state = state
              }
            , Cmd.none
            )


view : Model -> Html Msg
view { props, state } =
    div [ class "container mx-auto m-4 p-4" ]
        [ text <| "Hello, " ++ props.name ++ "!" ]

与所有页面共享值

AppServiceProvider.php

use Tightenco\Elm\Elm;
...
    public function boot()
    {
        ...

        Elm::share('user', function () {
            return auth()->user() ? [
                'id' => auth()->user()->id,
                'name' => auth()->user()->name,
            ] : null;
        });
    }
...

路由

Laravel Elm 中的路由完全由您的 Laravel 路由处理!

然而,我们可以 使用 这些路由在我们的 Elm 代码中以内置的方式。

  1. 添加一个路由,例如,我们的欢迎页面,并带有 name
Route::get('/', function () {
    return Elm::render('Welcome');
})->name('welcome');
  1. 运行 elm:routes 命令以生成 Elm 路由文件

    resources/elm/laravel-elm-stuff/Routes.elm(不要手动编辑此文件)

php artisan elm:routes
  1. 现在我们可以从 Elm 的 update 处理程序中发送用户到此页面

    将用户发送到 /

Routes.get Routes.welcome

甚至可以向端点发送一些数据

POST /todos,数据为 "description""添加更多文档"

Routes.post <|
  Json.Encode.object
      [ ( "url", Json.Encode.string <| Routes.todosStore )
      , ( "data"
        , Json.Encode.object
              [ ( "description", Json.Encode.string "add more docs" )
              ]
        )
      ]

验证错误

errors 值会自动传递到您的 Elm 视图中,您只需将其添加到 props 中即可使用!

import LaravelElm exposing (Errors)

type alias Props =
    { errors : Errors }

decodeProps : Decoder Props
decodeProps =
    succeed Props
        |> required "errors" (dict (list string))

与 JavaScript 互操作

在JS & Elm之间来回通信 resources/elm/ExamplePage.elm

port module ExamplePage exposing (..)

port saveEmail : String -> Cmd msg

port receiveEmail : (Value -> msg) -> Sub msg
...
LaravelElm.register("ExamplePage", (page) => {
    page.send("receiveEmail", localStorage.getItem("email"));

    page.subscribe("saveEmail", (email) => {
        localStorage.setItem("email", email);
    });
});

调试

Laravel 错误

在开发期间,Laravel错误会在前端以模态框的形式显示,使用你熟悉的点火错误页面!

开发者工具

即将推出!

持久滚动

有时你希望在导航到和离开不同页面时保留“类似于应用程序”的滚动位置。

Laravel Elm内置了对这一功能的支持,通过将视口值保存到历史记录中。

要使用它,你需要

  • 导入所需的组件
import LaravelElm exposing (Scroll, Viewports, decodeViewports, preserveScroll, receiveNewProps, saveScroll, setViewports)
  • 添加一个SaveScroll消息
type Msg
    = NewProps Value
    | NoOp
    | SaveScroll Scroll
  • 添加viewports属性
type alias Props =
    { errors : Errors
    , loading : Bool
    , viewports : Viewports }
  • 添加viewports属性的解码器
decodeProps : Decoder Props
decodeProps =
    Json.Decode.succeed Props
        |> required "viewports" decodeViewports
  • 确保在挂载时使用保存的视口位置
main : Program Value (Result Error Model) Msg
main =
    LaravelElm.pageWithMountAndSubscriptions
        { decodeProps = decodeProps
        , stateFromProps = stateFromProps
        , view = view
        , update = update
        , subscriptions = \_ -> receiveNewProps NewProps
        , onMount = \props -> setViewports NoOp props.viewports
        }
  • 确保在更新时使用保存的视口位置
  • 以及在滚动时保存视口位置
update : Msg -> Model -> ( Model, Cmd Msg )
update msg { props, state } =
    case msg of
        NewProps newProps ->
            case decodeValue decodeProps newProps of
                Ok decodedProps ->
                    ( { props = decodedProps
                      , state = state
                      }
                    , setViewports NoOp decodedProps.viewports
                    )

                Err _ ->
                    ( { props = props, state = state }, Cmd.none )

        SaveScroll scroll ->
            ( { props = props, state = state }, saveScroll scroll )
  • 最后,在HTML元素上使用preserveScroll(“key”对于多个滚动容器应该是唯一的)
view : Model -> Html Msg
view { props, state } =
    div
        ([ class "h-full overflow-y-scroll" ]
            ++ preserveScroll SaveScroll "key"
        )
        [ text "long content" ]

进度指示器

在Elm中

loading属性会自动传递给所有你的Elm视图,你只需将其添加到props中即可使用!

type alias Props =
    { loading : Bool }

decodeProps : Decoder Props
decodeProps =
    succeed Props
        |> required "loading" bool

在JavaScript中

你可以在JavaScript中通过elm-loading事件访问加载状态

使用nprogress显示顶部进度条的示例

(180ms后,所以对于快速连接不会显示)

import Nprogress from "nprogress";

let loadingTimeout = null;
Nprogress.configure({ showSpinner: false, minimum: 0.4 });
window.addEventListener("elm-loading", function ({ detail: loading }) {
    clearTimeout(loadingTimeout);

    if (loading) {
        loadingTimeout = setTimeout(Nprogress.start, 180);
    } else {
        Nprogress.done();
    }
});

部署

更新资源

Laravel Elm使用服务工作者确保在生产中使用最新资源。将php artisan elm:sw添加到你的“prod”命令中,以确保它获取最新版本的资源。

{
  "scripts": {
    ...,
    "prod": "npm run production;php artisan elm:sw",
    ...,
  }
}

配置

热重载

如果你的应用程序非常大/复杂,你可能希望在开发中禁用热重载和调试

  • 创建一个elm.php Laravel配置文件,并将debug设置为false
  • 然后在webpack.mix.js中添加
...
    .elm({debug: false})
...

这会禁用调试代码的生成,并且在npm run watch期间不会启动热重载服务器

测试

Laravel 测试

所有正常的HTTP测试都与纯Laravel应用程序中的功能相同。

但如果我们想断言发送给Elm的props,我们可以在tests/TestCase.phpsetUp方法中添加X-Laravel-Elm头信息

<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;

    public function setUp(): void
    {
        parent::setUp();
        $this->withHeaders(['X-Laravel-Elm' => 'true']);
    }
}

现在我们可以通过正常的Laravel JSON断言方法测试一切!

$this->get(route('entries.index'))->assertJsonCount(1, 'props.entries');

示例应用

贡献

要开始为Laravel Elm做贡献,请查看贡献指南

致谢

安全

如果你发现任何与安全相关的问题,请通过hello@tighten.co发送电子邮件,而不是使用问题跟踪器。

许可

查看此仓库的许可