Elm表单提交能否使用相对URL路径?
解决Elm SPA中表单相对路径提交且避免页面刷新的方案
方案1:直接用Elm Http模块发起相对路径请求(最简洁)
你之前提到的硬编码完整URL其实没必要——Elm的Http模块会自动将相对路径与当前页面的基准URL(origin)拼接。比如直接写:
Http.post { url = "/my-api" -- 相对路径,自动适配本地/生产环境 , body = Http.jsonBody myPayload , expect = Http.expectJson GotResponse decoder }
这样本地开发时会请求http://localhost:xxxx/my-api,生产环境则对应部署的域名,完全不用手动切换。配合提交按钮的onClick发送Msg触发请求,既保留了SPA无刷新的特性,又解决了环境适配问题。
方案2:拦截表单默认提交事件,手动处理
如果你想保留HTML表单的结构(比如利用浏览器自动填充、表单验证等原生特性),可以拦截表单的onSubmit事件,阻止默认刷新行为,再提取表单数据发起异步请求:
Html.form [ onSubmit HandleFormSubmit -- 拦截默认提交 ] [ input [ type_ "text", name "username", value model.username, onInput UpdateUsername ] [] , button [ type_ "submit" ] [ text "提交" ] ] -- 在update中处理: HandleFormSubmit -> let payload = encodeFormData model.username -- 自行编码表单数据 request = Http.post { url = "/my-api" , body = Http.multipartBody payload -- 或jsonBody,根据接口需求 , expect = Http.expectJson GotResponse decoder } in ( model, Http.send GotResponse request )
这种方式既利用了原生表单的便利性,又实现了无刷新提交,同时用相对路径自动适配环境。
方案3:用隐藏iframe作为target(兼容传统表单提交场景)
如果必须用原生表单提交(比如文件上传这类复杂场景),可以添加一个隐藏的iframe作为表单的target,这样提交请求会在iframe中完成,主页面不会刷新。之后可以通过监听iframe的加载事件,在Elm中处理返回结果:
-- 页面中添加隐藏iframe iframe [ id "form-target", style "display" "none" ] [] -- 表单配置 Html.form [ method "POST" , action "/my-api" , target "form-target" -- 指定target为隐藏iframe , on "load" (Json.succeed IframeLoaded) -- 监听iframe加载完成事件 ] [...] -- 在update中处理IframeLoaded事件,读取iframe内容获取响应 IframeLoaded -> -- 这里可以通过端口(Port)调用JS读取iframe的响应内容,再传回Elm ( model, sendPortToJs "getIframeResponse" () )
这种方式适合需要原生表单处理的场景,同时避免页面刷新,相对路径也能正常工作。
内容的提问来源于stack exchange,提问作者ConfusedPerson
相关产品推荐
相关产品推荐

