我有这些javascript文件。了解MVC如何与javascript结合使用,这确实是一个很小的测试项目。当我尝试单击“删除Bloak”按钮时,除了ID为100的最后一个按钮外,什么都没有发生。其他按钮没有任何单击事件。为什么?
Controller.js
{
switch (GetChar ())
{
case Ping:
Serial.write ("Connection estabilished.\n");
continue;
case PANAngle:
{
int h=0;
h = GetChar ();
if(h >= '0' && h <= '9') // is h a number?
pos = pos * 10 + h - '0'; // yes, accumulate the value
else if(h == 'p') // pan
{
panServo.write(pos);
Serial.print("Pan Servo angle: ");
Serial.println(pos);
}
}
case TILTAngle:
{
int j=0;
j = GetChar ();
if(j >= '0' && j <= '9') // is j a number?
pos = pos * 10 + j - '0'; // yes, accumulate the value
else if(j == 't') // tilt
{
tiltServo.write(pos);
Serial.print("Tilt Servo angle: ");
Serial.println(pos);
}
}
Model.js
var BloakController = function BloakController(model, view) {
this.model = model;
this.view = view;
}
BloakController.prototype.init = function init() {
this.view.onAddBloak = this.addBloak.bind(this);
this.view.onDeleteBloak = this.deleteBloak.bind(this);
this.view.onGetAllBloaks = this.getAllBloaks.bind(this);
}
BloakController.prototype.addBloak = function addBloak() {
}
BloakController.prototype.getAllBloaks = function getAllBloaks() {
this.model.getAllBloaks(this.getAllBloaksList.bind(this));
}
BloakController.prototype.getAllBloaksList = function getAllBloaksList(allBloaksList) {
for (var i = 0; i < allBloaksList.length; i++) {
var bloak = allBloaksList[i];
var bloakDataObjectModel = {
title: bloak.title,
body: bloak.body,
userId: bloak.userId,
id: bloak.id
};
this.view.render(bloakDataObjectModel);
}
}
BloakController.prototype.deleteBloak = function deleteBloak(id) {
this.model.deleteBloak(id, this.getAllBloaksList.bind(this));
}
View.js
var BloakModel = function BloakModel(XMLHttpRequest) {
this.XMLHttpRequest = XMLHttpRequest;
}
BloakController.prototype.addBloak = function addBloak() {
}
BloakModel.prototype.getAllBloaks = function getAllBloaks(callback) {
var request = new this.XMLHttpRequest;
request.onload = function onLoad(e) {
var ajaxResponse = JSON.parse(e.currentTarget.responseText);
callback(ajaxResponse);
}
request.open('GET', 'https://jsonplaceholder.typicode.com/posts', true);
request.send();
}
BloakModel.prototype.deleteBloak = function deleteBloak(id, callback) {
console.log(id);
var request = new this.XMLHttpRequest;
request.onload = function onLoad(e) {
var ajaxResponse = JSON.parse(e.currentTarget.responseText);
callback(ajaxResponse);
}
request.open('DELETE', 'https://jsonplaceholder.typicode.com/posts/' + id, true);
request.send();
}
App.js
var BloakView = function BloakView(domElement) {
this.domElement = domElement;
this.onAddBloak = null;
this.onDeleteBloak = null;
this.onGetAllBloaks = null;
}
BloakView.prototype.render = function render(bloakDataObjectModel) {
this.domElement.innerHTML += '<div class="bloakContainer"><h3>' + bloakDataObjectModel.title + '</h3><p class="bloakContent">' + bloakDataObjectModel.body + '</p><label class="bloakAuthor">' + bloakDataObjectModel.userId + '</label><br /><label class="bloakDate">' + bloakDataObjectModel.id + '</label><br /><input id=' + bloakDataObjectModel.id + ' type="button" value="Delete Bloak" /></div>';
var addBloakButton = document.getElementById('addBloakButton');
var deleteBloakButton = document.getElementById(bloakDataObjectModel.id);
addBloakButton.addEventListener('click', this.onAddBloak);
deleteBloakButton.addEventListener('click', this.onDeleteBloak);
}
答案 0 :(得分:3)
事实证明,做完更多研究后,我完全错了,好像使用innerHTML
属性会导致所有子元素read more about it here遭到破坏。无论哪种方式,提供的解决方案仍然有效,事实证明我自己并不知道。
我本应该意识到我最初是错的,如果我是对的,那么您将出现一个错误,指出您无法将事件监听器附加到null
或undefined
上,这很糟糕,我这是愚蠢的错误!
非常简短查看了您的代码,我认为可以肯定地说您的渲染功能有些错误,由于使用了innerHTML
,它无法以足够快的速度解析更新的HTML事件监听器可以正常工作...
我自己进行了测试,并完成了以下操作:
setTimeout(() => {
var addBloakButton = document.getElementById('addBloakButton');
var deleteBloakButton = document.getElementById(bloakDataObjectModel.id);
addBloakButton.addEventListener('click', this.onAddBloak);
deleteBloakButton.addEventListener('click', this.onDeleteBloak);
}, 10);
有效。因此,如果您不想做太大的更改,则可以做我上面所做的事情,或者,可以按照以下方式做点事情:
var div = document.createElement("div");
div.innerHTML = '<div class="bloakContainer"><h3>' + bloakDataObjectModel.title + '</h3><p class="bloakContent">' + bloakDataObjectModel.body + '</p><label class="bloakAuthor">' + bloakDataObjectModel.userId + '</label><br /><label class="bloakDate">' + bloakDataObjectModel.id + '</label><br /><input id=' + bloakDataObjectModel.id + ' type="button" value="Delete Bloak" /></div>';
this.domElement.append(div);
var addBloakButton = document.getElementById('addBloakButton');
var deleteBloakButton = div.querySelector('input[id*="' + bloakDataObjectModel.id + '"]');
addBloakButton.addEventListener('click', this.onAddBloak);
deleteBloakButton.addEventListener('click', this.onDeleteBloak);
此外,作为一种更可靠,更可靠的方法,我将在视图中实现一个onRender
函数,基本上说一次 和一次 > 所有相关HTML已呈现,然后启动onRender
方法。 或者,也许像view.dispatchEvents
之类的东西,等等。特别是在此示例中,我将在控制器中运行这样的功能,因此一旦getAllBloaksList
呈现了所有相关的数据,您可以然后启动dispatchEvents
函数,如下所示:
// Within the controller part...
BloakController.prototype.getAllBloaksList = function getAllBloaksList(allBloaksList) {
for (var i = 0; i < allBloaksList.length; i++) {
var bloak = allBloaksList[i];
var bloakDataObjectModel = {
title: bloak.title,
body: bloak.body,
userId: bloak.userId,
id: bloak.id
};
this.view.render(bloakDataObjectModel);
}
this.view.dispatchEvents();
};
// .. Within the View part...
BloakView.prototype.dispatchEvents = function () {
var list = this.domElement.querySelectorAll(".bloakContainer");
var todo = this.onDeleteBloak;
list.forEach(function (div) {
var deleteButton = div.querySelector("input[type=button]");
deleteButton.onclick = function () {
todo(this.id);
};
});
};
// Controller.
var BloakController = function BloakController(model, view) {
this.model = model;
this.view = view;
};
BloakController.prototype.init = function init() {
this.view.onAddBloak = this.addBloak.bind(this);
this.view.onDeleteBloak = this.deleteBloak.bind(this);
this.view.onGetAllBloaks = this.getAllBloaks.bind(this);
};
BloakController.prototype.addBloak = function addBloak() {
// todo
};
BloakController.prototype.getAllBloaks = function getAllBloaks() {
this.model.getAllBloaks(this.getAllBloaksList.bind(this));
};
BloakController.prototype.getAllBloaksList = function getAllBloaksList(allBloaksList) {
for (var i = 0; i < allBloaksList.length; i++) {
var bloak = allBloaksList[i];
var bloakDataObjectModel = {
title: bloak.title,
body: bloak.body,
userId: bloak.userId,
id: bloak.id
};
this.view.render(bloakDataObjectModel);
}
this.view.dispatchEvents();
};
BloakController.prototype.deleteBloak = function deleteBloak(id) {
this.model.deleteBloak(id, this.getAllBloaksList.bind(this));
};
// Model.
var BloakModel = function BloakModel(XMLHttpRequest) {
this.XMLHttpRequest = XMLHttpRequest;
};
BloakController.prototype.addBloak = function addBloak() {
// todo
};
BloakModel.prototype.getAllBloaks = function getAllBloaks(callback) {
var request = new this.XMLHttpRequest;
request.onload = function onLoad(e) {
var ajaxResponse = JSON.parse(e.currentTarget.responseText);
callback(ajaxResponse);
}
request.open('GET', 'https://jsonplaceholder.typicode.com/posts', true);
request.send();
};
BloakModel.prototype.deleteBloak = function deleteBloak(id, callback) {
console.log(id);
var request = new this.XMLHttpRequest;
request.onload = function onLoad(e) {
var ajaxResponse = JSON.parse(e.currentTarget.responseText);
callback(ajaxResponse);
}
request.open('DELETE', 'https://jsonplaceholder.typicode.com/posts/' + id, true);
request.send();
};
// View.
var BloakView = function BloakView(domElement) {
this.domElement = domElement;
this.onAddBloak = null;
this.onDeleteBloak = null;
this.onGetAllBloaks = null;
};
BloakView.prototype.render = function render(bloakDataObjectModel) {
this.domElement.innerHTML += '<div class="bloakContainer"><h3>' + bloakDataObjectModel.title + '</h3><p class="bloakContent">' + bloakDataObjectModel.body + '</p><label class="bloakAuthor">' + bloakDataObjectModel.userId + '</label><br /><label class="bloakDate">' + bloakDataObjectModel.id + '</label><br /><input id=' + bloakDataObjectModel.id + ' type="button" value="Delete Bloak" /></div>';
}
BloakView.prototype.dispatchEvents = function() {
var list = this.domElement.querySelectorAll(".bloakContainer");
var todo = this.onDeleteBloak;
var addBloakButton = document.getElementById('addBloakButton');
addBloakButton.addEventListener('click', this.onAddBloak);
list.forEach(function(div) {
var deleteButton = div.querySelector("input[type=button]");
deleteButton.onclick = function() {
todo(this.id);
};
});
};
// App.
var bloakModel = new BloakModel(XMLHttpRequest);
var targetElement = document.getElementById('bloaksContainer');
var bloakView = new BloakView(targetElement);
var bloakController = new BloakController(bloakModel, bloakView);
bloakController.init();
bloakController.getAllBloaks();
<button id="addBloakButton">Add</button>
<div id="bloaksContainer">
<!-- DHTML -->
</div>
答案 1 :(得分:1)
代码this.domElement.innerHTML += ...;
不正确。您正在使用+ =运算符,该运算符会自身添加一些内容,然后分配新值。
新值是现有innerHTML和新HTML的结果。因此,新值[HTML]将没有以前添加的事件处理程序,它将仅复制HTML。
您可以使用appendChild方法来添加新元素。
此外,您应该避免将for-loop
与innerHTML一起使用,因为它将不断更新DOM,并且您可能会在屏幕上看到闪烁。如果必须使用innerHTML,则应该
事件委托是一种将事件绑定到顶级容器的技术,因此您不必担心将事件侦听器附加到每个项目。
您可以阅读有关DOM here的更多信息。