从模板插入元素后如何获取元素

问题描述 投票:0回答:1

我最近遇到了一个问题,即我的脚本无法访问通过编辑同一脚本中的innerHTML 插入的元素。

所以,我的 HTML 有这个占位符代码:

<div class="stage_preset_selection_column">
    <div class="stage_preset" id="stage_preset_1">
        <!-- <div class="preset_number">Preset 1</div>
            <div class="preset_title">title of the preset</div>
            <div class="questions_stage stage_preset_information">
                <div class="preset_text">questions per stage:</div>
                <div class="preset_text_number">5</div>
            </div>
            <div class="number_stages stage_preset_information">
                <div class="preset_text">number of stages:</div>
                <div class="preset_text_number">13</div>
            </div>
            <div class="number_failure stage_preset_information">
                <div class="preset_text">number of f for failure:</div>
                <div class="preset_text_number">3</div>
            </div>
            <div class="last_edited">last edited: 30-06-2021 14:51</div>
            <img src="../../assets/elements/cross.png" alt="remove preset" class="remove_preset">
            <img src="../../assets/elements/cross_inverted.png" alt="remove preset" class="remove_preset_inverted"> -->

        <!-- <div class="preset_number toggle_empty_preset">Preset 2</div>
            <div class="empty_preset_title">Empty preset</div> -->
    </div>
    <div class="stage_preset" id="stage_preset_2"></div>
</div>

<div class="stage_preset_selection_column">
    <div class="stage_preset" id="stage_preset_3"></div>
    <div class="stage_preset" id="stage_preset_4"></div>
</div>

然后在启动时使用以下 JavaScript 代码进行编辑:

function updatePreset() {
    fs.readFile(path.join(__dirname, '/stage_presets.json'), 'utf8', (err, data) => {
        if(err) {
            console.log(`Error reading file from disk: ${err}`);
        } else {
            const stage_presets = JSON.parse(data);
    
            Object.values(stage_presets).forEach(preset => {
                let htmlPresetElement = document.getElementById(`stage_preset_${preset.stage_preset_number}`)
                
                if(preset.is_empty) {
                    htmlPresetElement.innerHTML = `<div class="preset_number toggle_empty_preset">Preset ${preset.stage_preset_number}</div>
                    <div class="empty_preset_title">Empty preset</div>`
    
                } else {
                    htmlPresetElement.innerHTML = `<div class="preset_number">Preset ${preset.stage_preset_number}</div>
                    <div class="preset_title">${preset.preset_title}</div>
                    <div class="questions_stage stage_preset_information">
                        <div class="preset_text">questions per stage:</div>
                        <div class="preset_text_number">${preset.questions_per_stage}</div>
                    </div>
                    <div class="number_stages stage_preset_information">
                        <div class="preset_text">number of stages:</div>
                        <div class="preset_text_number">${Object.keys(preset.stages).length}</div>
                    </div>
                    <div class="number_failure stage_preset_information">
                        <div class="preset_text">number of f for failure:</div>
                        <div class="preset_text_number">${preset.f_for_failure}</div>
                    </div>
                    <div class="last_edited">last edited: ${preset.last_edited}</div>
                    <img src="../../assets/elements/cross.png" alt="remove preset" class="remove_preset">
                    <img src="../../assets/elements/cross_inverted.png" alt="remove preset" class="remove_preset_inverted" id="remove_preset_inverted_${preset.stage_preset_number}">`
                }
            });
        }
    });
}

所以现在我的问题是,由于某种原因,当我尝试为 id“remove_preset_inverted_[num]”的元素创建 EventListener 时,我收到此错误:

Uncaught TypeError: Cannot read property 'addEventListener' of null 

所以我的问题是,为什么会发生这种情况以及如何解决它?到目前为止,我尝试过的每个解决方案都失败了。

谢谢

编辑:添加了可运行的代码片段 由于某种未知的原因,它在代码片段中起作用,但在我的代码中不起作用。这和我在插入元素的函数中使用 fs.readFile 有关系吗?

stage_presets = {
  "stage_preset_1": {
    "stage_preset_number": 1,
    "preset_title": "Test Preset!",
    "is_empty": false,
    "questions_per_stage": 5,
    "last_edited": "Sun, 04 Jul 2021 20:13:19 GMT",
    "f_for_failure": 3,
    "probability_easy": 60,
    "probability_medium": 25,
    "probability_hard": 15,
    "stages": {
      "grade_1": {
        "title": "Grade 1",
        "questions": {
          "question_1": {
            "question": "When mokey do funny, what happen?",
            "answer": "everyone laughs :)",
            "difficulty": "easy",
            "subject": "science"
          },
          "question_2": {
            "question": "What's 1+1?",
            "answer": "idk",
            "difficulty": "hard",
            "subject": "maths"
          }
        }
      },
      "grade_2": {
        "title": "Grade 2",
        "questions": {
          "question_1": {
            "question": "What was the word 'crap' named after?",
            "answer": "Thomas Crapper",
            "difficulty": "easy",
            "subject": "history"
          },
          "question_2": {
            "question": "",
            "answer": "",
            "difficulty": "medium",
            "subject": "chaos"
          }
        }
      },
      "grade_3": {
        "title": "Grade 3",
        "questions": {
          "question_1": {
            "question": "How does banana market fluctuation influence prices?",
            "answer": "monkey regulation",
            "difficulty": "easy",
            "subject": "political_science"
          },
          "question_2": {
            "question": "",
            "answer": "",
            "difficulty": "hard",
            "subject": "litterature"
          },
          "question_3": {
            "question": "rohulk?",
            "answer": "this is gonna be messy",
            "difficulty": "medium",
            "subject": "osu"
          }
        }
      },
      "grade_4": {
        "title": "Grade 4",
        "questions": {
          "question_1": {
            "question": "",
            "answer": "",
            "difficulty": "hard",
            "subject": "pe"
          }
        }
      }
    }
  },
  "stage_preset_2": {
    "stage_preset_number": 2,
    "preset_title": "New preset",
    "is_empty": false,
    "questions_per_stage": 5,
    "last_edited": "Sun, 04 Jul 2021 18:49:54 GMT",
    "f_for_failure": 3,
    "probability_easy": 60,
    "probability_medium": 25,
    "probability_hard": 15,
    "stages": {}
  },
  "stage_preset_3": {
    "stage_preset_number": 3,
    "preset_title": "New preset",
    "is_empty": false,
    "questions_per_stage": 5,
    "last_edited": "Sun, 04 Jul 2021 18:49:52 GMT",
    "f_for_failure": 3,
    "probability_easy": 60,
    "probability_medium": 25,
    "probability_hard": 15,
    "stages": {}
  },
  "stage_preset_4": {
    "stage_preset_number": 4,
    "preset_title": "New preset",
    "is_empty": false,
    "questions_per_stage": 5,
    "last_edited": "Sun, 04 Jul 2021 19:02:58 GMT",
    "f_for_failure": 3,
    "probability_easy": 60,
    "probability_medium": 25,
    "probability_hard": 15,
    "stages": {}
  }
}


function updatePreset(stage_presets) {
  Object.values(stage_presets).forEach(preset => {
      let htmlPresetElement = document.getElementById(`stage_preset_${preset.stage_preset_number}`)

      if(preset.is_empty) {
          htmlPresetElement.innerHTML = `<div class="preset_number toggle_empty_preset">Preset ${preset.stage_preset_number}</div>
          <div class="empty_preset_title">Empty preset</div>`

      } else {
          htmlPresetElement.innerHTML = `<div class="preset_number">Preset ${preset.stage_preset_number}</div>
          <div class="preset_title">${preset.preset_title}</div>
          <div class="questions_stage stage_preset_information">
              <div class="preset_text">questions per stage:</div>
              <div class="preset_text_number">${preset.questions_per_stage}</div>
          </div>
          <div class="number_stages stage_preset_information">
              <div class="preset_text">number of stages:</div>
              <div class="preset_text_number">${Object.keys(preset.stages).length}</div>
          </div>
          <div class="number_failure stage_preset_information">
              <div class="preset_text">number of f for failure:</div>
              <div class="preset_text_number">${preset.f_for_failure}</div>
          </div>
          <div class="last_edited">last edited: ${preset.last_edited}</div>
          <img src="../../assets/elements/cross.png" alt="remove preset" class="remove_preset">
          <img src="../../assets/elements/cross_inverted.png" alt="remove preset" class="remove_preset_inverted" id="remove_preset_inverted_${preset.stage_preset_number}">`
      }
  });

}

updatePreset(stage_presets)

function presetRemove(e) {
  console.log("successfully ran the function!")
}

document.querySelector('#remove_preset_inverted_1').addEventListener('click', presetRemove)
* {
    margin: 0;
    padding: 0;
    font-family: 'Arial';

    box-sizing: border-box;
}

body {
    font-weight: 200;
    font-size: 0.46vh;

    background-color: #cde480;

    height: 100vh;
    width: 100vw;

    overflow: hidden;
}

.stage_preset_selection_container {
    display: flex;
    flex-direction: row;

    justify-content: center;
    align-items: center;

    height: 100vh;
    width: 100vw;
    
    transition: transform .5s;
}

.stage_preset_selection_column {
    display: flex;
    flex-direction: column;

    justify-content: space-around;
    align-items: center;
}

.preset_number {
    font-size: 11em;
    color: #394a00;
    font-weight: 400;
    letter-spacing: .1em;
    user-select: none;
    transition: color .3s;
}

.preset_title {
    font-size: 10em;
    color: #394a00;
    letter-spacing: .1em;
    margin-bottom: 3vh;
    user-select: none;
    transition: color .3s;
}

.preset_text_number,
.preset_text {
    font-size: 6em;
    color: #727f45;
    letter-spacing: .1em;
    user-select: none;
}

.last_edited {
    font-size: 4em;
    color: #727f45;
    letter-spacing: .1em;
    margin-top: 3vh;
    user-select: none;
    white-space: nowrap;
}

.empty_preset_title {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, 0%);

    font-size: 10em;
    color: #727f45;
    font-style: italic;
    letter-spacing: .1em;
    user-select: none;

    white-space: nowrap;
}

.stage_preset_information {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
}

.stage_preset {
    position: relative;
    border: 0.56vh solid #394a00;
    border-radius: 4.63vh;
    width: 45vw;
    height: 42vh;
    padding: 3vh 12vh 4vh 4vh;
    margin: 2vh 3vh;
    cursor: pointer;
    box-shadow: 0 1.5vh 1.7vh rgba(0, 0, 0, 0.3);
    user-select: none;
    transition: all .3s;
}

.stage_preset:hover {
    background-color: #394a00;
    transform: translateY(-1vh);
    box-shadow: 0 2.5vh 2.7vh rgba(0, 0, 0, 0.4);
}

.stage_preset:active {
    background-color: #212b00;
    border: 0.56vh solid #212b00;
    transform: translateY(-.5vh);
    box-shadow: 0 2vh 2.2vh rgba(0, 0, 0, 0.35);
}

.stage_preset:hover > .remove_preset_inverted {
    opacity: 100%;
    display: block;
}

.stage_preset:active > .preset_title,
.stage_preset:active > .preset_number,
.stage_preset:hover > .preset_title,
.stage_preset:hover > .preset_number {
    color: #cde480;
}

.toggle_empty_preset {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -100%);
}

.remove_preset {
    position: absolute;
    top: 14%;
    left: 92%;
    transform: translate(-50%, -50%);
    width: 3.33vh;
    height: 3.33vh;
    cursor: pointer;
    transition: all 0.3s;
}

.remove_preset_inverted {
    position: absolute;
    top: 14%;
    left: 92%;
    transform: translate(-50%, -50%);
    width: 3.33vh;
    height: 3.33vh;
    cursor: pointer;
    opacity: 0;
    display: none;
    transition: all 0.3s;
}

.remove_preset_inverted:hover {
    transform: translate(-50%, -60%);
}

.remove_preset_inverted:active {
    transform: translate(-50%, -55%)
}

.stage_preset_selected {
    transform: translateX(-100%);
}

.preset_setup_container {
    position: absolute;
    display: flex;
    top: 0;
    left: 0;
    transform: translateX(100vw);
    transition: all 0.5s;
}

.preset_setup_selected {
    transform: translateX(0);
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div class="stage_preset_selection_container">
        <div class="stage_preset_selection_column">
            <div class="stage_preset" id="stage_preset_1">
                <!-- <div class="preset_number">Preset 1</div>
                    <div class="preset_title">title of the preset</div>
                    <div class="questions_stage stage_preset_information">
                        <div class="preset_text">questions per stage:</div>
                        <div class="preset_text_number">5</div>
                    </div>
                    <div class="number_stages stage_preset_information">
                        <div class="preset_text">number of stages:</div>
                        <div class="preset_text_number">13</div>
                    </div>
                    <div class="number_failure stage_preset_information">
                        <div class="preset_text">number of f for failure:</div>
                        <div class="preset_text_number">3</div>
                    </div>
                    <div class="last_edited">last edited: 30-06-2021 14:51</div>
                    <img src="../../assets/elements/cross.png" alt="remove preset" class="remove_preset">
                    <img src="../../assets/elements/cross_inverted.png" alt="remove preset" class="remove_preset_inverted"> -->

                <!-- <div class="preset_number toggle_empty_preset">Preset 2</div>
                    <div class="empty_preset_title">Empty preset</div> -->
            </div>
            <div class="stage_preset" id="stage_preset_2"></div>
        </div>

        <div class="stage_preset_selection_column">
            <div class="stage_preset" id="stage_preset_3"></div>
            <div class="stage_preset" id="stage_preset_4"></div>
        </div>
    </div>
</body>
</html>

javascript html dom typeerror event-listener
1个回答
-1
投票

答案肯定是通过事件委托附加侦听器,而不是直接附加到动态元素上。这将使您不必在每个“#remove_preset_inverted[num]”上放置一个新的侦听器。

您可以简单地在初始页面加载中执行此操作

window.addEventListener('load', () => {
  document.addEventListener('click', (e) => {
    if (e.target.classList.contains('remove_preset_inverted')) {
      // this is one of those elements. If you need to test for the id:
      let id = e.target.getAttribute('id').split('remove_preset_inverted_')[1];
    }
  })
})
© www.soinside.com 2019 - 2024. All rights reserved.