【问题标题】:Code organization in JavaScript: MVC? Self-rendering components?JavaScript 中的代码组织:MVC?自渲染组件?
【发布时间】:2011-07-17 23:58:28
【问题描述】:

我正在构建一个非常依赖 JS 的 Web 应用程序。我说这是 JS-heavy,因为绝大多数工作都是在客户端完成的(尽管有一些使用 AJAX 和 XMPP 来回同步到服务器)。

这是我第一次在纯 JS 中(使用 jQuery)构建这种规模的东西,所以我开始使用 MVC 以模仿 Rails 的方式组织我的代码。例如,如果用户单击一个按钮,则会在 Controller 对象中调用一个方法,该方法从模型中提取一些数据,然后将数据传递给视图函数。我几乎对所有事情都这样做,甚至是像显示一个小弹出窗口这样的琐碎操作。

几个月后,我觉得我没有充分利用这门语言。我真的应该像网页一样呈现我的视图吗?

将视图分解为组件似乎更有意义,这些组件将是 Javascript 对象/函数的实例。例如,而不是...

var itemListHTML = '<ul id="item-list"><li>item1</li><li>item2</li></ul>';
jQuery('#container').html(itemListHTML);

...我本来可以...

components.itemList.render();

所以这里只有一个名为itemList 的组件。由于所有数据都存储在客户端上,因此这些组件可以立即访问创建和管理自身所需的所有数据。我想我仍然会使用 MVC,但不需要负责整个视图的控制器操作。如果我想刷新 UI 的一部分,我只需调用 whateverComponentControlsThatArea.redraw() 并重新呈现自己。

我确信以前有人这样做过。这种代码组织方式有名称吗?有关如何实施它的任何指南或最佳实践?

【问题讨论】:

标签: javascript jquery model-view-controller components code-organization


【解决方案1】:

现在有许多可用的 javascript MVC 框架
例如JavaScriptMVCPureMVCSammy.js
通常通过某种模板引擎处理视图或子视图的呈现。
JavaScriptMVC 有一个模块EJS,它以ERB 为模型,我发现它非常有用。模板可以编译成函数以加快生产速度。
还有其他模板解决方案,例如 John Resig's Micro-Templatingmany more

如果还不算太晚,我建议您使用其中一种框架。我已经在几个项目中使用了 JavaScriptMVC,并且可以推荐它(文档需要一些时间来适应)

【讨论】:

    【解决方案2】:

    您真的应该研究 jquery.tmpl (http://api.jquery.com/jquery.tmpl/) 以创建适合构建视图渲染的快速 javascript 模板。

    【讨论】:

      【解决方案3】:

      聚会有点晚了,但我这里有 0.02 美元,我不知道该怎么处理...

      暂时忘记(典型的)Web-MVC(即:RailsMVC 等):

      考虑到 JavaScript 可以都驻留在同一个地方,并且您不必担心确定路由和类实例化(除非您真的想这样做)。

      理想情况下,从软件的角度来看,您希望 MVC 做的是将用户所做的事情与构成内容的内容(基于动作)和构成视图的内容(基于动作)分开)。

      没有什么说你不能有多个视图,甚至你不能有一个包含多个视图的视图(可能使用模板,或者是功能生成的,并附加到一个 DOM 节点 - 要么是有效)。

      在一个简单的伪示例中,而不是具有如下所示的流程:

      动作加载控制器 -> 控制器加载模型 -> 控制器查询模型 -> 模型回答控制器 -> 控制器加载视图 -> 控制器将数据馈送到视图 -> 视图将页面发送到控制器 -> 控制器输出页面

      为什么不这样:

      Controller 监听 Action (addEventListener) -> Controller 将 Action 变成 State-Logic -> Controller 通知 Model (observer) OR Model Polls Controller -> Model 根据逻辑改变状态,并收集/排序所有数据 -> Model Notifies View (observer) OR View Polls Model -> View Changes State based on Logic -> View Renders all Components, based on Data + ViewState (innerHTML OR documentFragment)。

      它看起来有点长,但实际上,一切都很好而且分开。 使用视图(或视图管理器,或者你想怎么想)来规定页面上的窗口、每个窗口的组成方式、数据的去向、每篇文章的内部、每个窗口中...

      ...现在你有一个 MVC 模式,但你也有能力说:

      View["mainpage"] = {
      
          data : { tweets : [{id:...}...]/* et cetera - pushed by Model, not Controller */ },
          layout : [ "Header", "Carousel", "Articles", "TwitterFeed", "RSSFeed", "Footer" ],
      
          // if your system is this clean, you could even prototype the content-builders
          // rather than defining them in each ViewState - you'd just need layout, then
          buildPage : function () {
              var page = document.createDocumentFragment();
              for (/* everything in this.layout */) {
                  View.build[this.layout[i]](this.data, page);
              }
              document.body.appendChild(page);
          },
      
          cleanUp : function () { /* fancy or simple DOM cleaning for state-change */ },
      
          // grabs SubView by expected handle (id="tweetfeed" or whatever) and replaces it
          // observer functionality, for views to automatically update as data changes
          updateView : function (view, newData) { ... },
      
          addData : function (data) { this.data = data; }, // for Observer
      
          /* Observer - if you want to run the WHOLE site with AJAX from index.html
           * clean up old (ex:"main") page and build and/or transition new (ex:"media") page
           * could be unique for each page, for custom transitions, or just prototype it */
          changeState : function (newState, newData) {
              View["mainpage"].cleanUp();
              View[newState].addData( newData );
              View[newState].buildPage();
          }
      }
      

      现在您已经定义了整个主页。 当然,不仅要维护主页的定义,还要维护每个页面/部分的定义,这将是一项额外的工作。 ...然后,您需要创建将创建每个子视图的功能——但基于组件的设计正是您所要求的。 本质上,对于每个小部件,它都有自己的构建逻辑。 这就是视图的作用——它们要么有一个可以重复使用的单独模板,要么有一个每次都以相同方式工作的函数。

      原子视图是您处理构建 1 个项目(1 个推文、1 个帖子、1 个商店项目)并为此构建视图的函数。 让 Single_Tweet 视图连续 20 次向页面发布一条推文对于 JS 性能来说是一个的想法。

      但是,让 Single_Tweet 视图将推文按顺序推送到 Twitter_Feed 视图放在网站上的 Tweets 数组中是正常的。

      如果你的页面是视图,由视图的小部件组成,由视图的原子单元组成,那就更好了。 当所有这些都发生在 DOM 之外(所以是 innerHTML 或 documentFragment)。

      最好的框架是您以这种方式定义页面的框架,但您也可以随时根据模型的数据推送更新单个小部件。

      这就是 AJAX 的美妙之处——老式的 MVC 可以发生,没有一个无所不知的控制器。

      控制器只保存一个按键列表、鼠标坐标、点击按钮的意图...... 它告诉模型发生了什么事。 模型会处理所有与状态/数据/数据操作(排序)相关的事情,并将新状态或数据提供给视图,视图会按照您指定的顺序将其全部接收并放入 HTML。

      就是这样。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-08
        • 1970-01-01
        • 1970-01-01
        • 2023-03-07
        相关资源
        最近更新 更多