【前端】Javascript MVC模式之我见

什么是MVC?

MVC是一种设计模式,即MODEL(模型)、VIEW(视图)、CONTROLLER(控制器)。

MVC模式让每一层做好一件事情,层与层之间保持松耦合,让代码更具可维护性。


问题:

如何划分MVC?

如何命名空间?在团队开发中,有可能会有命名冲突。

所以我们需要在window里面建立java中类似工程的东西,工程下面又有各个子项目


要实现:

简单方式实现对各子项目的MVC各模块装,取功能


实验1:

首先,我希望我的工程依托于我的工具

(function() {
    var Util = function() {};

    Util.prototype = {
	constructor : Util,
        // 创建工程和项目
        project : function(project, page) {
            this[project] = {};          // 工程
            this[project][page] = {};    // 子项目
        },
    }
	
    $$ = new Util();
}) ();
$$.project("VideoPlayer", "video");

console.log(window);

运行结果:

这样的结果是我们希望的。在VideoPlayer工程下有video项目


实验2:

除video外我还想建立一个Student,再调用这个函数会覆盖video,,所以  必须加判断!

将project方法中建立项目、工程代码改为如下:

if (this[project] == undefined) {
    this[project] = {};
}
if (this[project][page] == undefined) {
	this[project][page] = {}
}

这个时候就可以存在两个子项目了,这两个独立的项目应该有相同的内容

$$.project("VideoPlayer", "video");
$$.project("VideoPlayer", "student");

console.log(window);

运行:


实验3:

继续,当然我的每一个子项目都要包含MVC三个模块,所以,我需要在我每个子工程下建立三个类,所以代码更新至如下

(function() {
    var Util = function() {};

    var Mvc = function() {
        this.model = {};
        this.view = {};
        this.control = {};
    };

    Util.prototype = {
        constructor : Util,

        // 创建工程,创建项目
        project : function(project, page) {
            if (this[project] == undefined) {
                this[project] = {};
            }
            if (this[project][page] == undefined) {
                this[project][page] = new Mvc;
            }
        },
    };
    $$ = new Util();
}) ();
$$.project("VideoPlayer", "video");
$$.project("VideoPlayer", "student");

console.log(window);

结果如下:


实验4:

目前咱们只搭了个台子,往后还要给他们(MVC)加东西,因此,还需要装和取两种操作
在model里想加学生信息,而且要方便我以后取,因此要在model里加方法

当然,在实际使用这个工具的时候,咱们肯定是要在持续建类,为了方便建立,我们当然要能时刻定位当下目录

此时工具中还应给出在MVC各模块下增加类的方法

(function() {
    var Util = function() {
	    this.prt = Util.prototype;
    };

    var Mvc = function() {
	    this.model = {};
	    this.view = {};
	    this.control = {};
    };

    Util.prototype = {
	    constructor : Util,

	    currentPage : this,   //定位操作

	    // 创建工程,创建项目
	    project : function(project, page) {
	    	if (this[project] == undefined) {
	    		this[project] = {};
	    	}
	    	if (this[project][page] == undefined) {
	    		this[project][page] = new Mvc;
	    	}
			
	    	this.prt.currentPage = this[project][page];  
                //定位到当下目录
		//为什么不用this,对于左值,会先在当前对象成员里找,找不到则立刻建立
		// currenPage的作用,通过它可以知道当前处理的位置,相当于目录转换,类似与java包
	    },
	    model : function(className, Klass) {
	  	 this.prt.currentPage.model[className] = Klass;
		 var klass = this.prt.currentPage.model[className];
		 klass.obj = {};
		 // 建立对象
	    },
    };
    $$ = new Util();
}) ();
$$.project("VideoPlayer", "video");
$$.project("VideoPlayer", "student");

$$.model("StudentModel", function() {
 	this.name = '';
 	this.sex = true;
});

console.log(window);

运行结果: 

看,每个项目其原型空间中(prototype)都存在prt,他表示目前正在处理的位置,相当于目录转换,和java包异曲同工


实验5:

建立是有了,可取呢?

如果model函数中只传来一个参数,那我们就要执行取操作

有没有发现,这样越来越像Java了,可不可以在建立工程的时候把参数定成XXXX.XXXX.XXXX的形式,建立model的时候参数也定作这样,在工具中我们只用处理传来的字符串,建立工程和类

这样不就形成了java包的模式了

model : function (className, Klass) {
        if (arguments.length == 1) {
	    var index = className.indexOf(".");
    	    if (index == -1) {
	        return this.prt.currentPage.model[className];
	    }
	    var objName = className.substring(index+1);
	    className = className.substring(0, index);
	    return this.prt.currentPage.model[className][objName];
	}
	if (Klass instanceof Function) {
	    this.prt.currentPage.model[className] = Klass;
	    return Klass;
	}
	var classNames = className.split(".");
	className = classNames[0];
	var objName = classNames[1];
	this.prt.currentPage.model[className][objName] = Klass;
},

咱们只看model函数,当参数长度为1时,model用来获取model对象,若长度大于1,当然通过字符串路径添加model类了。


所有代码:

(function () {
	var Util = function () {
		this.prt = Util.prototype;
	};

	var Mvc = function () {
		this.model = {};
		this.view = {};
		this.action = {};
	};

	Util.prototype = {
		constructor : Util,
		currentPage : this,
		package : function (packageName) {
			var current = this;
			var packages = packageName.split(".");
			for (var index in packages) {
				var page = packages[index];
				if (current[page] == undefined) {
					current[page] = {};
				}
				current = current[page];
			}
			Mvc.call(current);
			this.prt.currentPage = current;
		},
		model : function (className, Klass) {
			if (arguments.length == 1) {
				var index = className.indexOf(".");
				if (index == -1) {
					return this.prt.currentPage.model[className];
				}
				var objName = className.substring(index+1);
				className = className.substring(0, index);
				return this.prt.currentPage.model[className][objName];
			}
			if (Klass instanceof Function) {
				this.prt.currentPage.model[className] = Klass;
				return Klass;
			}
			var classNames = className.split(".");
			className = classNames[0];
			var objName = classNames[1];
			this.prt.currentPage.model[className][objName] = Klass;
		},
	};

	$$ = new Util();
}) ();
$$.package("com.mec.video.core");
$$.package("com.mec.student");

$$.model("StudentModel", function (name, sex) {
 	this.name = name;
 	this.sex = sex;
});

var StudentModel = $$.model("StudentModel");
$$.model("StudentModel.student", new StudentModel("张三", true));

console.log(window);

运行结果:

总结:

这样运用,把js尽量往java上靠

看上图$$下有我们的整个工程,里面有包名称,包内有MVC,model里放所有类及其对象

对于view层,可以开始将html中带id的element拿出来形成键值对,装入view,不用每次查找再getElementById了(但对于一些后来添加的或更改的就必须要刷新view了,可以在get找不到标签的时候再刷新)

 

这样就构建了一个简单的前端MVC框架。

根据学习笔记,写出了这篇博文。若有问题,欢迎指教!

全部评论

相关推荐

10-21 23:48
蚌埠坦克学院
csgq:可能没hc了 昨天一面完秒挂
点赞 评论 收藏
分享
10-25 00:32
香梨想要offer:感觉考研以后好好学 后面能乱杀,目前这简历有点难
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务