我想以自己的方式组织模板中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
由于我对这个解决方案并不完全满意,我问你,这是正确的吗?不是吗?最好的方法是什么? 有人有这个问题吗?
===== 编辑 ======
SOLUTION1:
清晰、睿智、善良、完整的回应被同行者曝光 在长生不老药论坛
SOLUTION2:
Deini在Elixir-Lang的Slack Channel中指出的另一种解决方案再次使用Webpack,并涉及更多的Phoenix-Elixir风格,已由hoang_nguyen在Medium上发布。
SOLUTION3:
在 Diacode 中使用早午餐和使用 Webpack 以及此处的第二页
选择的解决方案有几个部分,如变音码所示,只需很少的更改,就可以应用于凤凰城的未来 Webpack> = 1.4。
第一件事是指示我们要加载哪个 js 文件,为了方便起见,我们将其命名为与模块-模板对相同。
该名称是在layout_view.ex
的函数中创建的,并作为属性放置在app.html.eex
的Body
标签中,如下所示:
<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上有