我想要达到这样的目标:
querySelectorAll
)href
attr获取链接。但是,我无法从img.addEventListener("load", function(){})
获取值
如果我在该函数外检查console.log(this.naturalWidth)
但undefined
,那么值就在那里。
现在,我在StackOverflow上打开了近20个关于" JS Scope"但它对我的情况没有意义。
注意:我试图在没有jquery的情况下使 。
var pselemgroup = document.querySelectorAll(pselemgroupname);
for(var j = 0; j < pselemgroup.length; j++){
var obj = new Object();
var href = pselemgroup[j].href;
var img = new Image();
img.src = pselemgroup[j].href;
img.addEventListener("load", function(){
obj = {
src: href,
w: this.naturalWidth,
h: this.naturalHeight
};
console.log(obj);
});
//pselemgroup[j].dataset.index = j;
galleryElements.push(obj);
}
这也与实际问题无关,但是:
当我尝试获取href
值时,我收到有关href
的错误。
一小时后,我了解到querySelectorAll
返回NodeList,而不是Array。所以我也试过了:
[].slice.call(document.querySelectorAll(pselemgroupname));
并更改了一些代码:
pselemgroup[j]["href"]
但没有运气。
谢谢。
所以当我在加载函数中使用galleryElements.push(obj)时它会起作用,但是,我的最终目标是创建一个包含对象的数组。
像:
var items = [
{
src: "foo",
w: "bar",
h: "baz"
},
{
src: "foo",
w: "bar",
h: "baz"
},
]
我可以访问像items[0].src
这样的对象但是我。无法以相同的方式访问我的galleryElements[]
数组对象。我得到错误说:
undefined.src
答案 0 :(得分:0)
你问题的一部分原因是你不了解eventlistener的工作方式以及你的对象何时被填充。
Eventlisteners以异步方式运行,因此,您不能假设您在回调中填充的对象在该范围之外填充。
一种简单的方法是使用Promise
对象。
您可以轻松地将代码更改为以下
// loads the image and resolves when ready, containing the information you wanted to receive from the image
function loadImageFromUrlAsync( url, text ) {
return new Promise( (resolve, reject) => {
let image = new Image();
image.src = url;
image.addEventListener('load', () => resolve({
title: text,
width: image.naturalWidth,
height: image.naturalHeight
} ) );
});
}
function loadAllImagesBySelectorAsync( selector ) {
return new Promise( (resolve, reject) => {
let elements = document.querySelectorAll( selector ),
loaders = [], gallery = [];
for (let element of elements) {
// after the image is loaded the result gets pushed in your gallery
loaders.push(
loadImageFromUrlAsync( element.href, element.innerText )
.then( result => gallery.push(result) )
);
}
// this will only go into resolve after all images are loaded
Promise.all( loaders ).then( () => {
resolve( gallery );
});
});
}
loadAllImagesBySelectorAsync('.image-link').then( gallery => {
// writes the content of the gallery to the result div
document.querySelector('#result').innerHTML = gallery
.map( item => `${item.width}px + ${item.height}px for ${item.title}` )
.join('<br />');
});
<a class="image-link" href="https://tse4.mm.bing.net/th?id=OIP.x0SJKpQsIUBt0asGiBa-iwEsDh&pid=15.1&P=0&w=232&h=175">Image 1</a>
<a class="image-link" href="https://tse2.mm.bing.net/th?id=OIP.wFyOf5HQmlo2j9p39nTbogEsC7&pid=15.1&P=0&w=279&h=175">Image 2</a>
<a class="image-link" href="https://tse2.mm.bing.net/th?id=OIP.SV38MmYJt0TbuZpJMM1mtwEsDI&pid=15.1&P=0&w=255&h=171">Image 3</a>
<a class="image-link" href="https://tse1.mm.bing.net/th?id=OIP.s2uDayjT1fqnoT921zfsQwDhEs&pid=15.1&P=0&w=300&h=300">Image 4</a>
<a class="image-link" href="https://tse3.mm.bing.net/th?id=OIP.cZ12zxh0UKEsf3Y1_GaReQDHEs&pid=15.1&P=0&w=300&h=300">Image 5</a>
<div id="result"></div>
但是如果您不想对当前代码进行如此广泛的更改,我们也可以像这样更改它,在这种情况下,您将拥有一个带有回调函数,该函数将在加载所有图像后调用
我试着评论代码中的变化,希望这样就够了
function loadMyGallery(pselemgroupname, callback) {
// move all variable declaration per function
// to the top, as var is function scoped
var pselemgroup = document.querySelectorAll(pselemgroupname),
j, img, galleryElements = [];
for (j = 0; j < pselemgroup.length; j++) {
img = new Image();
img.src = pselemgroup[j].href;
img.addEventListener("load", function( href ) {
// push in the load method
galleryElements.push({
title: this.src,
width: this.naturalWidth,
height: this.naturalHeight
});
// call the callback when you loaded as many images as you found in the pselemgroup.length
if (galleryElements.length === pselemgroup.length) {
callback( galleryElements );
}
// bind img as the this context
}.bind(img));
}
if (pselemgroup.length === 0) {
// no elements
setTimeout( callback, 0 );
}
}
// load the gallery
loadMyGallery( '.image-link', ( gallery ) => {
// writes the content of the gallery to the result div
document.querySelector('#result').innerHTML = gallery
.map( item => `${item.width}px + ${item.height}px for ${item.title}` )
.join('<br />');
});
<a class="image-link" href="https://tse4.mm.bing.net/th?id=OIP.x0SJKpQsIUBt0asGiBa-iwEsDh&pid=15.1&P=0&w=232&h=175">Image 1</a>
<a class="image-link" href="https://tse2.mm.bing.net/th?id=OIP.wFyOf5HQmlo2j9p39nTbogEsC7&pid=15.1&P=0&w=279&h=175">Image 2</a>
<a class="image-link" href="https://tse2.mm.bing.net/th?id=OIP.SV38MmYJt0TbuZpJMM1mtwEsDI&pid=15.1&P=0&w=255&h=171">Image 3</a>
<a class="image-link" href="https://tse1.mm.bing.net/th?id=OIP.s2uDayjT1fqnoT921zfsQwDhEs&pid=15.1&P=0&w=300&h=300">Image 4</a>
<a class="image-link" href="https://tse3.mm.bing.net/th?id=OIP.cZ12zxh0UKEsf3Y1_GaReQDHEs&pid=15.1&P=0&w=300&h=300">Image 5</a>
<div id="result"></div>