tightenco / laravel-elm
Elm Laravel 平台
Requires
- laravel/framework: ^8.0
Requires (Dev)
- orchestra/testbench: ^6.0
README
Elm on Laravel 的平台
厌倦了前端选择悖论和持续更新吗?
想要一个稳定且具有个人见解的平台来构建吗?
此包使构建变得无缝。
需求
- Laravel 8
文档
从现在开始需要一些 Elm 知识!
安装
- 确保你有一个准备好的 8.x Laravel 应用(https://laravel.net.cn/docs/8.x/installation)
- 现在添加 laravel-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/js
和public/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 代码中以内置的方式。
- 添加一个路由,例如,我们的欢迎页面,并带有
name
Route::get('/', function () { return Elm::render('Welcome'); })->name('welcome');
- 运行
elm:routes
命令以生成 Elm 路由文件resources/elm/laravel-elm-stuff/Routes.elm
(不要手动编辑此文件)
php artisan elm:routes
- 现在我们可以从 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.php
的setUp
方法中添加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发送电子邮件,而不是使用问题跟踪器。