NodeJs实战-待办列表(3)-前端页面填充待办数据

为啥在前端填充待办数据?

第2节的页面数据在后台填充的,这样有个问题,每次待办列表发生变化,都需要重新返回页面,导致每次更新待办都要返回整个页面

如何在前端填充待办数据?

需要了解的知识

  1. ajax 发送http请求
  2. jQuery操作DOM元素增删改查

页面修改

    • 标签增加 id,后续操作DOM时需要使用这个id
<ul id="todo_ul"></ul>
  1. 页面初始化的时候,使用 ajax 发送请求,获取后端服务的待办数据
        function init() {
    
    
            $.ajax({
    
    
                url: "/query",
                method: 'GET',
                success: function(result) {
    
    
                    initUlData(result);
                }
            });
        }
  1. 服务端返回 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));
                });
            }
        }
  1. 页面初始化的时候调用 init() 方法
$(function() {
    
    
   init();
}
  1. 完整的 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>

后端服务封装数据返回

后端服务用json数据返回给前端,json结构清晰,前端解析json比较方便。

server.js 修改

  1. 增加对象用于存储返回数据
let retData = {
    
    
	'code':'',
	'data': [],
	'msg':''
}

如何把对象变成字符串?
打开浏览器开发者工具 console 试试
在这里插入图片描述
2. 增加服务器输出json方法

function sendMsg(response, msg) {
    
    
	response.writeHead(200, {
    
    'Content-Type': 'application/json;charset=UTF-8'});
    response.write(msg);
    response.end();
}

注意:需要指定 Content-Type 为 application/json

  1. 修改 readFile 逻辑,不需要填充数据了,刷新才返回页面
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);
	});
}
  1. 增加 /query,/ 的执行逻辑方法
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;
	}
	
});

服务端修改成只有读取首页的时候才加载 HTML 页面,访问其它地址就返回 json 数据

  1. 完整的 server.js 代码
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}/`)
})

效果图

执行 node server.js 启动服务

F:\Github\Nodejs\todolist>node server.js
Server running at http://127.0.0.1:3000/

初始化页面

在这里插入图片描述

添加待办事项

  1. 添加 111
  2. 添加 en111
  3. 添加 中文111
    在这里插入图片描述
    发现有个小问题,中文乱码了,后续处理

完成待办事项

  1. 完成 111
  2. 完成 中文111
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/modelmd/article/details/127916265
今日推荐