有没有更简单的方法通过HTML按钮在Node.js中调用JS函数?

huangapple go评论86阅读模式
英文:

Is there an easier way to call JS functions in Node.js via HTML-buttons?

问题

JS代码部分:

const fetch = require("fetch");
const jsdom = require('jsdom');
const http = require('http');
const fs = require('fs');
var url = require('url');
const port = 3000

const server = http.createServer(function(req, res) {
    
    var q = url.parse(req.url);
    var filename = "." + q.pathname;
    console.log(req.url)

    if (req.url == '/') {
        res.writeHead(301, { Location: 'http://localhost:3000/frontpage.html' })
        res.end()
        } else {
            res.writeHead(200, { 'Content-Type': 'text/html' })
            fs.readFile(filename, function(error, data) {
                if(error) {
                    res.writeHead(404)
                    res.write('Error: File Not Found')
                } else {
                    res.writeHead(200, { 'Content-Type': 'text/html' })
                    res.write(data)
                }
                return res.end()
            })
    }
})

server.listen(port, function(error) {
    if (error) {
        console.log('Something went wrong', error)
    } else {
        console.log('Server is listening on port ' + port)
    }
})

const { JSDOM } = jsdom;

const { document } = (new JSDOM('frontpage.html')).window;
global.document = document;
var button = document.getElementById("meinButton")
button.addEventListener("click", fetch.register_medication);

HTML元素部分:

<script src="fetch.js"></script>
    
<button id="meinButton">Klick mich!</button>
英文:

I'm trying to add a JavaScript function that I wrote myself, to an HTML button which I also did myself. I'm having problems calling the document.getElementById() function because I'm working with Node.js. I read in some other forum, you can work around that with JSDOM. Now I'm having problems with that. Is there any other solution which is easier than the JSDOM-way? I also can't really use JSDOM because it would require a new installation which couldn't be done in the intire team time-wise.

JS code

const fetch = require(&quot;./fetch&quot;);
const jsdom = require(&#39;jsdom&#39;);
const http = require(&#39;http&#39;);
const fs = require(&#39;fs&#39;);
var url = require(&#39;url&#39;);
const  port = 3000
const server = http.createServer(function(req, res) {
var q = url.parse(req.url);
var filename = &quot;.&quot; + q.pathname;
console.log(req.url)
if (req.url == &#39;/&#39;) {
res.writeHead(301, { Location: &#39;http://localhost:3000/frontpage.html&#39; })
res.end()
} else {
res.writeHead(200, { &#39;Content-Type&#39;: &#39;text/html&#39; })
fs.readFile(filename, function(error, data) {
if(error) {
res.writeHead(404)
res.write(&#39;Error: File Not Found&#39;)
} else {
res.writeHead(200, { &#39;Content-Type&#39;: &#39;text/html&#39; })
res.write(data)
}
return res.end()
})
}
})
server.listen(port, function(error) {
if (error) {
console.log(&#39;Something went wrong&#39;, error)
} else {
console.log(&#39;Server is listening on port &#39; + port)
}
})
const { JSDOM } = jsdom;
const { document } = (new JSDOM(&#39;frontpage.html&#39;)).window;
global.document = document;
var button = document.getElementById(&quot;meinButton&quot;)
button.addEventListener(&quot;click&quot;, fetch.register_medication);

HTML Elements

    &lt;script scr=&quot;fetch.js&quot;&gt;&lt;/script&gt;
&lt;button id=&quot;meinButton&quot;&gt;Klick mich!&lt;/button&gt;

答案1

得分: 0

看起来你已经混淆了服务器端代码和客户端代码。NodeJS 是用于服务器端的;客户端活动,如在按钮上添加事件处理程序,应在客户端运行,而不是嵌入在 Node 脚本中。这可能会令人困惑,因为它们都是用相同的语言编写的(使用不同的库),而一些现代工具链和库在概念上模糊了服务器端和客户端代码之间的区别,但它们在完全不同的上下文中执行,不能混合在一起。

你的代码的第一部分是为 Node 服务器而设计的,将在主机上执行;它看起来正在检查(服务器的)文件系统以匹配 URL,然后使用 fs 读取它们,并将内容发送到浏览器:

const server = http.createServer(function(req, res) {
    var q = url.parse(req.url);
    var filename = "." + q.pathname;
    if (req.url == '/') {
        res.writeHead(301, { Location: 'http://localhost:3000/frontpage.html' })
        res.end()
    } else {
        res.writeHead(200, { 'Content-Type': 'text/html' })
        fs.readFile(filename, function(error, data) {
            if (error) {
                res.writeHead(404)
                res.write('Error: File Not Found')
            } else {
                res.writeHead(200, { 'Content-Type': 'text/html' })
                res.write(data)
            }
            return res.end()
        })
    }
})

server.listen(port, function(error) {
    if (error) {
        console.log('Something went wrong', error)
    } else {
        console.log('Server is listening on port ' + port)
    }
})

(我不是 Node 方面的专家,所以不确定是否这是最佳方法来实现它,但看起来应该可以工作。)

然而,接下来的部分是普通的 JavaScript。它应该在浏览器中运行,而不是在服务器上:

var button = document.getElementById("meinButton")
button.addEventListener("click", fetch.register_medication);

实现这一点的最简单方法是将其存储在自己的 .js 文件中,与 Node 脚本分开,并让需要它的每个网页使用 &lt;script src="/path/to/clientside.js"&gt; 加载它。(此路径应该是相对于网站根目录的,就像图像或 CSS 文件一样;它不会与你的 NodeJS 路径相同)。Node 本身不需要知道这个 .js 文件的存在;它将由浏览器直接请求并在浏览器中执行。

jsdom 是 Node 的一部分,用于在将 HTML 发送到浏览器之前执行 DOM 操作,在某些情况下非常有用,但对于你在这里处理的更复杂用例来说,可以跳过所有这些步骤,直接使用 getElementById 函数。

(在评论中,你提到尝试分离 JavaScript 但遇到错误 "ReferenceError: document is not defined" — 这是一个 Node 的错误消息,这表明你仍然试图在服务器上运行脚本,而不是在浏览器中运行。确保是网页本身,而不是 Node,请求应在浏览器中运行的任何 JavaScript。)

英文:

It looks like you've gotten your serverside code and your clientside code mixed up. NodeJS is for the server; clientside activity such as adding an event handler to a button should be running in the client, not embedded inside a node script. It can be confusing, since both are written in the same language (with different libraries available), and some modern toolchains and libraries kind of conceptually blur the difference between serverside and clientside code -- but they're executed in completely different contexts and can't be intermingled.

This first part of your code is meant for the node server, and will be executed on the host; it looks like what it's doing is checking the (server's) filesystem for paths that match the url, reading them using fs, and sending the contents on to the browser:

const server = http.createServer(function(req, res) {
var q = url.parse(req.url);
var filename = &quot;.&quot; + q.pathname;
if (req.url == &#39;/&#39;) {
res.writeHead(301, { Location: &#39;http://localhost:3000/frontpage.html&#39; })
res.end()
} else {
res.writeHead(200, { &#39;Content-Type&#39;: &#39;text/html&#39; })
fs.readFile(filename, function(error, data) {
if(error) {
res.writeHead(404)
res.write(&#39;Error: File Not Found&#39;)
} else {
res.writeHead(200, { &#39;Content-Type&#39;: &#39;text/html&#39; })
res.write(data)
}
return res.end()
})
}
})
server.listen(port, function(error) {
if (error) {
console.log(&#39;Something went wrong&#39;, error)
} else {
console.log(&#39;Server is listening on port &#39; + port)
}
})

(I'm far from expert in Node, so I'm not sure if that's the best way to do what it's doing, but it looks like it should work.)

This next part, though, is plain javascript. It should be run in the browser, not on the server:

var button = document.getElementById(&quot;meinButton&quot;)
button.addEventListener(&quot;click&quot;, fetch.register_medication);

The simplest way to accomplish that would be to store this in its own .js file, separate from the node scripts, and have each web page that needs it load it using &lt;script src=&quot;/path/to/clientside.js&quot;&gt;. (This path should be relative to the web root, just like for images or css files; it will not be the same as your nodejs paths). Node itself doesn't need to know anything about this .js file; it'll be requested directly by the browser and executed there.

jsdom is part of Node which is used to perform DOM operations before sending the html to the browser, which is useful in some situations but for much more complicated use cases than what you're dealing with here. You can skip all that and go straight to the getElementById fun.

(In a comment you mentioned trying to separate the js but getting the error "ReferenceError: document is not defined" -- that's a Node error message, which suggests that you were still trying to run the script on the server instead of in the browser. Make sure it's the web page itself, not node, that requests any js that should run in the browser.)

答案2

得分: -2

我不确定您在这里尝试使用JSDOM做什么,但从阅读您的问题来看,我认为您只是想让页面上的按钮向您的API发出POST请求更多信息在这里

然后,在您的Node应用程序响应请求的地方,您可以检测REST API调用并在那里执行您的工作,就像这样:

if (req.url == '/') {
  // ...这里的内容保持不变
}else if (req.url.indexOf("register_medication") == 0){
  // 在这里调用您的行为
}

如果您希望为用户提供带有修改的页面,您需要在提供文件之前处理它,但我不确定这是否是您想要的?

英文:

I'm not sure what you're trying to do with JSDOM here, but from reading your question, I think you just want the button on your page to do a post to your api more info here

Then where your node app is responding to requests, you can detect the REST API call and do your work there like this:

if (req.url == &#39;/&#39;) {
// ...the stuff here is fine as is
}else if (req.url.indexOf(&quot;register_medication&quot;) == 0){
// call your behaviour here
}

If you wanted to serve the page with modifications in for the user, you'd need to take care of that before serving the file, but I don't think that's what you want?

huangapple
  • 本文由 发表于 2023年6月22日 02:15:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526087.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定