【问题标题】:How to handle events in dynamically created elements in js如何在js中处理动态创建的元素中的事件
【发布时间】:2020-11-03 04:06:59
【问题描述】:

我想动态地将点击事件添加到创建的元素中,当用户点击按钮时创建一些元素(在下面的代码中显示的元素)和当用户点击名为remov的元素时必须运行名为deltion的函数但是不起作用。我该如何实现?

我使用 Vue js

methods: {
        showinfo: function() {
            db.collection("Studnets")
                .get()
                .then(function(querySnapshot) {
                    querySnapshot.forEach(function(doc) {
const student = document.createElement("tr");
const email = document.createElement("td");
email.innerText = doc.data().email;

const name = document.createElement("td");
name.innerText = doc.data().name;

const phone = document.createElement("td");
phone.innerText = doc.data().phone;

const stage = document.createElement("td");
stage.innerText = doc.data().stage;

const remov = document.createElement("button");
const pic = document.createElement("img");
pic.setAttribute("src","/dist/delete.svg?afdf9975229cdc15458e851b478bb6cb");
remov.classList.add("del");

//the problem
remov.addEventListener("click", this.deltion());

student.appendChild(email);
student.appendChild(name);
student.appendChild(phone);
student.appendChild(stage);
student.appendChild(remov);
remov.appendChild(pic);
document.getElementById("studentList").appendChild(student);
},

  deltion: function(e) {
         const rawStudent = e.target;
         const raw = rawStudent.parentElement;
         console.log(raw);
         raw.remove();
     }

【问题讨论】:

  • 如果使用Vue.js,应该不需要直接操作Dom。
  • 您使用的是 Vue,但您的整个方法是 vanilla JS 方式。使用 vue,您可以向应用程序状态添加一个新数据行,这会导致重新渲染,由于模板中的循环,它会显示一个带有额外行的表格。除非确实需要,否则您永远不会直接操作 DOM。 Vue list rendering
  • 对于初学者来说,remov.addEventListener("click", this.deltion()); 将是 remov.addEventListener("click", this.deltion);remov.addEventListener('click', e=>{ this.deltion(e); }); 或者你不会得到 EventObject... 但我真的不喜欢你的编码风格。提高你的技能。

标签: javascript vue.js dom vuejs2 createelement


【解决方案1】:

您的代码存在三个问题。

第一个问题:在事件监听器上调用函数

您在注册事件侦听器时正在调用 deltion(也许您的意思是删除 :P)函数。

remov.addEventListener("click", this.deltion());

正确的形式是

remov.addEventListener("click", this.deltion);

因为你想将函数体传递给事件监听器,而不是函数结果。 (如果你想调用它,你可以将函数包装在一个箭头函数中,但最后是一样的)。

第二期:这不是

如果你修复了第一个,你会找到另一个(程序员的生活)。 this是js中的一个特殊关键字,this的上下文会根据调用者的不同而变化。

  1. showinfo 被称为 this 关键字是指组件实例。
  2. db.collection("Studnets").get().then(function(querySnapshot) {}) promise 被调用,并且在解析时它将调用具有 querySnapshot 参数的函数。 **this** 关键字上下文更改。
  3. 您使用 foreach querySnapshot.forEach(function(doc) {}) **this** 关键字上下文再次更改了集合。

一个解决方案是使用箭头函数,这样它就不会绑定到父函数。

db.collection("Studnets").get().then(querySnapshot => {
    querySnapshot.data.forEach(doc => { 
        // code
    })
}) 

如果由于某种原因您不能使用箭头函数,您可以在 showinfo 函数上添加一个“隐藏”this 关键字上下文的变量。

showinfo() {
    const vm = this;
    api.getStudentsCollection().then(function(querySnapshot) {
      querySnapshot.data.forEach(function(doc) {
        // setup code
        remov.addEventListener("click", vm.deltion);
        // setup code
      });
    });
}

第三题:点击箭头图片会删除按钮,但不会删除tr 使用 currentTarget 代替 target,target 是用户点击的元素,可以是按钮内的任何元素,比如图片,currentTarget 是事件监听器附加的元素,也就是按钮。

{
    deltion: function(e) {
        const rawStudent = e.currentTarget;
        const raw = rawStudent.parentElement;
        console.log(raw);
        raw.remove();
    }
}

不请自来的建议

Vue 以其简单性和声明性代码而著称。您可以像原始代码一样解决问题,但有一种更简单的方法让组件管理其状态

我用固定的原始版本和最简单的 vue 方式(使用简单的空和加载状态切换)复制了您的代码。希望你觉得它有用并从中学习。 :) https://codesandbox.io/s/student-list-ammar-yasir-b5sxo?file=/src/App.vue

学习参考

【讨论】:

  • 非常感谢兄弟我编辑了我提到的 3 个问题的代码,现在可以正常工作了
猜你喜欢
  • 1970-01-01
  • 2012-09-23
  • 1970-01-01
  • 1970-01-01
  • 2018-05-29
  • 2013-04-21
  • 2019-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多