【问题标题】:Using modular design pattern in Javascript with DOM selections在带有 DOM 选择的 Javascript 中使用模块化设计模式
【发布时间】:2017-02-27 12:40:23
【问题描述】:

我关注Modular Design Pattern 已经有一段时间了,发现它非常有用,因为它有助于代码的良好维护和将块分离为模块。

经常使用 jQuery 的模块结构导致我的大部分应用程序/代码遵循以下结构:

(function() {
    var chat = {
        websocket: new WebSocket("ws://echo.websocket.org/"),
        that: this,
        init: function() {
            this.scrollToBottom();
            this.bindEvents();
            this.webSocketHandlers();
        },
        bindEvents: function() {
            this.toggleChat();
            this.filterPeople();
            this.compose();
        },
        elements: {
            indicator: $(".indicator"),
            statusText: $(".status-text"),
            chatHeadNames: $(".people li .name"),
            filterInput: $("#filter-input"),
            msgInput: $("#msg-input"),
            sendBtn: $(".send")
        },
        ...
        ...
        ...
        filterPeople: function() {
          var that = this;
          this.elements.chatHeadNames.each(function() {
              $(this).attr('data-search-term', $(this).text().toLowerCase());
          });
        },
        ...
        ...
        };

        chat.init();
})();

我想知道的是,通过 jQuery 引用我的所有元素作为单个变量 chat.elements 的一部分是否是一种良好做法

我的一部分告诉我,它确实是一次引用所有选择器并将它们缓存在变量中的好方法,以便可以使用缓存的变量(而不是多个 DOM 选择)完成对同一元素的多次使用。

我的另一部分告诉我这可能是一个反模式,需要时应该选择特定元素并在本地缓存。

我自始至终都使用了类似的结构,并且对代码的反应不一,但没有什么可靠的。任何帮助,将不胜感激。谢谢!

【问题讨论】:

  • 使用元素来选择名称和状态或其他东西不是一个好主意,如果有人用检查元素更改名称会发生​​什么?或者明天你的队友换主题一切都会被打破!
  • 将数据保存在数组或对象中并用于存储使用本地存储
  • 元素属性在页面加载时被解析,事件直接绑定到节点,所以如果有人用检查元素更改名称,它不会引起问题。而localstorage 是个坏主意。

标签: javascript jquery design-patterns modular-design


【解决方案1】:

缓存选择器是一件好事。坚持他们是个好主意。它提高了重复查询 DOM 相同事物的性能。您上面的代码看起来与 BackboneJS 和 MarionetteJS 代码非常相似。

不过,我确实有一些警告:

  1. 这种模式可能会导致内存泄漏。考虑破坏子视图但保留对选择它的某些内容的引用的情况。这称为悬空指针。视图不会真正消失。所有绑定都将保留。活动将继续在幕后进行。
  2. 您最终会遇到一个错误,您决定重新渲染屏幕的一部分。然后需要清理所有绑定,并且您需要记住删除和选择器。如果您不这样做,您几乎肯定会遇到问题,您想知道为什么事件确实在触发但屏幕上似乎没有发生任何事情......(这将是因为它发生在屏幕外,发生在您尝试过的元素上删除,它仍然存在......有点)。
  3. 当前查询元素的方式会导致搜索整个页面。看看https://api.jquery.com/find/。如果您缓存一个选择器,然后在该选择器中执行搜索,它可能会给您带来一点性能提升。

【讨论】:

  • 1.如果我不使用像 Backbone 这样的框架(通常是这种情况),那么不会破坏任何子视图,也不会出现悬空指针的情况。 2. 除非委托的事件直接绑定到DOM节点,所以如果我删除一个元素节点,绑定到的事件会自动分离。 3. 我在缓存的选择器上使用jQuery.find 来搜索子元素。
  • @nashcheez 您不需要使用框架,您只需要构建自己的系统来负责清理(如果需要)。有很多应用程序不需要处理任何类型的清理。无论如何,这些都不重要,它仍然是一个很好的模式。如果您确实需要清理,可以更轻松地找到要清理的内容。
  • 当然感谢您的回复。我将对此进行一些研究。 :)
  • 我只会在上面的答案中添加一件事:惰性选择(关于问题的哪一部分可以通过例如 getter 完成 - 并且仍然可以通过属性访问),但它会引入额外的引擎盖下的复杂性(在 2. 的范围内更糟)。恕我直言,潜在的好处可能不值得,但您的里程可能会有所不同。
【解决方案2】:
  • 我认为,如果聊天模块只有其子模块的选择器,那么这是一个很好的模式。喜欢:
<div id="chat-module">
  <div class="indicator">...</div>
  <div class="status-text">...<div>
  ...
</div>
<script src="and your chat module.js"></script>
// your chat module selecting .indicator:
// $('#chat-module.indicator')
  • 另外,为您的模块添加关闭功能。因此,当您将其从视图中移除时(就像在单页应用程序中一样),您可以取消选择器和分离事件处理程序,例如:delete this.elements.indicator 和事件分离代码。

为此还有其他/更好的模式,例如,当用户键入内容时,您会触发一个事件,然后在您的模块中捕获该事件。将 UI 和代码分开。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多