在另一个 js 文件中进行 dom 操作后,如何运行 javascript 文件?
Posted
技术标签:
【中文标题】在另一个 js 文件中进行 dom 操作后,如何运行 javascript 文件?【英文标题】:How can I run javascript file after dom manipulation made in another js file? 【发布时间】:2021-03-18 09:07:48 【问题描述】:当我运行我的 rails 应用程序并在控制台中输入 likeButton 时,它给了我 Uncaught ReferenceError: likeButton is not defined 在:1:1 (匿名)@ VM1591:1 我尝试将 html 中的脚本移动到头部和正文。我目前正在尝试使用 DOMContentLoaded 但似乎我遗漏了一些东西。我的总体目标是在按下按钮后更改按钮的颜色,并在页面刷新后保持颜色。我在这个过程中使用 sessionStorage。我只想确保在加载 html 后声明 likeButton 变量。如果可以仅在 javascript 中完成。
//first js file
const BASE_URL = "http://localhost:3000"
const GPUS_URL = `$BASE_URL/gpus`
const USERS_URL = `$BASE_URL/users`
const gpuCollection = document.querySelector('#gpu-collection')
let wish = sessionStorage.getItem('wish');
class Gpu
constructor(gpuAttributes)
this.title = gpuAttributes.title;
this.price = gpuAttributes.price;
this.features = gpuAttributes.features;
this.link = gpuAttributes.link;
this.image = gpuAttributes.image;
this.id = gpuAttributes.id;
render()
let div = document.createElement('div');
div.classList.add('card');
let h = document.createElement('h2');
let t = document.createTextNode(`$this.title ($$this.price)`);
h.appendChild(t);
div.appendChild(h);
let h1 = document.createElement('h1');
h1.classList.add('gpu-cat');
h1.innerHTML = `$this.features`;
div.appendChild(h1);
let button = document.createElement('button');
button.classList.add('list_btn');
button.innerHTML = '♡';
div.appendChild(button);
let a = document.createElement('a');
let img = document.createElement('img');
a.href = `$this.link`;
a.target = '_blank';
img.src = `$this.image`;
img.classList.add('gpu-image');
a.appendChild(img);
div.appendChild(a);
gpuCollection.appendChild(div);
//second js file
document.addEventListener("DOMContentLoaded", function ()
let likeButton;
SignUp();
logInUser();
logOutUser();
function putGpusOnDom(gpuArray)
gpuArray.forEach(gpu =>
let newGpu = new Gpu(gpu)
newGpu.render()
);
likeButton = document.querySelector("button");
function fetchGpus()
fetch(GPUS_URL)
.then(res => res.json())
.then(gpus => putGpusOnDom(gpus))
const enableWish = () =>
console.log(likeButton)
sessionStorage.setItem('wish', 'red')
gpuCollection.addEventListener('click', function ()
wish = sessionStorage.getItem('wish');
if(wish !== 'red')
enableWish();
else
disableWish();
);
)
//html file
...
<body>
<div id = "gpu-collection"></div>
<script type="text/javascript" src="src/Gpu.js"></script>
<script type="text/javascript" src="src/index.js" ></script>
</body>
</html>
【问题讨论】:
如果按钮不是原始 DOM 的一部分而是由 javascript 添加的,则它不会出现在 DOMContentLoaded 上 更多关于div.appendChild(button);
,您似乎没有在您提供给我们的代码中定义div
。
对不起,我不是有意忽略它,但我确实将它包含在我的原始代码中。
可以提供minimal reproducible example吗?对于其中的最小部分,您可能可以排除登录内容,它看起来与问题无关。
我刚刚意识到 当我运行我的 rails 应用程序并在控制台中输入 likeButton 它给了我 Uncaught ReferenceError: likeButton is not defined at 的含义: 1:1(匿名)@ VM1591:1 。正如您将likeButton
定义为const
和我let
我相信它超出了直接进入控制台的范围。请参阅:ui.dev/var-let-const
【参考方案1】:
正如我在评论中提到的,如果动态添加,DOMContentLoaded
上的点赞按钮不可用。您需要等到按钮被放置在 DOM 中
使用类似下面的东西,我在这里做一些猜测,因为你的代码中有一些空白
document.addEventListener("DOMContentLoaded", function ()
//document.querySelector("button"); not yet available
//NOTE: The likeButton variable will ONLY be in scope INSIDE the event listener function
// You will not be able to access directly in the console.
let likeButton;
SignUp();
logInUser();
logOutUser();
function putGpusOnDom(gpuArray)
gpuArray.forEach(gpu =>
let newGpu = new Gpu(gpu)
newGpu.render()
);
//Now you have rendered the button it is available
//CAUTION: querySelector("button") will grab the first button on the page
// and ONLY the first button
likeButton = document.querySelector("button");
//Log like button to console while it is still in scope.
console.log(likeButton);
function fetchGpus()
fetch(GPUS_URL)
.then(res => res.json())
.then(gpus => putGpusOnDom(gpus))
const enableWish = () =>
console.log(likeButton)
sessionStorage.setItem('wish', 'red')
)
【讨论】:
我更新了我的代码以填补空白。我尝试了你的方法,我仍然得到相同的结果。该按钮未在 html 文件中定义。以上是关于在另一个 js 文件中进行 dom 操作后,如何运行 javascript 文件?的主要内容,如果未能解决你的问题,请参考以下文章
如何在dojo工具包的Current JS文件中使用在另一个JS文件中创建的Dialog变量