我编写了一个自定义组件来创建一个html按钮。 自定义组件定义如下
dojo.provide("ovn.form.OvnButton") ;
require([ "dojo/_base/declare",
"dojo/dom-construct",
"dojo/parser",
"dojo/ready",
"dijit/_WidgetBase"],
function (declare, domConstruct, parser, ready, _WidgetBase){
return declare ("ovn.form.OvnButton",[_WidgetBase],{
label: "unknown",
constructor : function(args){
this.id = args.id;
args.props.forEach(function(prop) {
if(prop.name == 'label'){
this.label = prop.value;
alert("found label " + this.label);
}
});
alert("from constructor " + this.label);
},
postMixInProperties : function(){
},
buildRendering : function(){
alert("from renderer label is " + this.label);
this.domNode = domConstruct.create("button", { innerHTML: this.label }); //domConstruct.toDom('<button>' + this.label + '</button>');
},
_getLabelAttr: function(){
return this.label;
},
_setLabelAttr : function(label){
alert("from set input is " + label)
this.label = label;
},
postCreate : function(){
alert("Post create label is " + this.label);
},
startUP : function(){
}
});
});
这就是我实例化组件的方式
var button = new ovn.form.OvnButton({
id:'run',
props:[{"name":"label","value":"Run"},{"name":"class","value":"btn"}]
});
在自定义组件的构造函数中,我遍历传递的数组并分配给名为&#39; label&#39;的实例变量。令我惊讶的是,当我们在buildRendering函数中打印实例变量时,它仍然打印默认值而不是指定的值。
有人可以解释为什么会这样。
供参考: 我在控制台上收到以下消息序列 1.found标签运行 2.来自构造函数未知 3.来自渲染器标签未知 4.来自设置输入未知 5.帖子创建标签未知
答案 0 :(得分:0)
这是因为在小forEach
函数中,this
实际指向与OvnButton对象完全不同的东西。
Javascript&#39; this
关键字在这方面很奇怪(实际上它与Dojo没有任何关系)。您可以在此处详细了解其工作原理:http://howtonode.org/what-is-this。这是一个非常基本的Javascript概念,与其他语言不同,因此值得您花些时间熟悉它。
但是有很多不同的方法可以快速解决它,所以这里有几个!
最简单的可能是使用常规for循环而不是forEach进行回调。
....
// args.props.forEach(function(prop) {
for(var i = 0, l = args.props.length; i < l; i++) {
var prop = args.props[i];
if(prop.name == 'label'){
this.label = prop.value;
alert("found label " + this.label);
}
}//); <-- no longer need the closing parenthesis
这里要说的是Javascript的this
魔法只发生在函数调用中,所以在这种情况下,当我们只使用for循环时,this
继续指向正确的东西
但也许你真的想用forEach
。它实际上有第二个参数,通常称为thisArg
。它告诉forEach
确保this
指向您在回调函数中选择的内容。所以你会做这样的事情:
....
args.props.forEach(function(prop) {
if(prop.name == 'label'){
this.label = prop.value;
alert("found label " + this.label);
}
}, this); // <--- notice we give forEach two arguments now,
// the callback function _and_ a "thisArg" value
我并不完全确定上述内容适用于所有浏览器,所以这是解决问题的另一种方法:
我们将临时变量设为this
。人们经常称这样的变量self
,但你可以任意命名。这很重要:它只是Javascript在回调函数中处理不同的this
关键字:
....
var self = this; //<--- we basically give `this` an alternative
// name to use inside the callback.
args.props.forEach(function(prop) {
if(prop.name == 'label'){
self.label = prop.value; //<--- replaced `this` with `self`
alert("found label " + self.label); //<--- here as well
}
});
有些人不喜欢self
解决方案,可能是因为他们喜欢始终使用this
来引用拥有的对象。因此,许多框架都有一个&#34; bind&#34;函数,确保在特定范围内始终调用函数。在dojo的情况下,该函数被称为hitch
。以下是如何使用它:
require([....., "dojo/_base/lang"], function(....., DojoLang) {
....
args.props.forEach(DojoLang.hitch(this, function(prop) {
if(prop.name == 'label'){
this.label = prop.value;
alert("found label " + this.label);
}
}));
Dojo和几乎所有其他框架都有一个hitch()函数。因为它是Javascript中常用的概念,新的Javascript标准实际上引入了它自己的变体Function.prototype.bind()。您可以像这样使用它:
....
args.props.forEach(function(prop) {
if(prop.name == 'label'){
this.label = prop.value;
alert("found label " + this.label);
}
}.bind(this));
对于一个非常小的事情,这是一个非常长的答案,我希望它有一定意义!