You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React组件引入外部JS文件实现模态框功能失效问题咨询

核心问题原因

  • 你定义的用于引入main.js的aScript组件没有在Work组件的render方法中渲染,main.js根本没有被加载到页面
  • 就算正确加载了main.js,脚本执行时Work组件的DOM还未挂载到页面,document.getElementById获取到的所有元素都是null,绑定事件监听直接失败
  • 原生JS直接操作DOM的写法和React渲染逻辑冲突,不是React项目的推荐实现方式

快速修复方案(保留现有JS逻辑的写法)

  1. 把aScript组件放到Work组件的render返回的节点里,同时给ScriptTag加isHydrating属性,避免重复执行脚本
  2. 把main.js里的所有逻辑包裹在DOMContentLoaded事件回调里,等页面DOM全部挂载完成再执行元素获取和事件绑定:
// 修改后的main.js代码
document.addEventListener('DOMContentLoaded', function() {
  // 你原来的所有JS逻辑原封不动放到这个回调里即可
  // select the open-btn button
  let openBtn = document.getElementById('open-btn');
  // select the modal-background
  let modalBackground = document.getElementById('modal-background');
  // select the close-btn 
  let closeBtn = document.getElementById('close-btn');

  // shows the modal when the user clicks open-btn
  openBtn.addEventListener('click', function () {
      modalBackground.style.display = 'block';
  });

  // hides the modal when the user clicks close-btn
  closeBtn.addEventListener('click', function () {
      modalBackground.style.display = 'none';
  });

  // hides the modal when the user clicks outside the modal
  window.addEventListener('click', function (event) {
      // check if the event happened on the modal-background
      if (event.target === modalBackground) {
          // hides the modal
          modalBackground.style.display = 'none';
      }
  });

  // select the open-btn button
  let openBtn2 = document.getElementById('open-btn2');
  // select the modal-background
  let modalBackground2 = document.getElementById('modal-background2');
  // select the close-btn 
  let closeBtn2 = document.getElementById('close-btn2');

  // shows the modal when the user clicks open-btn
  openBtn2.addEventListener('click', function () {
      modalBackground2.style.display = 'block';
  });

  // hides the modal when the user clicks close-btn
  closeBtn2.addEventListener('click', function () {
      modalBackground2.style.display = 'none';
  });

  // hides the modal when the user clicks outside the modal
  window.addEventListener('click', function (event) {
      // check if the event happened on the modal-background
      if (event.target === modalBackground2) {
          // hides the modal
          modalBackground2.style.display = 'none';
      }
  });
})
  1. 修改Work组件的render方法,把aScript放到返回节点的最底部:
render() {
  return (
    <section>
      {/* 你原来的所有DOM节点保持不变 */}
      <aScript />
    </section>
  )
}

标准React实现方案(推荐,避免DOM操作冲突)

直接用React的state控制模态框的显示隐藏,不需要额外引入外部JS文件:

import React, { Component } from 'react';

import toDoListApp from '../mockups/to-do-list-img..jpg';
import pokeMockup from '../mockups/mockup-poke.jpg';
import ExpatColMock from '../img/colombia_logo.png';
import DogAPIMock from '../mockups/mockup-doggie.gif';

class Work extends Component {
  // 初始化模态框显示状态
  state = {
    showModal1: false,
    showModal2: false
  }

  render() {
    return (
      <section>
        <div>
          {/* Modal Background and Modal */}
          <div 
            className="mCustomScrollbar" 
            data-mcs-theme="dark" 
            id="modal-background"
            style={{display: this.state.showModal1 ? 'block' : 'none'}}
            onClick={() => this.setState({showModal1: false})}
          >
            <div id="modal" onClick={e => e.stopPropagation()}>
              <span id="close-btn" onClick={() => this.setState({showModal1: false})}>×</span>
              <img className="modal-img" src="mockups/mockup.png" alt="expatcolombia" />
              <h2 className="modal-title">Expat Colombia</h2>
              <div className="modal-text">
                <h3>Description</h3>
                <p>Expat Service for people moving to Colombia. They provide consultations, tours, and assist in housing.</p>
                <h3>Dependencies</h3>
                <p>HTML, CSS, Javascript</p>
              </div>
              <div className="buttons">
                <a href="https://drxl95.github.io/Colombia/" target="_blank" rel="noopener noreferrer">Visit</a>
                <a href="https://github.com/Drxl95/Colombia" target="_blank" rel="noopener noreferrer">Github</a>
              </div>
            </div>
          </div>
          {/* Modal Background and Modal */}
          <div 
            className="mCustomScrollbar2" 
            data-mcs-theme="dark" 
            id="modal-background2"
            style={{display: this.state.showModal2 ? 'block' : 'none'}}
            onClick={() => this.setState({showModal2: false})}
          >
            <div id="modal2" onClick={e => e.stopPropagation()}>
              <span id="close-btn2" onClick={() => this.setState({showModal2: false})}>×</span>
              <img className="modal-img2" src="mockups/poke-mockup.jpg" alt="expatcolombia" />
              <h2 className="modal-title">PokemonAPI</h2>
              <div className="modal-text2">
                <h3>Description</h3>
                <p>Pokemon-themed App with a that includes names, images, and stats of different Pokemons.</p>
                <h3>Dependencies</h3>
                <p>Javascript, JQuery, Ajax</p>
              </div>
              <div className="buttons2">
                <a href="poke_demo.html" target="_blank" rel="noopener noreferrer">Demo</a>
                <a href="https://github.com/Drxl95/PokemonAPI" target="_blank" rel="noopener noreferrer">Github</a>
              </div>
            </div>
          </div>
        </div>
        <div>
          <header className="ScriptHeader">
            <div>
              <h1>My Work</h1>
            </div>
          </header>
          <section id="work">
            {/* Image row 1 */}
            <div className="row">
              <div className="column">
                <div className="container">
                  <img src={toDoListApp} className="image" alt="to-do-list-api" />
                  <a href="https://github.com/Drxl95/To-Do-List" target="_blank" rel="noopener noreferrer">
                    <div className="overlay">
                      <div className="text">Simple jQuery To Do List App</div>
                    </div>
                  </a>
                </div>
              </div>
              <div className="column">
                <a id="open-btn2" onClick={() => this.setState({showModal2: true})}>
                  <div className="container">
                    <img src={pokeMockup} className="image" alt="PokemanAPI" />
                    <div className="overlay">
                      <div className="text">Pokemon-themed API app <br /></div>
                    </div>
                  </div>
                </a>
              </div>
              <div className="column">
                <a id="open-btn" onClick={() => this.setState({showModal1: true})}>
                  <div className="container">
                    <img src={ExpatColMock} className="image" alt="expatcolombia.com" />
                    <div className="overlay">
                      <div className="text">Expat Colombia</div>
                    </div>
                  </div>
                </a>
              </div>
              <div className="column">
                <a href="https://github.com/Drxl95/DogAlbum" target="_blank" rel="noopener noreferrer">
                  <div className="container">
                    <img src={DogAPIMock} className="image" alt="dogAPI-mockup" />
                    <div className="overlay">
                      <div className="text">Dog Album API</div>
                    </div>
                  </div>
                </a>
              </div>
            </div>
          </section>
        </div>
      </section>
    )
  }
}

export default Work

该方案完全通过React内部状态控制模态框显隐,不会出现DOM操作冲突的问题。

内容的提问来源于stack exchange,提问作者RDX10290

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 17:57:00