无法访问javascript中的元素(null)

时间:2015-12-15 18:05:53

标签: javascript html

我有一个构造函数,它为我的文档添加了一个计算器,每次都有不同的类/ 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;
&#13;
&#13;

我是JavaScript和HTML的新手,所以并非一切都是最佳的......

1 个答案:

答案 0 :(得分:3)

有几个问题。其中一些来自您问题的早期版本(当答案引用之前的代码时,更改问题中的代码并不理想。)

ID,类和集合

这一行:

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');

(另外,getElementsByClassNamequerySelector及其表兄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);