将DOM交互放在可扩展的javascript架构上的位置

时间:2011-12-19 19:49:01

标签: javascript architecture

目前我对如何拥有更易维护的javascript架构感到困惑。我可能不在轨道上,但我会说我的代码中有近50%涉及DOM因此使用我的基础库(jQuery)。

我已经检查了[1] Nicholas Zakas的可扩展应用程序架构设计:http://developer.yahoo.com/yui/theater/video.php?v=zakas-architecture和[2] Addy Osmani模式用于大规模JavaScript应用程序架构http://addyosmani.com/largescalejavascript/

我有一个单页应用程序样式,通过动态添加的ajax和DOM元素获取大量内容。我的主要问题是:如果我使用jQuery(或任何其他基础库)来操作DOM,我如何将代码分成小的可重用块。

让我们选择一个任务列表模块。我知道模块看起来像这样:

var TaskList = function() {
  addTask = function() {
    ...
  };

  removeTask = function() {
    ...
  };

  return {
    addTask: addTask,
    removeTask: removeTask
  }
}();

应该在哪里编写DOM元素事件注册,使用ajax调用来保存,加载或删除任务,将新任务附加到DOM元素等等。

我承诺在模块上使用jQuery作为依赖项是没有问题的,但如果有更好的方法,我认为我错过了上面的两个资源,我很想知道它。

我只是希望有一种更优雅的方式来维护不断增长的javascript,因为我厌倦了意大利面条;)

谢谢你的时间!

3 个答案:

答案 0 :(得分:0)

由于您要开发单页面应用程序,您将拥有许多可视模块,这些模块将在当前步骤中显示,然后它们将被其他模块替换。

您可以遵循MVC模式(模型 - 控制器 - 视图),每个可视元素都是一个单独的实体,具有自己的DOM操作代码和存储在不同类中的业务逻辑。

一种方法是:

<html>
  <head>
   ....
  </head>
  <body>
    <div id="content"> 
    <!--The main container view that can handle the replacement of smaller views -->
      <div id="toolbar"_container">
        <!-- container for menu bar or tool bar that can also has its contained 
             sub-views replaced -->
      </div>
      <div id="main_content_container">
        ....
      </div>
      <div id="properties_panel">
       .....
      </div>
    </div>      
  </body>
</html>

主容器可以容纳所有较小的容器,每个人都可以容纳一个具有自己的DOM操作代码的不同视图控制器(它还具有能够按需动态加载的优点,从而减少初始化加载时间)。

每个视图都可以有一个执行“操作”的模块,它将与第三个模块(可选)通信,这个模块将处理数据库,套接字,文件等的I / O.

希望它有所帮助!

答案 1 :(得分:0)

您可以使用Backbone.js,也可以浏览CQRS(和相关模式)以获得更多自定义,复杂和分离的解决方案。这一切都取决于您的应用程序的复杂性(以及潜在的未来增长)。

您还可以查看some of this posts。在一个具体的例子中有几个很好的针对你的问题;)

答案 2 :(得分:0)

保持业务逻辑和显示逻辑分离

这比DOM更适用。浏览器和Node中的许多API都是围绕触发事件或等待其他类型的异步工作来完成的。根据经验,如果您编写了大量匿名回调函数,那么您的代码可能不容易测试。

// hard to test
$('button').on('click', () => {
    $.getJSON('/path/to/data')
        .then(data => {
            $('#my-list').html('results: ' + data.join(', '));
        });
});

// testable; we can directly run fetchThings to see if it
// makes an AJAX request without having to trigger DOM
// events, and we can run showThings directly to see that it
// displays data in the DOM without doing an AJAX request
$('button').on('click', () => fetchThings(showThings));

function fetchThings(callback) {
    $.getJSON('/path/to/data').then(callback);
}

function showThings(data) {
    $('#my-list').html('results: ' + data.join(', '));
}

在异步代码中使用回调或承诺

解决此问题的最常用方法是将回调函数作为参数传递给异步运行的函数。在单元测试中,您可以在传递的回调中运行断言。

// hard to test; we don't know how long the AJAX request will run
function fetchData() {
    $.ajax({ url: '/path/to/data' });
}

// testable; we can pass a callback and run assertions inside it
function fetchDataWithCallback(callback) {
    $.ajax({
        url: '/path/to/data',
        success: callback,
    });
}

// also testable; we can run assertions when the returned Promise resolves
function fetchDataWithPromise() {
    return $.ajax({ url: '/path/to/data' });
}

Here is the details