Maison  >  Article  >  interface Web  >  Explication détaillée des principaux exemples de la façon dont javascript implémente les événements extjs

Explication détaillée des principaux exemples de la façon dont javascript implémente les événements extjs

伊谢尔伦
伊谢尔伦original
2017-07-20 15:33:481431parcourir

La fonction qu'Extjs implémente l'héritage est une fonction très centrale Ext.extend. La méthode extend a deux versions reconstruites, la première accepte deux paramètres, la première est extend (superclasse de fonction, remplacements d'objets) et la seconde. est extend(Superclasse de fonction, Remplacements d'objets). La première est extend(Sous-classe de fonctions, Superclasse de fonctions, Remplacements d'objets) : La deuxième version est basée sur la sous-classe. La superclasse est le constructeur de la superclasse, les remplacements sont un objet et les attributs à l'intérieur doivent remplacer les attributs de la classe parent. Une sous-classe qui hérite d'une classe parent possède toutes les méthodes du prototype de la classe parent. Et les sous-classes peuvent remplacer les méthodes de la classe parent (override). De plus, chaque objet de la sous-classe peut également remplacer les méthodes de la classe parent. En fait, je pense que cette fonction n'a aucun effet. L'effet de la modification du prototype est équivalent, bien sûr, le but d'extjs est de protéger complètement la chose magique du prototype, afin que les programmeurs puissent traiter Javascript comme les autres langages. Bien sûr, même ainsi, son héritage est encore quelque peu différent de l'héritage ordinaire. Regardons d'abord un exemple et préparons une classe Person :

Person = function(name) { 
this.name = name; 
this.fn = function() { alert('I am a person') }; 
} 
Person.prototype.print=function(){ alert('I am a person');} 
Person.prototype.showAge = function() { alert('I am older than 0'); } 
Person.prototype.showName = function() { alert('Show Name:'+this.name) }; 
var per = new Person('Tom'); 
per.showName();子类:Student = function(id) { 
this.id = id; 
} 
Student.prototype.showID = function() { alert(this.id); } //子类的方法

Héritage :
Ext.extend(Student, Person ) ;
stu.showName(); Aucun résultat ! stu n'a pas de définition de nom stu.fn(); !!Aucun résultat stu.showID(); Toujours aucun résultat A ce stade, nous avons découvert quelques différences : le contenu du constructeur de la classe parent ne sera pas hérité . , le constructeur de la classe parent ne sera pas appelé, et les méthodes existantes de la sous-classe (en prototype) seront également perdues ! Continuez à lire et remplacez le code ci-dessous Ext.extend par :

var stu = new Student('01'); 
Student.override({ print: function() { alert('I am a student'); } }); 
stu.override({ print: function() { alert('I am a bad student,but I won\'t affect others'); } }); 
stu.print(); 
stu.showAge(); 
var stu2 = new Student(); 
stu2.print();

Les fonctions ici peuvent toutes être générées comme prévu. showAge est la méthode de la classe parent qui est exécutée, et stu.print est la méthode. de stu.override qui est exécuté. La méthode spécifiée dans , et stu2 exécute la méthode spécifiée dans Student.override. À ce stade, nous pouvons à peu près deviner comment extend est implémenté. Regardons son vrai code source. Cette méthode se trouve dans Ext.js. Le code et les commentaires sont les suivants : extend : function(){

// inline overrides 
var io = function(o){ //注意这个方法的this,仅看这里并不知道这个this是什么,下面这个io会被赋值给sbp.override,也就是子类的prototype 
for(var m in o){ //从而每个子类的对象的override都会指向这个方法,如果子类对象调用了override,那么这个this就是子类的对象了。也就是 
this[m] = o[m]; //上面的例子中stu.override表现出来的效果,仅对当前对象有效。从这里可以看出,override不仅仅是传统意义上的覆盖,完全也可以 
} //用来添加新方法。 
}; 
var oc = Object.prototype.constructor; 
return function(sb, sp, overrides){ 
if(Ext.isObject(sp)){ //是在检测当前使用的是哪个版本的重构函数。如果sp实际上是overrides,就做些替换工作,让变量的实际意义和名称相符合。 
overrides = sp; 
sp = sb; 
sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);}; //这个没看懂…… 
} 
var F = function(){}, 
sbp, 
spp = sp.prototype; 
F.prototype = spp; //F是父类的一个“干净”拷贝,所谓干净,是指它不会把父类中在构造函数内部定义的属性带过来。 //例如 Person=function() // {this.privateFn=new function{ some code goes here}} //那么这个privateFn对子类是不可见的,所以在构造函数中利用this定义的属性都相当于是类的私有变量。 
sbp = sb.prototype = new F(); //将子类的prototype设置为父类的prototype,继承的核心步骤。 sbp.constructor=sb; //设置正确的构造函数指向,见 JavaScript继承详解 
sb.superclass=spp; //设置父类 
if(spp.constructor == oc){ //没看懂……,这个是干嘛用的?望高人指点 
spp.constructor=sp; 
} 
sb.override = function(o){ //子类的重写方法,这个重写方法是函数的重写方法。它修改的是prototype。 
Ext.override(sb, o); //见最后。 
}; 
sbp.superclass = sbp.supr = (function(){ //设置原型的父类 
return spp; 
}); 
sbp.override = io; //给子类的prototype提供override方法,这样单个实体也可以覆盖,它修改的是实体对象。注意和上面的sb的override区分。 
Ext.override(sb, overrides); //重写 
sb.extend = function(o){return Ext.extend(sb, o);}; //给子类提供extend方法,以实现多重继承 
return sb; //返回子类。 
}; 
}();

Ce qui suit est le code de Ext.override, ce qui est relativement clair, et que Par rapport au remplacement en ligne, il s'agit d'un prototype modifié :override:

function(origclass, overrides){ 
if(overrides){ 
var p = origclass.prototype; 
Ext.apply(p, overrides); 
if(Ext.isIE && overrides.hasOwnProperty('toString')){ // 这个是什么?IE的特殊点? 
p.toString = overrides.toString; 
} 
} 
}

Vous pouvez maintenant commencer à introduire formellement le modèle d'événement d'Extjs. Semblable aux événements dans d'autres langages, vous devez d'abord définir un événement pour une classe. Les événements dans d'autres langages (tels que C#) ont généralement un type d'événement spécial. Le type d'événement peut en fait être considéré comme un tableau de délégués. , le délégué est en fait une fonction. Ajouter L'écouteur temporel (auditeur) veut juste ajouter un délégué (fonction) au tableau de délégués. Ce qu'on appelle l'événement déclencheur consiste à exécuter toutes les fonctions du tableau. Javascript est similaire, sauf que les fonctions de Javascript sont beaucoup plus puissantes et flexibles que ces langages, il n'est donc pas nécessaire d'avoir un type d'événement. Les événements Javascript ressemblent à une chaîne (ils doivent également conserver un tableau en interne). Vous pouvez ajouter des événements via la méthode Observale.addEvents, déclencher des événements via Observale.fireEvent et ajouter des écouteurs d'événements via Observale.addListner. Voici un exemple qui n’a pas beaucoup de sens mais illustre le problème.

Odder = function(min, max) { 
this.min = min; 
this.max = max; 
this.addEvents('onFindOdd'); 
} 
Ext.extend(Odder, Ext.util.Observable, { run: 
function() { 
for (var i = this.min; i < this.max; i++) { 
if (i % 2 != 0) { 
this.fireEvent(&#39;onFindOdd&#39;,i); 
} 
} 
} 
}); 
var p = new Odder(4, 8); 
p.addListener(&#39;onFindOdd&#39;,function(n){alert(n);}); 
p.run();

Odder est une classe qui passe une plage par un constructeur, puis recherche tous les nombres impairs de la plage et déclenche un événement à chaque fois qu'un nombre est trouvé. Ajoutez-y un gestionnaire d'événements et alertez les nombres impairs qu'il trouve. Il convient de noter que les paramètres du gestionnaire d'événements ici ne peuvent être maintenus cohérents que par le programmeur. Il n'est pas aussi fortement typé qu'un délégué.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn