Phoenix,在模板eex中使用套接字和在socket.js外部的Presence

时间:2018-06-12 09:06:55

标签: javascript sockets elixir phoenix-framework phoenix-channels

我想以自己的方式在模板中组织socketPresence的使用。 作为一个新手,在我看来,在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:

peerreynders曝光了明确,聪明,善良和完整的回应 在elixirforum

溶液2:

另一个解决方案是Deini在Elixir-Lang的Slack频道中指出的,再次使用Webpack,并涉及更多凤凰 - Elixir风格,由hoang_nguyen在Medium上发表。

SOLUTION3:

Diacode和第二页here

中使用Brunch并使用Webpack

1 个答案:

答案 0 :(得分:0)

选择的解决方案有几个部分,如diacode所示,几乎没有任何变化,可以应用于凤凰城的未来Webpack&gt; = 1.4。

首先要指出我们要加载哪个js文件,为方便起见,我们将其命名为与模块 - 模板对相同。

该名称是在layout_view.ex中的函数中创建的,并作为属性放置在Body的{​​{1}}标记中,如下所示:

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);

现在,您必须导入视图(这将随Webpack一起更改)

每个js文件的结构都是一对函数 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; } 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

我省略了代码,因为它在链接中,我相信你已经在其他地方看到了它。

还有很多工作要做,这是一个未完成的代码。 但是there在GitHub上