javascript - Phoenix,在模板 eex 中使用 socket.js 之外的套接字和 Presence
问题描述
我想以我自己的方式组织模板中socket
和的使用。Presence
作为一个新手,在我看来,将所有处理通道的客户端代码放入其中sockets.js
可以将其转换为非常大的一块。特别是如果有许多页面使用套接字/存在。我不知道哪个是最好的解决方案(或者这是否对其他人来说是个问题),但是我误解了 js 的功能,导致我很好地组织了代码。
在socket.js
import {Socket, Presence} from "phoenix"
// Other stuff
export {
Presence,
socket
}
在app.js
,而不是import socket from "./socket"
在结尾,我写
import {Presence, socket} from "./socket"
window.getPhoenixSocket = function () {
return socket;
};
window.getPhoenixPresence = function () {
return Presence;
};
在模板中eex
(我知道混合 html 和脚本不是一个好习惯)(除了 React 家伙!)我编写了以下脚本:
<script>
window.onload = function () {
let channel = getPhoenixSocket (). channel ("cute: channel", {})
let Presence = getPhoenixPresence ();
....
// Here I can use channel and Presence for my obscure purposes
....
}
</script>
因此,使用套接字的每个页面的代码都保留在自己的页面中,而不是在socket.js
由于我对这个解决方案并不完全满意,所以我问你,这是正确的吗?是不是?最好的方法是什么?有没有人有这个问题?
===== 编辑 ======
解决方案1:
elixirforum 的同行曝光了一个清晰、聪明、善良和完整的回应
解决方案2:
Deini 在 Elixir-Lang 的 Slack Channel 中指出的另一个解决方案再次使用 Webpack,并且涉及更多 Phoenix-Elixir 风格,已由 hoang_nguyen 在Medium上发布。
解决方案3:
解决方案
选择的解决方案有几个部分,如diacode所示,只需少量更改即可在 Phoenix> = 1.4 的未来 Webpack 中应用。
首先是指明我们要加载哪个js文件,为了方便我们将其命名为模块-模板对。
该名称在 中的函数中创建layout_view.ex
,并作为属性放置在Body
标签中,app.html.eex
如下所示:
<body data-js-view-name="<%= js_view_name(@view_module, @view_template) %>">
然后,app.js
负责为我们放置的每个模板加载特定的 js,assests/js/views
并调用加载函数。
import loadView from './views/view_loader';
function handleDOMContentLoaded() {
//// Get the current view name
const viewName = document.getElementsByTagName('body')[0].dataset.jsViewName;
// Load view class and mount it
const ViewClass = loadView(viewName);
window.currentView = new ViewClass();
window.currentView.mount();
}
function handleDocumentUnload() {
window.currentView.unmount();
}
window.addEventListener('DOMContentLoaded', handleDOMContentLoaded, false);
window.addEventListener('unload', handleDocumentUnload, false);
视图的加载器是:
import MainView from './main';
import RoomShowView from './room_show';
import UserShowView from './user_show';
// Collection of specific view modules
const views = {
"room_show": RoomShowView,
"user_show": UserShowView
};
export default function loadView(viewName) {
return views[viewName] || MainView;
}
现在,你必须导入视图(这将随着 Webpack 改变)
每个 js 文件的结构是一对函数mount
和unmount
, (默认情况下调用视图父级)我们放置代码的位置。
import MainView from './main';
import socket from "../socket";
import {Presence} from "phoenix";
export default class View extends MainView {
mount() {
super.mount();
// the code
console.log('room-show mounted');
console.log('eex room.id: '+eex["@room.id"])
}
unmount() {
super.unmount();
// Specific logic here
console.log('room-show unmounted');
}
}
在模板中,我们将从服务器嵌入的变量放在我们从动态加载的代码访问的字典中。
<script>
var eex = {
"@room.id": <%= @room.id %>,
"@current_user.name": "<%= @current_user.name %>",
"@current_user.id": <%= @current_user.id %>
}
</script>
想法是仅在一个模板中使用单个通道,并为所有模板的通用目的维护另一个通道。频道是在 中创建的app.js
,您可以push
在任何其他模板中,我已将其放入main.js
我省略了代码,因为它在链接中,我相信你已经在其他任何地方看到过它。
还有很多工作要做,这是一个未完成的代码。但是在 GitHub 上有
推荐阅读
- mongodb - 在 Mongodb 中从 MMap 更改为 Wiretiger 时,是否需要进行任何客户端更改
- powershell - 使用 Powershell 的邮件自动化任务
- mongodb - 在 Mongodb 中将数据存储为对象与数组
- java - 如何修复:Lombok builder() 方法似乎在 IntelliJ 中无法识别?
- spring-boot - Spring Security:无法启用 permitAll() 到 POST API
- nginx - 如何使用 ffmpeg 和 aparat.com 设置 rtmp?
- python - 将python中的zip文件保存到磁盘
- c# - 将字符串转换为 TimeSpan
- jdeveloper - 跨项目依赖和循环依赖
- node.js - 在 node.js 中发送带有 XML 数据的 POST 请求:错误 400,“客户端发送的请求在语法上不正确”