js 代码保持运行,即使元素从页面中删除。
使用
react-js
编码时的第一个困难。因为页面没有重新加载所以初始脚本仍在运行,如setInterval,websocket,etc
代码。下面的简单示例元素已被删除但仍在运行。如果我必须使用全局变量创建则无效。这将是一个安全漏洞
<button onclick="createNewJsCode()">create new js</button>
<button onclick="removeJsCode()">remove js</button>
<script>
let id = ''
function createNewJsCode(){
let s = document.createElement('script')
let code = 'setInterval(`console.log(new Date())`,500)'
s.id = (id = crypto.randomUUID())
s.appendChild(document.createTextNode(code));
document.body.appendChild(s);
}
function removeJsCode(){
document.getElementById(id).remove()
}
</script>
被视为 React 问题,下面是在 React 组件中使用
setInterval
的示例。如果您使用某种形式的 React Router,下面的代码也将正确卸载/挂载等
const {useState, useEffect} = React;
function Page() {
const [counter, setCounter] = useState(0);
useEffect(() => {
const i = setInterval(() => {
console.log(new Date());
setCounter(c => c +1);
}, 1000);
return () => {
console.log('umount');
clearInterval(i);
}
}, []);
return <div>
This is a page, and when unmounted will end the setInterval. <br/>Counter: {counter}, time: {new Date().toLocaleString()}<br/> Check console you will also see console logging of datetime finishes.
</div>
}
function OtherInfo() {
return <div>
Notice how the timer stopped inside the console. <br/> If you click Show Page the component will be mounted again, this is kind of the basis of how React Router works in a Single Page Application (SPA).
</div>
}
function App() {
const [pageVis, setPageVis] = useState(true);
return <div>
{pageVis && <Page/>}
{!pageVis && <OtherInfo/>}
<hr/>
{pageVis && <button onClick={() => setPageVis(false)}>Unmount Page</button>}
{!pageVis && <button onClick={() => setPageVis(true)}>Show Page</button>}
</div>
}
const root = ReactDOM.createRoot(document.querySelector('#mount'));
root.render(<App/>);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="mount"></div>
你不能只删除
<script>
节点,你必须做一些更具体的清理工作。
setInterval
返回一个间隔 ID,您可以将其传递给 clearInterval
以停止它。
一般来说,我会说你的代码在 React 上下文中没有多大意义,但在你的情况下你可以这样做:
<button onclick="createNewJsCode()">create new js</button>
<button onclick="removeJsCode()">remove js</button>
<script>
let id;
let intervalId;
function createNewJsCode(){
let s = document.createElement('script')
let code = 'intervalId = setInterval(`console.log(new Date())`,500)'
s.id = (id = crypto.randomUUID())
s.appendChild(document.createTextNode(code));
document.body.appendChild(s);
}
function removeJsCode(){
clearInterval(intervalId);
document.getElementById(id).remove()
}
</script>