js访问节点元素,然后进行事件监听的问题?

做简历过程中,需要用js控制进度条
1.首先我是用类名引入的是,Html代码和js代码:


然后去点击进度条是不会弹出prompt提示输入修改值的
2.然后我用id引入


然后在进度条框可以弹出输入修改的文本框

想知道怎么解决这个问题

阅读 1k
avatarAI BotBETA

从你的问题描述来看,你似乎遇到了在JavaScript中通过类名(ClassName)和ID来选择和操作HTML元素,以及添加事件监听器的问题。

首先,让我们来看看你的代码。

  1. 通过类名选择元素:
var progressBar = document.getElementsByClassName("progress");

通过类名选择元素时,getElementsByClassName方法返回的是一个HTMLCollection,也就是一个类数组的对象。即使页面上只有一个具有该类名的元素,这个方法也会返回一个包含这个元素的HTMLCollection。

如果你确定页面上只有一个具有该类名的元素,你可以通过索引来访问这个元素,例如:

var progressBar = document.getElementsByClassName("progress")[0];

然后你可以给这个元素添加一个事件监听器,例如:

progressBar.addEventListener("click", function() {
    prompt("请输入新的进度值:", "");
});
  1. 通过ID选择元素:
var progressBar = document.getElementById("progress");

通过ID选择元素时,getElementById方法返回的是一个单一的元素。这样你就可以直接给这个元素添加事件监听器了。例如:

progressBar.addEventListener("click", function() {
    prompt("请输入新的进度值:", "");
});

另外,你需要注意的一点是,在JavaScript中给元素添加事件监听器时,事件监听器的处理函数中可以访问到触发事件的元素。例如在你的代码中,你可以在事件处理函数中使用this关键字来访问触发事件的元素:

progressBar.addEventListener("click", function() {
    prompt("请输入新的进度值:", this.value);
});

在这个例子中,this关键字就代表了触发事件的元素(也就是进度条本身)。这样你就可以在事件处理函数中访问到进度条的值了。

3 个回答
✓ 已被采纳

方案一:

最直观的写法是:

<ul>
  <li>
    <span>Java</span>
    <progress
      max="100"
      value="40"
      onclick="updateProgress(this)"
    ></progress>
  </li>
  <li>
    <span>C++</span>
    <progress
      max="100"
      value="40"
      onclick="updateProgress(this)"
    ></progress>
  </li>
  <li>
    <span>C#</span>
    <progress
      max="100"
      value="40"
      onclick="updateProgress(this)"
    ></progress>
  </li>
</ul>

<script>
  function updateProgress(progressElement) {
    // 弹出输入框,让用户输入新的进度值
    var newValue = prompt(
      "Enter new progress value (0-100):",
      progressElement.value
    );

    // 确保输入值在合法范围内(0-100)
    newValue = parseInt(newValue, 10);
    if (!isNaN(newValue) && newValue >= 0 && newValue <= 100) {
      progressElement.value = newValue;
    } else {
      alert("Invalid input. Please enter a number between 0 and 100.");
    }
  }
</script>

改变progress.gif

方案二:

可以将点击事件委托到ul标签同一处理

<ul id="progressList">
  <li>
    <span>Java</span>
    <progress max="100" value="40"></progress>
  </li>
  <li>
    <span>C++</span>
    <progress max="100" value="40"></progress>
  </li>
  <li>
    <span>C#</span>
    <progress max="100" value="40"></progress>
  </li>
</ul>

<script>
  // 添加事件委托
  document
    .getElementById("progressList")
    .addEventListener("click", function (event) {
      // 判断点击的元素是否是 progress 元素
      if (event.target.tagName === "PROGRESS") {
        // 弹出输入框,让用户输入新的进度值
        var newValue = prompt(
          "Enter new progress value (0-100):",
          event.target.value
        );

        // 确保输入值在合法范围内(0-100)
        newValue = parseInt(newValue, 10);
        if (!isNaN(newValue) && newValue >= 0 && newValue <= 100) {
          event.target.value = newValue;
        } else {
          alert("Invalid input. Please enter a number between 0 and 100.");
        }
      }
    });
</script>

实现效果不变

方案三:

可以通过数据驱动的方式,渲染列表,避免增加一项就要写一堆html

<ul id="progressList"></ul>

<script>
  // 数据数组
  var data = [
    { language: "Java", progress: 40 },
    { language: "C++", progress: 40 },
    { language: "C#", progress: 40 }
  ];

  // 获取 ul 元素
  var ulElement = document.getElementById("progressList");

  // 遍历数据数组,创建并添加列表项和进度条
  data.forEach(function (item) {
    var liElement = document.createElement("li");
    var spanElement = document.createElement("span");
    spanElement.textContent = item.language;

    var progressElement = document.createElement("progress");
    progressElement.max = 100;
    progressElement.value = item.progress;

    // 添加点击事件监听器
    progressElement.addEventListener("click", function (event) {
      var newValue = prompt(
        "Enter new progress value (0-100):",
        event.target.value
      );
      newValue = parseInt(newValue, 10);
      if (!isNaN(newValue) && newValue >= 0 && newValue <= 100) {
        event.target.value = newValue;
      } else {
        alert("Invalid input. Please enter a number between 0 and 100.");
      }
    });

    // 将创建的元素添加到 DOM 中
    liElement.appendChild(spanElement);
    liElement.appendChild(progressElement);
    ulElement.appendChild(liElement);
  });
</script>

.getElementsByClassName 取到的是 NodeList,不是具体的节点,不能直接用 .onclick = function () {} 绑定事件。.getElementById 取到的是节点,所以可以 .onclick=function() {} 绑定。

有几个方案:

  1. 遍历 NodeList 绑定事件
  2. 将事件绑定在父节点,利用事件冒泡机制绑定处理函数
  3. 使用第三方类库改进绑定过程

建议用document.querySelector这个api, getElementByXXX除了id其他的(className,tagName,等等)返回的都是数组,无法绑定。
另外你第二段代码有点问题,我点击span标签,ul标签里的空白处也要我填入progress的value, 建议加判断

    let list = document.getElementById("list")
    list.onclick = function (e) {
        if (e.target.tagName != 'PROGRESS') {
            return
        }
        var num = prompt("请输入:")
        e.target.value = num
    }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题