Javascript代码组织数据驱动的应用程序

Gio*_*mio 15 javascript asp.net-mvc jquery design-patterns kendo-ui

我目前正在研究中/大规模数据驱动的 Asp.net MVC应用程序的前端,我对正确的代码组织/设计模式有所怀疑.Web应用程序由多个页面组成,其中包含使用Razor模板定义的许多Kendo UI MVC小部件.

对于那些不熟悉Kendo的人,剃刀语法被翻译为Javascript,如下面的片段: Kendo服务器端包装器

我在我的脚本文件夹中定义了两个主要文件夹,我按如下方式构建了我的js文件:

  • shared //包含共享的js文件-file1.js -file2.js

  • 页面//每页一个文件

    • page1.js
    • page2.js
    • ...
    • Ticket.js //第4页:)

每个js文件都是使用以下模式定义的单独模块:
注意:内部init函数将每个回调函数注册到窗口事件,偶尔也会注册一个$(document).ready(function(){})块.

;(function () {
    "use strict";

    function Ticket(settings) {
        this.currentPageUrls = settings.currentPageUrls;
        this.currentPageMessages = settings.currentPageMessages;
        this.currentPageEnums = settings.currentPageEnums;
        this.currentPageParameters = settings.currentPageParameters;         


        this.gridManager = new window.gridManager(); //usage of shared modules

        this.init();
    }

    Ticket.prototype.init = function () {           

            $("form").on("submit", function () {
                $(".window-content-sandbox").addClass("k-loading");
            });

            ...
    }    

    Ticket.prototype.onRequestStart = function (e) {

        ...
    }

    //private functions definition
    function private(a, b, c){

    }

    window.Ticket = Ticket;
}());   
Run Code Online (Sandbox Code Playgroud)

一旦我需要在模块中定义的Javascript函数,我就在页面中包含相关的Javascript文件.我的对象的一个​​istance存储在一个变量中,最重要的是,一个函数绑定到widget事件(参见:onRequestStart).

HTML/JAVASCRIPT

@(Html.Kendo().DropDownList()
      .Name("Users")
      .DataValueField("Id")
      .DataTextField("Username")
      .DataSource(d => d.Read(r => r.Action("UsersAsJson", "User"))
                        .Events(e => e.RequestStart("onRequestStart"))))



var settings = {};

var ticket = new window.Ticket(settings);

function onRequestStart(e){
    ticket.onRequestStart(e);
}
Run Code Online (Sandbox Code Playgroud)

我觉得我的设计模式可能和其他前端delevoper一样不友好,主要是因为我选择不在Jquery插件中实现Javascript模块.

首先,我做错了吗?
第二,我的设计模式是否适合Javascript测试框架?
第三,哪些是Jquery插件的必备方案?

更新

通过上面的Razor语法添加了Javascript输出.

代码段

Tim*_*len 5

文件夹结构

在功能(共享)和模块(模块化方法)方面,开发或应用程序代码应代表您在HTML中可以遇到的内容.对解决方案进行简单的ctrl + f应该会产生所有可能的更改.根据多年来的经验,我个人更喜欢将其划分为:

  • app (应用程序代码)
    • 课程(可重复使用)
    • 模块(单身)
  • lib (包管理器/ grunt/gulp/...)
    • jquery (正确的库名/未分隔的dist文件或根文件)
    • 剑道

文件名

代表什么做了什么,并且能够在眨眼之间重复使用它将会缩短你的开发时间.选择合适的名字有价值,因为我相信你知道.我的文件名总是以namespace通常的简短开头,然后是可重复使用的"搜索"术语:

  • 应用程序/原型
    • ns.calendar.js (多个配置)
    • ns.maps.js (组合或单次使用)
    • ns.places.js (表格或地图附加组件)
    • ns.validation.js (多种形式和一般处理)
  • 应用程序/单身
    • ns.cookiebox.js (单个配置)
    • ns.socialmedia.js (单个配置)
    • ns.dom.js (为dom更正,全局调整大小事件,小部件,...提供了一个位置)

要添加,您所谓的共享,是指全球化的功能.一个很好的例子是使用下划线库.或者自己创建一个函数集合(设备检测,节流,一般帮助)以在整个项目中重用=> ns.fn.js由于你只在整个命名空间中添加它们一次,它也被构建为单例并且可以添加到modules文件夹或直接在app根目录中.

作为最后添加的一个加载程序文件,用于在app根目录中启动你的控制点=> ns.load.js.此文件包含单个DOM ready事件以绑定原型和模块.

所以你可能想重新考虑分成页面的想法.相信我,我一直在那里.在某些时候,您会注意到功能如何变得太大,以便分别配置所有页面并因此重复.

文件结构

说实话,我喜欢@TxRegex的提示1,答案最多,只需添加一小部分来绑定命名空间,并在文件加载时将其从文件传递给文件.

核心原则:IIFE绑定到窗口对象

window.NameSpace = (function($, ns){
    'strict'
    function private(){}
    var x;
    ns.SearchTerm = {};
    return ns;
}(window.jQuery, window.NameSpace || {}));
Run Code Online (Sandbox Code Playgroud)

有关更多示例代码,我想指出我的github帐户.

捆绑

尝试实现从lib到app的单个捆绑和缩小文件,加载到headon asyncfor production版本中.使用分离和未分解的脚本文件defer进行开发和调试.如果执行此操作,则必须避免整个项目中具有全局依赖性的内联脚本.

  • 路径到js/lib/**/*.js(通常分开以保持顺序)
  • js/app/ns.load.js的路径
  • js/app/ns.fn.js的路径
  • 路径到js/app/**/*.js(自动更新捆绑包)

输出=> ns.bundle.js => ns.bundle.min.js

这样你就可以避免JavaScript中的渲染阻塞问题并加快加载过程,从而加速搜索引擎优化.此外,您还可以动态组合移动布局和桌面布局的功能,而不会出现内存问题或不稳定的行为.从加载器文件调用实例时,实际上很好地缩小并产生很少的开销.由于单个包将在整个页面中缓存,因此所有这些都取决于您可以从包中删除多少依赖项或库.理想情况下适用于可以共享代码并插入不同项目的中型和大型项目.

在这个更多信息另一篇文章.

结论

首先,我做错了吗?

  • 完全没有,你的模块化方法似乎没问题......
  • 它缺少一个全局命名空间,如果没有至少一个,很难避免.您为每个模块创建一个,但最好将它们全部分组到一个名称空间下,这样您就可以将库代码与窗口对象中的应用程序代码区分开来.
  • 剑道似乎创建内联脚本?你不能反击放置服务器端吗?

第二,我的设计模式是否适合Javascript测试框架?

  • 除了Kendo实例,您可以添加一个层用于测试目的.请记住,如果jQuery是你的依赖内联,你将不得不渲染阻止它的加载.否则=>jQuery is undefined
  • 如果无法控制内联脚本,请从捆绑包中排除Kendo依赖项.转到</body>捆绑解决方案.

第三,哪些是Jquery插件的必备方案?

  • 模块化方法
  • 多个实例的可配置方法(提示:从逻辑中移动所有字符串,查看Kendo如何使用对象文字)
  • 包管理员将"垃圾"与"黄金"分开
  • grunt/gulp/...设置从js中分离scss和css
  • 尝试实现数据属性绑定,因此一旦编写完毕,就可以通过HTML配置新实例.

写一次,在必要时轻松适应并配置充足!