首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我不能使用这个JavaScript箭头函数获得单击元素的属性?

为什么我不能使用这个JavaScript箭头函数获得单击元素的属性?
EN

Stack Overflow用户
提问于 2020-10-17 09:41:14
回答 4查看 407关注 0票数 1

我正在使用从对象数组中“提取”的数据填充HTML表:

代码语言:javascript
运行
复制
let cars = [{
    licensee: '23456 NY',
    arrival: new Date(2020, 9, 16, 11, 34, 30),
    leave: new Date(),
    isParked: true
  },
  {
    licensee: '56456 NY',
    arrival: new Date(2020, 8, 24, 10, 33, 30),
    leave: new Date(2020, 8, 24, 13, 50, 35),
    isParked: false

  },
  {
    licensee: '56780 NY',
    arrival: new Date(2020, 5, 12, 20, 33, 30),
    leave: new Date(2020, 5, 12, 21, 33, 30),
    isParked: false
  }
];

const formatDate = (date) => {
  var hours = date.getHours();
  var minutes = date.getMinutes();
  var ampm = hours >= 12 ? 'PM' : 'AM';
  hours = hours % 12;
  hours = hours ? hours : 12;
  minutes = minutes < 10 ? '0' + minutes : minutes;
  var strTime = hours + ':' + minutes + ' ' + ampm;
  return date.getDate() + "/" + (date.getMonth() + 1) + "/" + date.getFullYear() + " " + strTime;
}

const secondsToHours = (d) => {
  d = Number(d);
  let h = Math.ceil(d / 3600);
  return h;
}

const makeBill = (car) => {
  let arrivedAt = new Date(car.arrival).getTime();
  let leftAt = new Date(car.leave).getTime();
  //duration in seconds
  let duration = (leftAt - arrivedAt) / 1000;
  let hoursBilled = secondsToHours(duration);
  let billValue = car.isParked ? "-" : 10 + (hoursBilled - 1) * 5 + " LEI";
  return billValue;
}

const renterTable = () => {
  // Show new on top
  cars.reverse();

  let results = '';
  for (var i = 0; i < cars.length; i++) {
    results += `<tr>
          <td>${cars[i].licensee}</td>
          <td>${formatDate(cars[i].arrival)}</td>
          <td>${formatDate(cars[i].leave)}</td>
          <td class="text-center">${showStatus(cars[i])}</td>
          <td class="text-right">${makeBill(cars[i])}</td>
          <td class="text-right">
            <button data-row="${i}" onclick="changeStatus(e)" class="btn btn-sm btn-success">Summary</button>
             </td>
      </tr>`;
  }
  document.querySelector("#parking tbody").innerHTML = results;
}

const showStatus = (car) => {
  return car.isParked ? "In" : "Out";
}

const changeStatus = (e) => {
  let car = cars[e.target.dataset.row];
  console.log(car);
}

renterTable();
代码语言:javascript
运行
复制
#parking th,
#parking td {
  white-space: nowrap;
  font-size: 14px;
}
代码语言:javascript
运行
复制
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" />

<div class="table-responsive">
  <table id="parking" class="table table-striped m-0">
    <thead>
      <tr>
        <th>Registration plate</th>
        <th>Arrived</th>
        <th>Deaparted</th>
        <th>Status</th>
        <th class="text-right">Pay</th>
        <th class="text-right">Actions</th>
      </tr>
    </thead>
    <tbody></tbody>
  </table>
</div>

这个小函数用于将与单击的“汇总”按钮对应的汽车记录到控制台:

代码语言:javascript
运行
复制
const changeStatus = (e) => {
  let car = cars[e.target.dataset.row];
  console.log(car);
}

然而,我得到的不是期望的结果,而是Cannot read property 'target' of undefined"

我的错误在哪里?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2020-10-17 09:46:48

因为没有传递事件对象,所以没有定义。改变:

代码语言:javascript
运行
复制
onclick="changeStatus()"

至:

代码语言:javascript
运行
复制
onclick="changeStatus(event)"

还请注意,使用内联处理程序是,不是一个好的实践。如果您关心良好的实践,不要使用内联事件处理程序。相反,选择javascript中的元素并将单击事件侦听器附加到其中。

代码语言:javascript
运行
复制
const btns = document.querySelectorAll('.btn')
btns.forEach(btn => btn.addEventListener("click", e => {
  let car = cars[btn.dataset.row];
  console.log(car);
}));
票数 1
EN

Stack Overflow用户

发布于 2020-10-17 09:48:05

const changeStatus = (e) => [让car = carse.target.dataset.row;

它说它不会读target of undefined

因此,eundefined

因此,请查看函数的调用位置:

onclick="changeStatus()“

您不会传递任何参数,因此e将获得undefined的默认值。

不要使用内在事件属性。他们有很多问题。

如果使用addEventListener添加事件处理程序,那么它将获得一个事件对象作为第一个参数。

代码语言:javascript
运行
复制
const buttons = document.querySelector(".btn-success");
for (let i = 0; i < buttons.length; i++) {
    buttons[i].addEventListener("click", changeStatus);
}

考虑使用事件委托而不是将事件处理程序单独绑定到每个按钮。

票数 4
EN

Stack Overflow用户

发布于 2020-10-17 10:08:16

首先,你必须传递一些东西才能发挥作用:

代码语言:javascript
运行
复制
onclick="changeStatus(this)"

在这个时候,你的这个意思是‘这个元素’(在这个答案中这就是‘这个’!)

这意味着您没有event.target,但是元素:

代码语言:javascript
运行
复制
const changeStatus = (element) => {
  let car = cars[element.dataset.row];
  console.log(car);
}

工作守则:

https://jsfiddle.net/jmz37261/

顺便说一下。更好的选择是addEventListener而不是onclick。

@编辑:

也许最好使用这个解决方案(在指定的情况下):

代码语言:javascript
运行
复制
<button data-row="${i}" onclick="changeStatus(${i})" class="btn btn-sm btn-success">Summary</button>

然后:

代码语言:javascript
运行
复制
const changeStatus = (row) => {
  let car = cars[row];
  console.log(car);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64401071

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档