React组件引入外部JS文件实现模态框功能失效问题咨询
核心问题原因
- 你定义的用于引入main.js的
aScript组件没有在Work组件的render方法中渲染,main.js根本没有被加载到页面 - 就算正确加载了main.js,脚本执行时Work组件的DOM还未挂载到页面,
document.getElementById获取到的所有元素都是null,绑定事件监听直接失败 - 原生JS直接操作DOM的写法和React渲染逻辑冲突,不是React项目的推荐实现方式
快速修复方案(保留现有JS逻辑的写法)
- 把
aScript组件放到Work组件的render返回的节点里,同时给ScriptTag加isHydrating属性,避免重复执行脚本 - 把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'; } }); })
- 修改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
相关产品推荐
相关产品推荐

