NodeJs actual combat - to-do list 3 - front-end page filling to-do data
Why fill the pending data at the front end?
The page data in Section 2 is filled in the background, so there is a problem. Every time the to-do list changes, you need to return to the page again, resulting in returning to the entire page every time you update the to-do list
How to populate pending data on the front end?
What you need to know
- ajax send http request
- Add, delete, modify and check jQuery operation DOM elements
page modification
-
- The tag adds an id, which is required for subsequent operations on the DOM
<ul id="todo_ul"></ul>
- When the page is initialized, use ajax to send a request to get the pending data of the backend service
function init() {
$.ajax({
url: "/query",
method: 'GET',
success: function(result) {
initUlData(result);
}
});
}
- The server returns the result data, and the front-end page draws and fills the pending data
function initUlData(result) {
if (result.code == '0') {
alert(result.msg);
} else {
$('#todo_ul').empty();
if (result.data == null) {
alert('服务器返回数据为空');
return ;
}
result.data.forEach(a => {
$('#todo_ul').append( $('<li></li>').html(a));
});
}
}
- The init() method is called when the page is initialized
$(function() {
init();
}
- full index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>待办列表</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
<script type="text/javascript">
$(function() {
init();
$("#add").on('click', function(){
add();
});
$("#complete").on('click', function(){
complete();
});
});
function init() {
$.ajax({
url: "/query",
method: 'GET',
success: function(result) {
initUlData(result);
}
});
}
function add() {
var item = $("#item_text").val().trim();
if (item.length == 0) {
alert('输入数据不能为空');
}
$.ajax({
url: "/add",
method: 'GET',
data: {
item: item
},
success: function(result) {
initUlData(result);
}
});
}
function complete() {
var item = $("#item_text").val().trim();
if (item.length == 0) {
alert('输入数据不能为空');
}
$.ajax({
url: "/complete",
method: 'GET',
data: {
item: item
},
success: function(result) {
initUlData(result);
}
});
}
function initUlData(result) {
if (result.code == '0') {
alert(result.msg);
} else {
$('#todo_ul').empty();
if (result.data == null) {
alert('服务器返回数据为空');
return ;
}
result.data.forEach(a => {
$('#todo_ul').append( $('<li></li>').html(a));
});
focusItemText();
}
}
function focusItemText() {
$('#item_text').val('');
$('#item_text').focus();
}
</script>
</head>
<body>
<h1>待办列表</h1>
<form method="post" >
<p><input id="item_text" type="text" name="item" /></p>
<p><input id="add" type="button" value="添加" /></p>
<p><input id="complete" type="button" value="完成" /></p>
</form>
<ul id="todo_ul"></ul>
</body>
</html>
Backend service encapsulates data return
The back-end service uses json data to return to the front-end. The json structure is clear, and it is more convenient for the front-end to parse the json.
server.js modification
- Add an object to store the returned data
let retData = {
'code':'',
'data': [],
'msg':''
}
How to turn an object into a string?
Open the browser developer tool console and try
2. Add the server output json method
function sendMsg(response, msg) {
response.writeHead(200, {
'Content-Type': 'application/json;charset=UTF-8'});
response.write(msg);
response.end();
}
Note: You need to specify the Content-Type as application/json
- Modify the readFile logic, no need to fill in the data, refresh to return to the page
function readFile(response, filePath) {
fs.readFile(filePath, (err, data) => {
if (err) {
return send404(response);
}
var html = data.toString();
response.writeHead(200, {
'Content-Type': 'text/html'});
response.end(html);
});
}
- Add /query, / execution logic method
const server = http.createServer((request, response) => {
var urlParse = parse(request.url);
var urlPath = urlParse.pathname;
switch (urlPath) {
case '/':
var filePath = 'public/index.html';
var absPath = './' + filePath;
readFile(response, absPath);
break;
case '/query':
sendMsg();
break;
case '/add':
sendMsg();
break;
case '/complete':
sendMsg();
break;
}
});
The server is modified to only load the HTML page when reading the home page, and return json data when accessing other addresses
- Complete server.js code
const http = require('http');
const fs = require('fs');
const parse = require('url').parse;
const hostname = '127.0.0.1';
const port = 3000;
const CODE_ERROR = 0;
const CODE_SUCCESS = 1;
var todoSet = new Set();
function send404(response) {
response.writeHead(404, {
'Content-Type': 'text/plain'});
response.write('Error 404: resource not found.');
response.end();
}
function sendMsg(response, msg) {
response.writeHead(200, {
'Content-Type': 'application/json;charset=UTF-8'});
response.write(msg);
response.end();
}
function readFile(response, filePath) {
fs.readFile(filePath, (err, data) => {
if (err) {
return send404(response);
}
var html = data.toString();
// html = html.replace('%', Array.from(todoSet).join('</li><li>'));
response.writeHead(200, {
'Content-Type': 'text/html'});
response.end(html);
});
}
function add(itemData) {
todoSet.add(itemData);
}
function complete(itemData) {
// 判断待办事项是否已添加
if (!todoSet.has(itemData)) {
return itemData + '-待办事项不存在';
}
if (todoSet.delete(itemData)) {
return true;
}
return itemData + '-待办事项删除失败';
}
function findItemData(urlParse) {
if (urlParse.query.length > 0) {
var queryArray = urlParse.query.split('=');
if (queryArray.length >= 2) {
return queryArray[1];
}
}
return '';
}
function buildData(code, data, msg) {
// 返回数据
let retData = {
'code':'',
'data': [],
'msg':''
}
retData.code = code;
retData.data = data;
retData.msg = msg;
return retData;
}
const server = http.createServer((request, response) => {
var urlParse = parse(request.url);
var urlPath = urlParse.pathname;
var itemData;
if (urlPath == '/add' || urlPath == '/complete') {
itemData = findItemData(urlParse);
if (itemData.length == 0) {
var data = buildData(CODE_ERROR, [], '输入数据有误');
return sendMsg(response, JSON.stringify(data));
}
}
switch (urlPath) {
case '/':
var filePath = 'public/index.html';
var absPath = './' + filePath;
readFile(response, absPath);
break;
case '/query':
var data = buildData(CODE_SUCCESS, Array.from(todoSet), '页面初始化');
sendMsg(response, JSON.stringify(data));
break;
case '/add':
add(itemData);
var data = buildData(CODE_SUCCESS, Array.from(todoSet), '添加成功');
sendMsg(response, JSON.stringify(data));
break;
case '/complete':
var res = complete(itemData)
if (res == true) {
var data = buildData(CODE_SUCCESS, Array.from(todoSet), '待办已完成');
return sendMsg(response, JSON.stringify(data));
}
var data = buildData(CODE_ERROR, [], res);
sendMsg(response, JSON.stringify(data));
break;
}
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${
hostname}:${
port}/`)
})
renderings
Execute node server.js to start the service
F:\Github\Nodejs\todolist>node server.js
Server running at http://127.0.0.1:3000/
initialization page
Add to-do
- add 111
- add en111
- Added Chinese 111
and found a small problem, the Chinese characters are garbled, follow-up processing
Complete to-dos
- complete 111
- Completion of Chinese 111