Javascript 事件侦听器未返回所有事件类型的对象属性

Javascript 事件侦听器未返回所有事件类型的对象属性,javascript,events,foreach,Javascript,Events,Foreach,const stars=document.queryselectoral(“.star”) const message=document.querySelector(“.message”) 常数mouseEvents=[“mouseover”、“mouseout”、“click”] //创建星体对象 //将事件侦听器添加为数组 stars.forEach((star,i)=>{ star.starNum=(i+1) console.log(star.starNum) mouseEvents.fo

const stars=document.queryselectoral(“.star”)
const message=document.querySelector(“.message”)
常数mouseEvents=[“mouseover”、“mouseout”、“click”]
//创建星体对象
//将事件侦听器添加为数组
stars.forEach((star,i)=>{
star.starNum=(i+1)
console.log(star.starNum)
mouseEvents.forEach((事件)=>{
star.addEventListener(事件,Starate)
})
})
函数星号(e){
设num=e.target.starNum
console.log(num)
}
ul{
列表样式类型:无;
填充:0;
}
.明星{
显示:内联块;
颜色:#ddd;
字号:2.5em;
}

消息
事件接口的target属性是对 分派事件的对象

这意味着您可以访问dom元素,但无法访问所需的属性。您可以通过以下两种方式之一传递此属性

第一种方式:使用
数据-*
属性

修改html以包含所需的数据

 <li class="star" data-starnumber="1"><i class="fa fa-star" aria-hidden="true"></i></li>


第二种方式:将所需数据绑定到回调

您可以绑定希望出现在函数调用中的数据

stars.forEach((star, i) => {
  star.starNum = i+1;
  console.log(star.starNum);
  mouseEvents.forEach((event) => {
    star.addEventListener(event, starRate.bind(null, star);
  });
});

function starRate(star, e) {
  const num = star.starNum;
  console.log(num);
}
涉及
数据-*
属性是最佳解决方案。这个答案是在解决方案的事件方面展开的

当存在多个事件目标(即item--aka
li.star
)时,应该使用一种称为事件委派的重要编程模式。与其让每个元素侦听事件,不如指定它们的“父”元素(即list--aka
ul.stars
)侦听所有元素的事件。通过执行以下操作,您可以使用一个元素侦听在其任何子元素上触发的事件(数量不限)

  • 将事件注册到所有相关元素(即所有
    li.star
    ——目前每个元素将被称为项)作为共同祖先共享的元素(
    ul.stars
    ——目前被称为列表)

  • 回调函数必须传递事件对象

    示例:

    function starRate(event) {...
    

  • 使用带有事件对象属性的
    if/else if
    控制语句来隔离项目。最重要的事件属性包括:

    .target
    :始终引用单击、悬停等的实际元素(即项目)

    .currentTarget
    :始终引用侦听事件的元素(即列表)

    示例:

    if (e.target !== e.currentTarget) {...
    
    解释为:“如果触发事件的元素不是侦听事件的元素…”

请参阅有关的这篇文章

更多细节将在下面的演示中进行评论 注意:演示中的事件是
mouseover
,因为所有其他指针事件都调用相同的回调函数(即
starate()

/[列表]
//引用所有星号(ul.stars)的父元素
const list=document.querySelector('.stars');
//[项目]
//将所有星星收集成一个节点列表(li.star)
const items=document.queryselectoral('.star');
//[留言]
//引用消息显示元素(output.message)
const message=document.querySelector(“.message”)
//将鼠标悬停事件注册到父元素
//事件对象将引用[list]作为e.currentTarget
列表。添加的列表器(“鼠标悬停”,星号);
//为每个[项目]分配属性“data star num”
//设置与其索引+1对应的每个“数据星数”值
items.forEach((星号,索引)=>{
star.dataset.starNum=index+1;
});
//传递事件对象(e)
函数星号(e){
//e.target是悬停在[项目]上的实际元素
//e.currentTarget是事件注册到[列表]的元素
//如果悬停在元素[item]上的不是[list]。。。
如果(e.target!==e.currentTarget){
//如果[item]具有属性“data star num”。。。
if(e.target.hasAttribute('data-star-num')){
//获取该[item]的“data star num”值
//将其转换为实数是可选的
让num=parseInt(e.target.dataset.starNum);
//将值记录到控制台
console.log(num);
//在[消息]上显示值
message.textContent=num;
}
}
//否则终止函数
//此语句还防止事件进一步冒泡
返回false;
}
ul{
列表样式类型:无;
填充:0;
}
.明星{
显示:内联块;
颜色:#ddd;
字号:2.5em;
填充:8px;
保证金:5px;
光标:指针
}

消息
但为什么我可以在mouseout上访问该属性,而不能在其他事件上访问?我给这个对象一个starNum属性。target不是引用了那个对象吗?@Bob调用事件时,提供的参数是一个
事件
。此事件由浏览器生成,不知道您对
star
所做的修改。您正在向dom元素添加属性。触发事件时,
目标
由dom提供,不包含您设置的属性。好的,谢谢。为什么我保持一切不变,在CSS中
function starRate(e) {...
if (e.target !== e.currentTarget) {...