如何构建大型应用程序

时间:2014-05-28 10:57:46

标签: famo.us

我想知道如何构建我的应用程序。我应该使用自定义视图和一个将控制它们的主视图。或者将视图保存在灯箱中更好。我发现的所有示例都以某种方式限制了功能并呈现单个或几个屏幕。组织更大的应用程序的正确方法是什么?

2 个答案:

答案 0 :(得分:5)

我也想知道。

起点:

  • Famo.us应用程序在分层渲染树中构建。
  • Famo.us使用RequireJS模块。
  • Famo.us鼓励使用观看次数
    • 视图是可重用的组件。
    • 视图封装功能(以及渲染树的一部分)。
    • 视图使用事件进行通信。
    • 视图由选项对象初始化。

我们需要添加管理结构:

  • 业务逻辑
  • 非API功能,如REST api调用,音频,本地存储等。
  • 数据流:
    • 更新用户输入数据
    • 更新数据更改视图

模块,事件和松散耦合

目标:

  • 可扩展的应用程序结构。
  • 小型,独立,可测试的模块。
  • 促进代码的重复使用。
  • 轻松共享模块(只需删除项目文件)
  • 对其他Javascript框架没有依赖性

通常,模块之间存在紧密耦合:

  • 模块实例化并保留对另一个模块的引用
  • 模块跨越他们的语义边界
    • 了解特定REST api的视图
    • 使用特定模型代码(如Backbone)的视图(请参阅Taasky示例)

以下是如何避免这种情况:

  1. 模块在发生有趣事件(用户输入,数据更改等)时发出事件
  2. Mediator 会收听该事件
  3. Mediator调用另一个模块的公共API。
  4. 因此,它不会让View模块了解Backbone模型,而是发出如下的用户输入事件:

    1. Todo-Edit-View发出"用户输入"事件:"todo-update",{id:1,title:'Code'}
    2. Todo-Mediator听取此事件。
    3. Todo-Mediator调用Todo模块tasks.find({id:1}).update({title:'Code'})(例如使用Backbone)
    4. 规则

      • 有模块和调解员
      • 模块具有公共API并发出事件
      • API和事件保持其语义边界;即" updateTitle()"而不是" onBackboneModelChange()"
      • Mediator将应用程序耦合,即骨干模型更改为待办事项标题更新。
      • 调解员是单身人士
      • 一个应用程序可以有多个调解器。

      例如,像GMail这样的电子邮件应用程序可能会有

      的调解器
      • 聊天功能
      • 待办事项列表功能
      • 阅读电子邮件
      • 写作&发送电子邮件

      文件结构:

      /src
         /lib
         /services
         /mediators
         /layout
         /content
         /config
         /main.js
      

      模块类型:

      • 服务:一个独立的模块,用于封装非UI功能,例如:LocalStorage,Ajax,Web Audio等。
      • 布局:内容的布局,动画和定位,例如:ScrollView,HeaderFooterView等
      • 内容:应用的实际内容:渲染树的叶节点(曲面)。

      请注意布局内容之间的区别。通过分离UI组件和&从实际内容布局,重用UI模式变得容易,如侧面板,弹出窗口,导航栏,粘贴标题,滚动视图等。

      此外,我建议为每个仅包含结构布局创建*.css,并尽量减少主题。所有主题都可以在config/theme.css中覆盖/扩展,因此很容易重新设置应用。

      其他代码:

      • Mediator :使用事件和公共API耦合模块。
      • 配置:包含初始化时整个应用中使用的所有选项。
      • main.js :引导应用。

      Main.js中的Bootstrap应用程序

      1. 创建调解员
      2. 创建服务
      3. 构建渲染树
      4. 模块生命周期

        • 模块必须包含在一个文件中,即不要依赖于外部库!

        创建模块时,它会向所有调解员宣布其存在。我们使用Famo.us Engine发出全局事件。这将是唯一所需的依赖项!

         Engine.trigger('created',this)
        

        当模块被销毁时,它会向所有调解员宣布销毁。

         Engine.trigger('destroyed',this)
        

        调解员收听createddestroyed事件并将模块粘合在一起:

         var someDataModule; // Backbone or whatever
         Engine.on('create',function(module){
            if(module instance of SomeDataModule) {
                var someDataModule = module;
            }
            if(module instanceof TodoView) {
              module.on('change-title',function({id:id,title:title}){
                  someDataModule.find({id:id}).set('title',title);
              })
            }
         }) 
        

        在简单的调解器中,您可以按顺序初始化模块(即SomeDataModule之前的TodoView)。但是,在更复杂的情况下,您可能需要使用Promise来结合所有内容。

        关于依赖性的注释

        "有三个例外;自包含"模块:

        1. 布局内容模块允许具有层次依赖关系。父母可以初始化孩子,并期待这些孩子的某些事件。 ListView可能会初始化ItemView并处理ItemRemoved个事件。

        2. 服务可以是其他服务的Facade / Adapter。例如,DataService可能为RestApiService提供简化,抽象和安全层。

        3. 当然,调解员有硬连线依赖,因为他们结合了应用程序!

答案 1 :(得分:1)

Famo.us专注于UI,所以你最好寻找一个MVC模式来获得更好的结构,特别是在大型项目上,实际上因为Famo.us非常年轻,它只与Angular集成:

http://famo.us/integrations/angular/

但众所周知,他们将在不久的将来添加其他MVC集成

尝试Angular并查看它是否是您需要的,这是一个非常好的MVC框架,我的建议是首先学习Angular至少基础知识(http://angularjs.org/然后在Famo.us大学之后({{3})你可以理解这种整合