【发布时间】:2021-04-22 10:05:30
【问题描述】:
我正在尝试生成一个响应点击和鼠标悬停事件的网格。我有一个包含 tile 对象的 tile 管理器对象,每个对象都有自己的事件侦听器。目前,实际调用的方法是在管理器对象中,尽管我更希望它们存在于 tile 对象中。
我想找到一个比我目前知道的更优雅的解决方案,或者至少了解为什么这个解决方案甚至在其他解决方案不可行时仍然有效:
为了参考和清楚,cell 指的是 javacript 对象,cell_node 指的是单元格中的一个 DOM 对象,另外_handleClick 和 click_callback 是同一个函数 p>
目前,要查看是否发生回调,我将回调定义为:
_handleClick(el,r,c,i){
console.log("element:" + el)
console.log("row:" + r)
console.log("col:" + c)
console.log("index:" + i)
}
_handleClick(el,r,c,i) 位于管理器对象中,而不是图块中。
addEventListener 方法如下所示:
cell_node.addEventListener('click',
(function(el,r,c,i){
return function(){
click_callback(el,r,c,i);
}
})(cell,r,c,i),false);
我什至无法理解为什么这是必要的,或者为什么在以下尝试时它会起作用:
cell_node.addEventListener('click', cell.some_clicked_function_with_no_arguments)
不工作。如果我用this 关键字定义cell.some_clicked_function_with_no_arguments,所有内容都会打印为未定义,让我更加困惑。
下面将两种方法全文贴出来
class gridTile{
constructor(row, col, tile_id){
this.text= row + ", " + col;
this.child_text_div = this._make_child_text_div(this.text);
this.element = this._make_root_element()
this.row = row;
this.col = col;
this.id = tile_id;
}
_get_root_style(){
var randomColor = '#'+(Math.random() * 0xFFFFFF << 0).toString(16).padStart(6, '0');
return `
width: 100%;
padding-top: 100%;
//height: ${this.height}%;
background-color: ${randomColor};
position: relative;
`;
}
_make_child_text_div(text){
var cssobject =`
width: 100%;
height: 100%;
top: 0;
left: 0;
position: absolute;
`;
var obj = document.createElement("div");
obj.setAttribute("style", cssobject);
obj.innerHTML = text;
return obj;
}
_make_root_element(){
var root_grid_div = document.createElement("div");
root_grid_div.setAttribute("style", this._get_root_style());
root_grid_div.appendChild(this.child_text_div);
return root_grid_div;
}
get_element(){return this.element;}
clicked_callback(cell){
return function(cell){
console.log("element:" + cell.element);
console.log("row:" + cell.row);
console.log("col:" + cell.col);
console.log("index:" + cell.tile_id);
}
};
}
class Grid{
constructor(rows, columns){
this.grid_div = this._generate_grid_div(rows, columns, this._handleClick);
}
_generate_grid_div(rows, cols, click_callback){
// generate styling row and columns
var row_percent = String(1/rows * 100) + "% ";
var col_percent = String(1/cols * 100) + "% ";
console.log(row_percent + ", " + col_percent);
var rowstyle = "grid-template-rows: ";
for (var i=0; i<rows; i++){
rowstyle += row_percent
}
var colstyle = "grid-template-columns: ";
for (var i=0; i<cols; i++){
colstyle += col_percent
}
var style = `
display: grid;
${rowstyle};
${colstyle};
`
var grid = document.createElement('div');
grid.className = 'grid';
grid.setAttribute("style", style)
var i=0;
for (var r=0;r<rows;++r){
for (var c=0;c<cols;++c){
var cell = new gridTile(r, c, i);
var cell_node = grid.appendChild(cell.get_element())
cell_node.addEventListener('click',
(function(el,r,c,i){
return function(){
click_callback(el,r,c,i);
}
})(cell,r,c,i),false);
cell_node.addEventListener('mouseenter', click_callback(cell,r,c,i));
++i;
}
}
return grid;
}
_handleClick(el,r,c,i){
console.log("element:" + el)
console.log("row:" + r)
console.log("col:" + c)
console.log("index:" + i)
}
get_grid_element(){
return this.grid_div;
}
}
【问题讨论】:
-
可能与stackoverflow.com/questions/750486/…有关,但需要多贴代码。还要确保了解 IIFE 的工作原理(并且您不一定必须将其放在
addEventListener参数列表中)。 -
确实是^的骗子。最好的解决方案是使用
const和let而不是var,然后你只需要做.addEventListener('mouseenter', () => click_callback(cell,r,c,i)) -
我已经添加了完整的代码,很抱歉!此外,在@Bergi 评论中的链接中,我注意到下面的示例使用了一个我认为有效的匿名函数。为什么匿名函数或箭头函数在指向另一个对象时不起作用?这真的是范围问题吗?
标签: javascript callback scope