Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/423.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript:模型视图控制器(MVC)重构现有代码策略_Javascript_Model View Controller_Revealing Prototype - Fatal编程技术网

JavaScript:模型视图控制器(MVC)重构现有代码策略

JavaScript:模型视图控制器(MVC)重构现有代码策略,javascript,model-view-controller,revealing-prototype,Javascript,Model View Controller,Revealing Prototype,我将重新考虑一个带有Python/Django后端的大型单页web应用程序。我不想使用Angular.js、JavaScriptMVC、BackBone.js等任何现有框架。已经有大量的HTML和JavaScript代码,要遵守它们的方法需要很长时间 我已经使用揭示原型模式开发了一个MVC架构。您可以在此处看到一个简化的工作演示和源代码:。有一些_vars打算成为公共vars,我只是没有时间将它们全部重命名,所以请忽略下划线的含义 我的MVC是:[模型][控制器][视图] 示例中的体系结构实现了

我将重新考虑一个带有Python/Django后端的大型单页web应用程序。我不想使用Angular.js、JavaScriptMVC、BackBone.js等任何现有框架。已经有大量的HTML和JavaScript代码,要遵守它们的方法需要很长时间

我已经使用揭示原型模式开发了一个MVC架构。您可以在此处看到一个简化的工作演示和源代码:。有一些_vars打算成为公共vars,我只是没有时间将它们全部重命名,所以请忽略下划线的含义

我的MVC是:[模型][控制器][视图]

示例中的体系结构实现了我想要的一切:

  • 类对象(FolderManager),它可以利用自己的模型类对象、视图类对象和控制器类对象
  • 每个FolderManager都有私有、内部公共和公共成员
  • 模型、视图和控制器只能访问主类决定它们需要的部分
  • FolderManager自动实例化其模型视图和控制器
  • FolderManager可以有多个模型、视图和控制器
  • 这种架构允许我轻松地将现有的意大利面代码复制/粘贴到新格式中
  • 我不喜欢和需要帮助的方面:

  • FolderManager的构造函数使用了一些技巧来实现内部公共成员。
    • 有没有其他/更好的方法来实现这一点?(可能是通过继承)
    • 自动实现它的一种方法:ie var FolderManager=Class({})。
      • 我尝试采用上面的技术来选择我的公共变量和内部变量,并将它们应用到构造函数中。我无法让它在实例化时构造函数可以使用self的地方工作,以便我可以将它传递给模型、视图和控制器。(这将解决问题,请查找下面的代码)
        
        //创建公共变量(将其移动到类方法)
        对于(公共变量中的变量v){this[v]=公共变量[v];}
        //创建内部变量(将其移动到类方法)
        var self={};
        对于(公共变量中的v){self[v]=公共变量[v];}
        对于(v在内部变量中){self[v]=内部变量[v];}
        
  • 我正在实例化构造函数中的模型、视图和控制器,它可以工作,我喜欢代码的简单性,但这是上面第1项的原因。我很难理解/实现扩展类的方法。任何修改此策略的建议都将不胜感激
  • 主类构造函数:

    var FolderManager = function(name){
        //self instantiate
        if (!(this instanceof FolderManager)) return new FolderManager(name);
    
        //private vars
        var privateVar = 'private vars are available only to the \"'+name+'\" constructor.';
    
        //internal public vars
        var internal_vars={
            internalVar:'internal_vars are available only to internal classes.',
            sortable:false
        };
        //public vars
        var public_vars = {
            publicVar:'public_vars are available to everything.',
            toString:name,
            name:name
        };
    
        //create public vars (move this to a Class Method)
        for (var v in public_vars){this[v] = public_vars[v];}
        //create internal vars (move this to a Class Method)
        var self = {};
        for (v in public_vars){self[v] = public_vars[v];}
        for (v in internal_vars){self[v] = internal_vars[v];}
    
        //instantiate private classes with internalally public vars
        //and the classes they each need to have access to
        var model = new FolderManagerModel(self);
        var view = new FolderManagerView(self, model);
        var cont = new FolderManagerCont(self, model, view);
    
        //provide public access to internal classes as required
        this.refresh = model.refresh.bind(model)
        this.out = view.out.bind(view)
    
        // init model
        this.refresh();
    };
    
    var Class = function (className, methods, options) {
    
        options = options || {};
        options.ret = options.ret !== false;
        options.context = options.context || window
    
        //compile the constructor & internalMembers
        var init = function () {
            console.log('Class() is building:', this.constructor.name);
            //provide inernal object for constructor
            this.internal = {}
            this.constructor.apply(this, arguments);
            //remove internal from public scope
            var int = this.internal
            delete this.internal
            //populate self with this and internal vars
            var self = {pub:this, int:{}};
            for (var v in int){
                self.int[v] = int[v];
            }
            // Instantiate internalMembers with self
            var internalClass = methods.internalClass;
            if (internalClass) internalClass.call(this, self);
        };
    
        //create constructor function with className (fixes class name in debugger)
        //also includes self instantiation
        var klass = new Function("init", "return function " + className + "(name){ if (!(this instanceof " + className + ")) return new " + className + "(name);init.apply(this,arguments) };")(init);
    
        //create prototype from Class method
        var prototype = methods.prototype;
        if (prototype) klass.prototype = new prototype();
    
        //add other Class methods to prototype
        var exclude = ['internalClass', 'initialize', 'prototype'];
        for (var property in methods) {
            if (exclude.indexOf(property) == -1) {
                klass.prototype[property] = methods[property];
            }
        }
    
        if (options.ret) return klass; //return the class
        else options.context[className] = klass; //create the class
    };
    
    模型构造函数和原型(视图和控制器用户格式相同,完整代码见演示):


    更新: 我已经完成了我的类构造函数,以消除一些腿部工作,并修复了我的内部公共变量问题。我剩下的一个问题是:为了让调试器显示对象的类名,我需要为该类创建一个名为的函数。唯一的方法是使用新的function()构造函数。我理解由于性能问题,这不是一个好的做法,因为每次调用函数时都需要对其进行解析。但是,由于我在构造函数中使用它,因此仅在实例化时调用(一次)。这仍然是一个坏主意,还是这是一个合适的情况

    类构造函数:

    var FolderManager = function(name){
        //self instantiate
        if (!(this instanceof FolderManager)) return new FolderManager(name);
    
        //private vars
        var privateVar = 'private vars are available only to the \"'+name+'\" constructor.';
    
        //internal public vars
        var internal_vars={
            internalVar:'internal_vars are available only to internal classes.',
            sortable:false
        };
        //public vars
        var public_vars = {
            publicVar:'public_vars are available to everything.',
            toString:name,
            name:name
        };
    
        //create public vars (move this to a Class Method)
        for (var v in public_vars){this[v] = public_vars[v];}
        //create internal vars (move this to a Class Method)
        var self = {};
        for (v in public_vars){self[v] = public_vars[v];}
        for (v in internal_vars){self[v] = internal_vars[v];}
    
        //instantiate private classes with internalally public vars
        //and the classes they each need to have access to
        var model = new FolderManagerModel(self);
        var view = new FolderManagerView(self, model);
        var cont = new FolderManagerCont(self, model, view);
    
        //provide public access to internal classes as required
        this.refresh = model.refresh.bind(model)
        this.out = view.out.bind(view)
    
        // init model
        this.refresh();
    };
    
    var Class = function (className, methods, options) {
    
        options = options || {};
        options.ret = options.ret !== false;
        options.context = options.context || window
    
        //compile the constructor & internalMembers
        var init = function () {
            console.log('Class() is building:', this.constructor.name);
            //provide inernal object for constructor
            this.internal = {}
            this.constructor.apply(this, arguments);
            //remove internal from public scope
            var int = this.internal
            delete this.internal
            //populate self with this and internal vars
            var self = {pub:this, int:{}};
            for (var v in int){
                self.int[v] = int[v];
            }
            // Instantiate internalMembers with self
            var internalClass = methods.internalClass;
            if (internalClass) internalClass.call(this, self);
        };
    
        //create constructor function with className (fixes class name in debugger)
        //also includes self instantiation
        var klass = new Function("init", "return function " + className + "(name){ if (!(this instanceof " + className + ")) return new " + className + "(name);init.apply(this,arguments) };")(init);
    
        //create prototype from Class method
        var prototype = methods.prototype;
        if (prototype) klass.prototype = new prototype();
    
        //add other Class methods to prototype
        var exclude = ['internalClass', 'initialize', 'prototype'];
        for (var property in methods) {
            if (exclude.indexOf(property) == -1) {
                klass.prototype[property] = methods[property];
            }
        }
    
        if (options.ret) return klass; //return the class
        else options.context[className] = klass; //create the class
    };
    
    它的用途如下:

    Class('FolderManager', {
    
        constructor: function FolderManager(name) {
    
            //private vars
            var privateVar = 'this value is only accesable to the \"'+name+'\" constructor.';
    
            //public internal mthods and vars
            this.internal.internalVar='this value is only accesable to internal classes.',
            this.internal.sortable=false;
    
            //public vars
            this.publicVar='this is a public vlue';
            this.name = name;
        },
        internalClass:function(self){
    
           //instantiate private classes
            var model = new FolderManagerModel(self);
            var view = new FolderManagerView(self, model);
            var cont = new FolderManagerCont(self, model, view);
    
            //public access private class methods
            this.refresh = model.refresh.bind(model);
            this.out = view.out.bind(view);
            this.model = model;
    
            // init model
            this.refresh();
        },
        prototype:function(){
    
            // all static vars and methods here
        },
    },{ret:false,context:this});
    

    完整的工作演示:

    我相信您对这一切的设计有点过火


    不久前,我创建了视图、控制器、路由和作用域。检查一下,它只有75行代码。

    也是MVC的简单实现

    Html:

    型号:

    var model = {
     calculate: function () {
        var x  = $("input#input").val();
        return x * 2;
     }
    };
    
    控制器:

    var controller = {
      action: function () {
        $("button#showResult").click(function () {
            var res = model.calculate();
            view.showNumber(res);
        });
      }
    };
    

    请把代码的相关部分(可能带有缩写的值)放在你的问题中。我不明白为什么“Main”应该有任何私有或公共变量。只要把它们放在模型上就可以了…谢谢你的反馈@Bergi。添加main是解决javascripts缺少私有和内部成员的问题的方法。我来自动作脚本/java背景。由于该应用程序将有许多组件,因此该策略将尽可能保持全球范围的未经打磨。我以前从未见过这种情况,我想知道我是否犯了错误。您认为这种策略有什么缺点吗?我认为为应用程序设置
    Main
    没有什么错,但它不需要有太多的状态和属性。@Bergi,再次感谢。请看上面的更新,让我知道你对类构造函数的看法。SPA看起来很酷。不过,正如我刚才所说,我并没有试图用板条箱包装一个框架,也不能使用任何现有的框架。我正在使用的代码库已经有了自己的路由方法,而且非常复杂。设置所有控制器并定义HTML。我只需要将所有JavaScript插入MVC。这提供了一个空白画布,在这里我可以复制和粘贴所有的方法和变量。我非常感谢您抽出时间来查看。对于小任务,请在不同的文件中使用单独的逻辑。通过ajax在主文件中包含文件
    var controller = {
      action: function () {
        $("button#showResult").click(function () {
            var res = model.calculate();
            view.showNumber(res);
        });
      }
    };