在另一个 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 文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Node js 操作 DOM?

如何在dojo工具包的Current JS文件中使用在另一个JS文件中创建的Dialog变量

2017-3-29js语法 DOM操作

vue 项目中如何动态配合API请求地址?

小程序如何使用linq.js,在小程序中引用linq.js后运行报错

廖雪峰js教程笔记11 操作DOM(包含作业)