React中import机制与渲染顺序疑问:为何先渲染App.js而非A.js?
为什么先引入A.js却最终显示App.js的渲染结果?
核心原因:模块执行顺序 + ReactDOM.render的覆盖逻辑
你遇到的现象不是App.js先执行,而是A.js先执行渲染,但立刻被后执行的App.js的渲染操作覆盖了,结合Webpack的模块处理逻辑,具体拆解如下:
Webpack的模块执行顺序严格遵循import顺序
Webpack打包时会按照你在index.js里写的import顺序同步执行模块代码:- 先执行
import './A.js',A.js里的代码先运行:创建root实例,把#root元素的内容渲染成46 - 接着执行
import './App.js',App.js的代码随后执行:创建root实例(React 18中对同一个DOM节点多次调用createRoot会复用已有实例),把#root的内容替换成App组件的UI
你可以在两个文件里加console.log验证:A.js加console.log('A模块执行'),App.js加console.log('App模块执行'),打开控制台会看到A的日志先出现,再出现App的日志——这证明模块执行顺序完全符合你写的import顺序。
- 先执行
ReactDOM.render的本质是替换目标DOM的内容
不管你创建多少次root实例,只要目标是同一个#root节点,每次调用render()都会完全替换该节点内的所有内容。所以A.js先把#root改成46,紧接着App.js的render就把这个内容换成了App的组件结构,最终页面上只会留下最后一次render的结果。
直观验证方法
修改A.js和App.js,添加日志并延迟渲染App的内容:
// A.js import ReactDOM from 'react-dom/client'; const test=46; console.log('A模块执行'); const root = ReactDOM.createRoot(document.getElementById('root')); root.render(test);
// App.js import logo from './logo.svg'; import './App.css'; import ReactDOM from 'react-dom/client'; function App() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p>Edit <code>src/App.js</code> and save to reload.</p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> ); } console.log('App模块执行'); // 延迟2秒渲染,就能看到先显示46,再变成App的UI setTimeout(() => { const root2 = ReactDOM.createRoot(document.getElementById('root')); root2.render(<App />); }, 2000);
此时打开页面会先看到46,2秒后变成App的界面,完美验证了执行顺序和覆盖逻辑。
内容的提问来源于stack exchange,提问作者leo_256
相关产品推荐
相关产品推荐

