JavaScript动态按钮onClick事件(变量范围)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript动态按钮onClick事件(变量范围)相关的知识,希望对你有一定的参考价值。
背景
我根据查询数据库的AJAX请求返回的JSON对象动态创建了很多按钮。
然后每个按钮需要对同一个数据库进行后续的AJAX调用,具体取决于我在每个按钮的onClick函数中输入的信息。
基本上,网址是"api/{foo}/{bar}/{thing}/"
,如果我只打电话给"api/"
它给了我所有可能的选择foo
。如果我打电话给"api/book/"
它会给我所有可能的选择bar
foo = "book"
,等等....
我正在尝试的方法。
//getJSON is a promise function that returns a JSON object
getJSON("api")
// volumes is the JSON object that contains an array of objects
// each object is {book:"someTitle",url:"titleShorthand"}
.then((volumes) => {
for (var vol in volumes) {
//create Button returns a document.crateElement(input)
//with type=button and value = the passed in param.
var btn = createButton(volumes[vol].book)
btn.addEventListener('click', function(){
getJSON("api/" + volumes[vol].url)
.then((books) => {
console.log(books)
})
})
volumeDiv.appendChild(btn)
}
})
问题
所有的button.onClick事件都是一样的,因为console.log(books)
只给我最后一套书,无论我点击哪个按钮。对于每个按钮,volumes[vol].url
似乎都会被for循环的每次迭代重写,而不仅仅是新创建的按钮。
答案
那是因为你在for
循环中声明了一个函数。由于volume[vol]
的工作方式,closures的值始终是你在循环中声明的函数运行时的最后一个值。
要解决这个问题,你可以使用higher order function。
我不得不模拟一些函数来使这个片段工作,但是你必须在代码中编写像getEventListener
这样的函数才能使它工作。
var volumeDiv = document.getElementById('container')
function getJSON (url) {
return new Promise (resolve => {
var vol1 = {
book: "vol1",
url: "vol1"
}
var vol2 = {
book: "vol2",
url: "vol2"
}
var map = {
'api': { vol1, vol2 },
'api/vol1': vol1,
'api/vol2': vol2
}
resolve(map[url])
})
}
function createButton (name) {
console.log(`creating button ${name}`)
var btn = document.createElement('input')
btn.type = 'button'
btn.value = name
return btn
}
function getEventListener (url) {
return () => {
getJSON(url)
.then((books) => {
console.log(books)
})
}
}
getJSON("api")
.then(volumes => {
for (var vol in volumes) {
var volumeUrl = volumes[vol].url
var btn = createButton(volumes[vol].book)
btn.addEventListener('click', getEventListener("api/" + volumeUrl))
volumeDiv.appendChild(btn)
}
})
<div id="container" />
以上是关于JavaScript动态按钮onClick事件(变量范围)的主要内容,如果未能解决你的问题,请参考以下文章