使用Golang时Javascript无法正常运行的问题

使用Golang时Javascript无法正常运行的问题 如果我在 jsfiddle 中使用,这段代码能正常工作:

const btns = document.querySelectorAll(".btn");
const nav = document.querySelector(".nav");

https://jsfiddle.net/0x54fL7t/10/

在 Go 中使用 Javascript 时,querySelectorAll() 能工作… imagequerySelector 不行

image 为什么完全相同的代码在 Go 环境外能工作,但在 Go 中使用时就不行?

有什么建议能指出我做错了什么吗?


更多关于使用Golang时Javascript无法正常运行的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

Sibert:

为什么完全相同的代码在 Go 之外可以工作,但在 Go 中却不行?

你这是什么意思?你如何“使用 Go”来执行 JavaScript?

更多关于使用Golang时Javascript无法正常运行的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我找到了原因。

<head> 
   <script src="/js/nav.js" defer></script> 
</head>

原来JavaScript在页面加载之前就被加载了。通过添加defer属性,问题得到了解决。

这是什么意思?

在 main 中:

func init() {
tpl = template.Must(template.ParseGlob("public/templates/*.html"))
http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("./public/js"))))
}

在 httphead 中:

<head>
    <script type="text/javascript" src="/js/nav.js"></script >
</head>

在主模板中:

  <div class="nav">
      {{template "nav" ("faq")}}
  </div>

在 nav.js 中

const btns = document.querySelectorAll(".btn");
const nav = document.querySelector(".nav");

alert(nav)
alert(btns)

所以 JavaScript 是由模板内的 head 部分调用的。

奇怪的是:

document.querySelectorAll(".btn") ...有效
document.querySelector(".nav"); ...失败

唯一的区别是 .btn 在一个子模板中。在 Go 环境之外,两者都有效。

Edit fiddle - JSFiddle - Code Playground

Edit fiddle - JSFiddle - Code Playground

使用 JSFiddle 代码编辑器在线测试你的 JavaScript、CSS、HTML 或 CoffeeScript。

在Go中使用JavaScript时遇到querySelector无法正常工作的问题,通常是由于DOM操作时机或执行环境差异导致的。以下是可能的原因和解决方案:

1. DOM未完全加载

在Go的Web服务器环境中,JavaScript可能在DOM完全加载前执行:

// main.go
package main

import (
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte(`
<!DOCTYPE html>
<html>
<head>
    <title>Test</title>
</head>
<body>
    <div class="nav">Navigation</div>
    <button class="btn">Button 1</button>
    <button class="btn">Button 2</button>
    
    <script>
        // 错误:DOM未加载完成时执行
        const nav = document.querySelector(".nav");
        console.log(nav); // 可能为null
        
        // 正确:等待DOM加载完成
        document.addEventListener("DOMContentLoaded", function() {
            const nav = document.querySelector(".nav");
            const btns = document.querySelectorAll(".btn");
            console.log("Nav element:", nav);
            console.log("Buttons found:", btns.length);
        });
    </script>
</body>
</html>
        `))
    })
    
    http.ListenAndServe(":8080", nil)
}

2. 使用defer或DOMContentLoaded事件

确保JavaScript在DOM解析完成后执行:

// 在HTML模板中正确使用
const htmlTemplate = `
<!DOCTYPE html>
<html>
<head>
    <title>Go JS Test</title>
    <script>
        // 方法1:使用DOMContentLoaded
        document.addEventListener('DOMContentLoaded', function() {
            const nav = document.querySelector('.nav');
            const btns = document.querySelectorAll('.btn');
            
            if (nav) {
                console.log('Nav found:', nav.textContent);
            } else {
                console.log('Nav not found');
            }
            
            console.log('Buttons count:', btns.length);
        });
        
        // 方法2:将script标签放在body末尾
    </script>
</head>
<body>
    <div class="nav">Navigation Bar</div>
    <button class="btn">Click 1</button>
    <button class="btn">Click 2</button>
    
    <script>
        // 这里可以安全访问DOM
        const nav = document.querySelector('.nav');
        console.log('Direct access:', nav);
    </script>
</body>
</html>
`

3. 检查元素选择器

确保选择器与HTML结构匹配:

// 生成包含正确类名的HTML
func generateHTML() string {
    return `
<!DOCTYPE html>
<html>
<body>
    <!-- 确保类名完全匹配 -->
    <div class="nav"> <!-- 注意:这里是 "nav" 不是 ".nav" -->
        <ul>
            <li>Item 1</li>
        </ul>
    </div>
    
    <button class="btn">Button A</button>
    <button class="btn">Button B</button>
    
    <script>
        // 等待微小延迟确保DOM就绪
        setTimeout(() => {
            const nav = document.querySelector('.nav'); // 选择器正确
            const btns = document.querySelectorAll('.btn');
            
            console.log('Nav element:', nav);
            console.log('Nav innerHTML:', nav ? nav.innerHTML : 'null');
            console.log('Number of buttons:', btns.length);
            
            // 验证选择器
            if (!nav) {
                console.log('Checking all divs:');
                const allDivs = document.querySelectorAll('div');
                allDivs.forEach((div, i) => {
                    console.log(`Div ${i}:`, div.className);
                });
            }
        }, 100);
    </script>
</body>
</html>
`
}

4. 完整的Go Web服务器示例

package main

import (
    "net/http"
    "time"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        html := `
<!DOCTYPE html>
<html>
<head>
    <title>Go JavaScript Test</title>
    <style>
        .nav { background: #f0f0f0; padding: 10px; }
        .btn { margin: 5px; padding: 8px 16px; }
    </style>
</head>
<body>
    <div class="nav" id="mainNav">Main Navigation</div>
    <div>
        <button class="btn" data-id="1">Button 1</button>
        <button class="btn" data-id="2">Button 2</button>
        <button class="btn" data-id="3">Button 3</button>
    </div>
    
    <script>
        // 使用多种方式确保DOM就绪
        function init() {
            // 方法1: querySelector
            const nav = document.querySelector('.nav');
            console.log('querySelector result:', nav);
            
            // 方法2: getElementsByClassName (备用)
            const navAlt = document.getElementsByClassName('nav')[0];
            console.log('getElementsByClassName result:', navAlt);
            
            // 方法3: querySelectorAll
            const btns = document.querySelectorAll('.btn');
            console.log('querySelectorAll buttons:', btns.length);
            
            // 添加事件监听器验证
            if (nav) {
                nav.style.border = '2px solid blue';
            }
            
            btns.forEach(btn => {
                btn.addEventListener('click', function() {
                    console.log('Button clicked:', this.dataset.id);
                });
            });
        }
        
        // 确保DOM完全加载
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', init);
        } else {
            init();
        }
    </script>
</body>
</html>
        `
        
        w.Header().Set("Content-Type", "text/html; charset=utf-8")
        w.Write([]byte(html))
    })
    
    server := &http.Server{
        Addr:         ":8080",
        ReadTimeout:  10 * time.Second,
        WriteTimeout: 10 * time.Second,
    }
    
    server.ListenAndServe()
}

运行这个Go服务器并访问http://localhost:8080,打开浏览器控制台查看输出。如果querySelector仍然返回null,检查浏览器控制台是否有错误信息,并验证HTML结构是否按预期渲染。

回到顶部