我有一个构造函数,它为我的文档添加了一个计算器,每次都有不同的类/ ID,但是当我尝试在构造函数中按类名访问这些元素时,在事件监听器中,我得到null
。有什么想法吗?
我尝试访问按钮3和"添加"
var calcDiv = document.createElement('div');
calcDiv.setAttribute('id', 'calcPage');
document.body.appendChild(calcDiv);
var calcList = [];
var calcID = 0;
document.getElementById("calcPage").innerHTML += '<table>' +
'<tr>' +
'<td><button type="button" class="addCalc" >Add Calculator</button></td>' +
'</tr>' +
'</table>';
//constructor for calculator
function calculator() {
var value = "";
this.id = calcID;
this.stringID = calcID.toString();
var calc = document.createElement('div');
calc.setAttribute('id', "calculator" + this.stringID);
calc.innerHTML =
'<table>' +
'<TR>' +
'<TD>' +
'<input class="buttonclr' + this.stringID + '" type="Button" value="clr">' +
'</TD>' +
'<TD colspan=3 align=middle>' +
'<input class="screen' + this.stringID + '" value="0" readonly>' +
'</TD>' +
'</TR>' +
'<TR>' +
'<TD>' +
'<input class="button-' + this.stringID + '" type="Button" value="-">' +
'</TD>' +
'<TD>' +
'<input class="button7' + this.stringID + '" type="Button" value="7">' +
'</TD>' +
'<TD>' +
'<input class="button8' + this.stringID + '" type="Button" value="8">' +
'</TD>' +
'<TD>' +
'<input class="button9' + this.stringID + '" type="Button" value="9">' +
'</TD>' +
'</TR>' +
'<TR>' +
'<TD>' +
'<input class="buttonadd' + this.stringID + '" type="Button" value="+">' +
'</TD>' +
'<TD>' +
'<input class="button4' + this.stringID + '" type="Button" value="4">' +
'</TD>' +
'<TD>' +
'<input class="button5' + this.stringID + '" type="Button" value="5">' +
'</TD>' +
'<TD>' +
'<input class="button6' + this.stringID + '" type="Button" value="6">' +
'</TD>' +
'</TR>' +
'<TR>' +
'<TD>' +
'<input class="button*' + this.stringID + '" type="Button" value="*">' +
'</TD>' +
'<TD>' +
'<input class="button1' + this.stringID + '" type="Button" value="1">' +
'</TD>' +
'<TD>' +
'<input class="button2' + this.stringID + '" type="Button" value="2">' +
'</TD>' +
'<TD>' +
'<input class="button3' + this.stringID + '" type="Button" value="3">' +
'</TD>' +
'</TR>' +
'<TR>' +
'<TD>' +
'<input class="button0' + this.stringID + '" type="Button" value="0">' +
'</TD>' +
'</TR>' +
'</table>';
calcDiv.appendChild(calc);
calcID++;
//press buttons event handling
var handle1 = function(event) {
value += '1';
//var screen =
alert(document.querySelector(".screen" + this.stringID).value);
//screen.value = eval(value+'0');
//screen.setAttribute("value",eval(value+'0').toString());
};
var button1 = document.querySelector(".button1" + this.stringID);
button1.addEventListener('click', handle1);
var handleAdd = function(event) {
value += '+';
var screen = document.querySelector("screen" + this.stringID);
screen.value = eval(value + '0')
//screen.ans.value = eval(value+'0');
//screen.setAttribute(value,eval(value+'0').toString());
};
var buttonAdd = document.querySelector(".buttonadd" + this.stringID);
buttonAdd.addEventListener('click', handleAdd);
}
//add event handling
var handleAddCalc = function(event) {
calcList.push(new calculator());
};
var addCalcu = document.querySelector(".addCalc");
addCalcu.addEventListener('click', handleAddCalc);
&#13;
我是JavaScript和HTML的新手,所以并非一切都是最佳的......
答案 0 :(得分:3)
有几个问题。其中一些来自您问题的早期版本(当答案引用之前的代码时,更改问题中的代码并不理想。)
这一行:
var screen = document.getElementById('screen' + this.stringID);
不起作用,因为你没有使用像id
这样的screen0
来创建元素,等等,您正在使用类创建元素,您可以选择如下:
var screen = document.querySelector('.screen' + this.stringID);
或者,使用id
创建元素,原始的getElementById
也可以。
这些行:
var screen = document.getElementsByClassName("screen" + this.stringID);
screen.value = eval(value+'0');
不起作用,因为getElementsByClassName
返回所有匹配元素的集合,而不是单个元素,并且集合没有value
属性。而是再次querySelector
,它仅返回第一个匹配元素:
var screen = document.querySelector('.screen' + this.stringID);
screen.value = eval(value+'0');
(另外,getElementsByClassName
与querySelector
及其表兄querySelectorAll
的支持不是很好,它会返回像getElementsByClassName
这样的集合.IE8没有{例如,{1}}但确实有QS / QSA。可悲的是,IE8仍然在全球市场占有率超过10%,但希望不会持续更长时间。)
您有时也错过了getElementsByClassName
,例如.
中的这一行:
handleAdd
var screen = document.querySelector("screen" + this.stringID);
// Missing . ------------------------^
第二个问题是你没有在你的回调中保留this
的值,所以这个:
this
...会在点击按钮时设置对button1.addEventListener('click', handle1);
的回调,但在回调中,handle1
将是对this
元素的引用,而不是对您的计算器的引用实例
您可以使用button1
创建一个新功能,在调用时,会使用正确的Function#bind
来调用handle1
:
this
或者,由于所有这些都在构造函数中,您可以在构造函数中使用局部变量,将其设置为button1.addEventListener('click', handle1.bind(this));
(一旦在顶部通常是最好的):
this
...然后使用匿名函数:
var thisCalc = this;
但button1.addEventListener('click', function() {
handle1.call(thisCalc);
});
选项简单易用。
以下是针对上述内容的修补程序片段:
Function#bind
附注:var calcDiv = document.createElement('div');
calcDiv.setAttribute('id', 'calcPage');
document.body.appendChild(calcDiv);
var calcList = [];
var calcID = 0;
document.getElementById("calcPage").innerHTML += '<table>' +
'<tr>' +
'<td><button type="button" class="addCalc" >Add Calculator</button></td>' +
'</tr>' +
'</table>';
//constructor for calculator
function calculator() {
var value = "";
this.id = calcID;
this.stringID = calcID.toString();
var calc = document.createElement('div');
calc.setAttribute('id', "calculator" + this.stringID);
calc.innerHTML =
'<table>' +
'<TR>' +
'<TD>' +
'<input class="buttonclr' + this.stringID + '" type="Button" value="clr">' +
'</TD>' +
'<TD colspan=3 align=middle>' +
'<input class="screen' + this.stringID + '" value="0" readonly>' +
'</TD>' +
'</TR>' +
'<TR>' +
'<TD>' +
'<input class="button-' + this.stringID + '" type="Button" value="-">' +
'</TD>' +
'<TD>' +
'<input class="button7' + this.stringID + '" type="Button" value="7">' +
'</TD>' +
'<TD>' +
'<input class="button8' + this.stringID + '" type="Button" value="8">' +
'</TD>' +
'<TD>' +
'<input class="button9' + this.stringID + '" type="Button" value="9">' +
'</TD>' +
'</TR>' +
'<TR>' +
'<TD>' +
'<input class="buttonadd' + this.stringID + '" type="Button" value="+">' +
'</TD>' +
'<TD>' +
'<input class="button4' + this.stringID + '" type="Button" value="4">' +
'</TD>' +
'<TD>' +
'<input class="button5' + this.stringID + '" type="Button" value="5">' +
'</TD>' +
'<TD>' +
'<input class="button6' + this.stringID + '" type="Button" value="6">' +
'</TD>' +
'</TR>' +
'<TR>' +
'<TD>' +
'<input class="button*' + this.stringID + '" type="Button" value="*">' +
'</TD>' +
'<TD>' +
'<input class="button1' + this.stringID + '" type="Button" value="1">' +
'</TD>' +
'<TD>' +
'<input class="button2' + this.stringID + '" type="Button" value="2">' +
'</TD>' +
'<TD>' +
'<input class="button3' + this.stringID + '" type="Button" value="3">' +
'</TD>' +
'</TR>' +
'<TR>' +
'<TD>' +
'<input class="button0' + this.stringID + '" type="Button" value="0">' +
'</TD>' +
'</TR>' +
'</table>';
calcDiv.appendChild(calc);
calcID++;
//press buttons event handling
var handle1 = function(event) {
value += '1';
//var screen =
alert(document.querySelector(".screen" + this.stringID).value);
//screen.value = eval(value+'0');
//screen.setAttribute("value",eval(value+'0').toString());
};
var button1 = document.querySelector(".button1" + this.stringID);
button1.addEventListener('click', handle1.bind(this));
var handleAdd = function(event) {
value += '+';
var screen = document.querySelector(".screen" + this.stringID);
screen.value = eval(value + '0')
//screen.ans.value = eval(value+'0');
//screen.setAttribute(value,eval(value+'0').toString());
};
var buttonAdd = document.querySelector(".buttonadd" + this.stringID);
buttonAdd.addEventListener('click', handleAdd.bind(this));
}
//add event handling
var handleAddCalc = function(event) {
calcList.push(new calculator());
};
var addCalcu = document.querySelector(".addCalc");
addCalcu.addEventListener('click', handleAddCalc.bind(this));
属性在元素实例上有一个反射属性,所以:
id
可以简单地
calc.setAttribute('id', "calculator" + this.stringID);