dojo类机制模拟实现

24 篇文章 0 订阅
1 篇文章 0 订阅

 

 

偶然在infoq上看到朋友的文章《dojo类机制简介》,闲来无事,根据文章所讲,做了个dojo类机制的模拟实现。

主要实现以下功能:

定义类、定义类静态变量、实现单继承和多继承、调用父类方法 以及工具类方法和属性(isInstanceOf方法和declaredClass)。

代码如下:

 

//dojo类机制模拟实现

//--------工具类-------------
//创建命名空间
function createNS(path){
   if(!path)return null;
	var r ;
	if(typeof path == 'string') r = path.split('.');
	else if(path.constructor==Array) r = path;
	var currentPath = window;
	for(var i=0;i<r.length;i++){
	   currentPath[r[i]] = currentPath[r[i]] || {};
	  	currentPath = currentPath[r[i]];
	}
	return currentPath;
}
//掺元继承
function mix(s,d){
	for(var i in s){
		if(s[i]&&s.hasOwnProperty&&s.hasOwnProperty(i)) d[i] = s[i];
	}
}
//类式继承
function extend(subclass,superclass){
    var F = function(){};/*在此使用一个空函数,并将用它创建的一个对象实例插入到原型链中,这样做可以避免创建超类的新实例.因为1.超类的示例可能会比较大2.超类的构造函数有一些副作用3.或者执行一些需要大量计算的任务*/
    F.prototype = superclass.prototype;
    subclass.prototype = new F();
    subclass.prototype.constructor = superclass;

    //为类和对象增加父类引用'superclass'
    subclass.prototype.superclass = subclass.superclass = superclass.prototype;
    //对使用“superclass.prototype={method1:function(){...},...}”方式定义的类进行构造器属性修正
    if(superclass.prototype.constructor==Object.prototype.constructor){
        superclass.prototype.constructor = superclass;
    }
}
//-----------------------------------------------
//类机制实现:声明类
function declareClass(path,parent,config){
   if(!path) return;
   var declaredClass = path;                 //类标记
   var pathAndName = path.split('.');        //分拆包名和类名
   var className = pathAndName.pop();        //获取类名
   var ns = createNS(pathAndName)||window;   //根据传入类路径,创建命名空间
   //声明类的实现
   var clz =function(){
      //如果存在父类,首先调用父类的构造器方法。
      if(clz.superclass&&clz.superclass.constructor) clz.superclass.constructor.apply(this,arguments);
      //如果config参数中设置了声明类的构造器constructor方法,调用声明类的构造器方法。
      if(config.constructor) config.constructor.apply(this,arguments);
   };

   if(parent){
   	if(typeof parent=='function'){
   	  	extend(clz,parent);
   	}else if(parent.constructor==Array){
      	//如果参数设置了多个父类,使用第一个作为声明类的父类,其他使用掺元继承方式实现。
         extend(clz,parent[0]);
         for(var i=1;i<parent.length;i++)
            mix(parent[i].prototype,clz.prototype);
   	}
   }
   //调用父类相关方法
   clz.prototype.inherited = function(args){
      var caller =  arguments.callee.caller;
      var methodName = caller.nom;
      return this.superclass[methodName].call(this,args);
   };
   //isInstanceOf方法
   clz.prototype.isInstanceOf = function(c){
   	return (this instanceof c);
   }
   //将config定义的属性赋予声明类
   for(var p in config){
   	clz.prototype[p] = config[p];
   	//如果属性为函数,为函数属性增加'nom'属性,值为函数名的字符串
   	if(typeof config[p] =='function') clz.prototype[p].nom = p.toString();
   }
   //增加declaredClass标记属性
   clz.prototype.declaredClass = declaredClass;
   //将声明类加入到命名空间
   ns[className] = clz;
}
 
 

测试代码:

//---------------测试---------------------
//定义cn.hou.GrandParent类
declareClass("cn.hou.GrandParent",null,{
   sex:'male',
   familyInfo:{money:1},      //静态属性
   constructor:function(param){
   	this.sex = param.sex;
   },
   getSex:function(){
   	return this.sex;
   }
});

var gp = new cn.hou.GrandParent({sex:'man'});
console.log(gp.getSex());              //man
gp.familyInfo.money++;
var gp2 = new cn.hou.GrandParent({sex:'woman'});
console.log(gp2.getSex());             //woman
console.log(gp2.familyInfo.money);     //2

//掺元测试类
function TestMix(){}
TestMix.prototype.test = function(){console.log('TestMix.test');};
//定义cn.hou.Parent子类,继承cn.hou.GrandParent 和 TextMix
declareClass("cn.hou.Parent",[cn.hou.GrandParent,TestMix],{
   name:null,
   age:0,
   constructor:function(param){
      this.name = param.name;
      this.age = param.age;
   },
   getName:function(){
   	return this.name;
   },
   getAge:function(){
   	return this.age;
   },
   getSex:function(){
      //var sex = this.superclass.getSex.apply(this);//在没有以上inherited方法前,调用父类同名函数 的一种方法。
      var sex = this.inherited(arguments);     //通过 declareClass 声明函数定义的对象,可以使用inherited方法调用父类同名函数。
   	return 'parent getSex() called:'+sex;
   }
});

var p = new cn.hou.Parent({name:'test',age:22,sex:'男'});
console.log(p.declaredClass);             //cn.hou.Parent
console.log(p.getName());                 //test
console.log(p.getSex());                  //parent getSex() called:男
console.log(p instanceof cn.hou.Parent)   //true
console.log(p.isInstanceOf(cn.hou.Parent))//true
console.log(p instanceof TestMix)         //false
p.test();                                 //TestMix.test
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Dojo Datagrid 中实现数据删除功能,可以按照以下步骤进行: 1. 在 Datagrid 中添加一个列,用于显示删除按钮。 2. 在该列中定义一个自定义单元格模板,用于显示删除按钮。 3. 在该模板中添加一个点击事件处理程序,以便在单击删除按钮时触发删除操作。 4. 在删除操作处理程序中获取要删除的数据行,并将其从数据存储中删除。 以下是一个简单的示例代码,演示如何在 Dojo Datagrid 中实现数据删除功能: ```javascript require(["dojo/_base/lang", "dojo/_base/declare", "dojo/data/ItemFileWriteStore", "dojox/grid/DataGrid", "dojo/domReady!"], function(lang, declare, ItemFileWriteStore, DataGrid){ var data = { identifier: "id", items: [ { id: 1, name: "John Doe", age: 32 }, { id: 2, name: "Jane Smith", age: 25 }, { id: 3, name: "Bob Johnson", age: 45 } ] }; var store = new ItemFileWriteStore({data: data}); var grid = new DataGrid({ structure: [ { name: "Name", field: "name", width: "200px" }, { name: "Age", field: "age", width: "100px" }, { name: "Delete", field: "id", width: "100px", formatter: function(id){ return "<button data-dojo-type='dijit/form/Button'>Delete</button>"; }, cellType: dojox.grid.cells.Cell, editable: false, onClick: function(evt){ var row = grid.getItem(evt.rowIndex); store.deleteItem(row); store.save(); } } ], store: store, rowSelector: "20px" }, "grid"); grid.startup(); }); ``` 在这个示例中,我们添加了一个名为“Delete”的列,用于显示删除按钮。我们定义了一个自定义单元格模板,用于显示一个具有“Delete”标签的按钮。我们还添加了一个事件处理程序,以便在单击按钮时触发删除操作。在该处理程序中,我们获取要删除的数据行,并将其从数据存储中删除。最后,我们使用 ItemFileWriteStore 作为数据存储,并将其与 Datagrid 组件一起使用。 注意:该示例代码仅供参考,具体实现需要根据具体情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值