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

news2025/8/3 4:13:14

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

  • 为啥在前端填充待办数据?
  • 如何在前端填充待办数据?
    • 需要了解的知识
    • 页面修改
  • 后端服务封装数据返回
    • server.js 修改
  • 效果图
    • 初始化页面
    • 添加待办事项
  • 完成待办事项

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

第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();
// 返回数据
let retData = {
	'code':'',
	'data': [],
	'msg':''
}

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) {
	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
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/15958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Django基础学习

目录 1、Django MVT模型 2、Django项目和应用 2.1 项目和子应用的创建 2.2 子应用url路由配置 3、Django的templates配置 4、Django请求的处理 4.1 get请求处理 4.2 post请求处理 5、Django数据库操作 5.1、数据库连接配置 5.2、models.py配置 5.3、django数据库表的…

【node进阶】深度解析Koa框架---路由|静态资源|获取请求参数

✅ 作者简介&#xff1a;一名普通本科大三的学生&#xff0c;致力于提高前端开发能力 ✨ 个人主页&#xff1a;前端小白在前进的主页 &#x1f525; 系列专栏 &#xff1a; node.js学习专栏 ⭐️ 个人社区 : 个人交流社区 &#x1f340; 学习格言: ☀️ 打不倒你的会使你更强&a…

创建自己的函数库

创建自己的函数库前言一、什么是STM32标准函数库1.定义&#xff1a;2.作用&#xff1a;3.对比&#xff1a;二、构建库函数1.修改寄存器地址封装2.定义访问的结构体指针和引脚3.创建封装函数3.1创建拉低引脚函数3.2创建引脚初始化函数总结前言 回顾一下&#xff0c;前面点亮led…

世界儿童日,周大福真诚关爱儿童成长

守护童心 呵护成长 周大福秉持着“用真诚让幸福永恒”的企业理念&#xff0c;百周年承诺“以人为本”。以爱和关怀凝聚社会力量&#xff0c;提倡社会共融&#xff0c;缔造可持续未来。 梦想家祝福 2021年周大福珠宝集团与美丽中国&#xff0c;携手打造“家源于此”项目。于2…

podman-compose 有前途吗?

文章目录1. 前言2. Docker Compose 和 Podman Compose 的历史3. 未来4. 观点5. 安装5.1 pip3 安装5.2 python 安装5.3 dnf 安装6. 示例1. 前言 虽然 Kubernetes 已经发展成为容器编排的主导者&#xff0c;但人们仍然对管理较小规模的容器&#xff08;通常是单个系统&#xff0…

centos7—安装mysql

文章目录1.1 卸载MariaDB1.2 官网下载包文件1.3 解压安装包1.4 安装相关的Mysql服务1.5 开启Mysql服务1.1 卸载MariaDB 由于centOS7中默认安装了MariaDB,需要先进行卸载 rpm -qa | grep -i mariadb #查找本地mariadb rpm -e --nodeps mariadb-libs-5.5.68-1.el7.aarch64 #这个…

nuxt 如何生成sitemap.xml 动静态站点地图

前言 sitemap.xml的作用是将我们网站的所有页面都被SEO&#xff08;浏览器搜索引擎&#xff09;收录&#xff0c;我们网站的内容更容易被用户搜到&#xff0c;同时增加我们的网站的知名度&#xff0c;排名更靠前。简言之就是用技术做网站推广&#xff0c;所以对于网站推广sitem…

JVM【类加载与GC垃圾回收机制】

JVM【类加载与GC垃圾回收机制】&#x1f34e;一.JVM&#x1f352;1.1JVM简介&#x1f352;1.2JVM执行流程&#x1f34e;二.JVM运行时数据区&#x1f352;2.1 程序计数器(线程私有)&#x1f352;2.2 栈(线程私有)&#x1f352;2.3 堆(线程共享)&#x1f352;2.4 方法区(线程共享…

Matlab图像处理基础(part 1)

目录 0. 概要 1. 图像表示 Image Representation 1.1 图像格式 Image format 1.2 图像分辨率 resolution of image 1.3 图像的编码 1.4 Matlab图像加载、显示和保存 1.5 Image Information 1.6 图像格式转换 1.7 其它类型的像素 1.8 像素数值格式 1.9 图像数据的访问…

vue实现防抖函数、节流函数,全局使用【输入框、按钮】

博主介绍 &#x1f4e2;点击下列内容可跳转对应的界面&#xff0c;查看更多精彩内容&#xff01; &#x1f34e;主页&#xff1a;水香木鱼 &#x1f34d;专栏&#xff1a;后台管理系统 文章目录 简介&#xff1a;这是一篇有关【vue实现防抖函数、节流函数&#xff0c;全局使用…

第一章《初学者问题大集合》第4节:Java程序是如何执行的

想要学好Java编程,就必须先弄清楚Java程序是如何执行的。首先来解释一个最基本的概念:什么是程序?把你想让计算机做的事情用编程语言一条条列出,这个由多条编程语言所组成的“代码序列”就是程序。 那么Java程序又是如何运行的呢?这个过程如图1-1所示。 图1-1 Java程序运…

C语言小游戏之三子棋(井字棋)(1.5w字超详细讲解)

hello&#xff0c;csdn的伙伴们&#xff0c;大家好&#xff0c;我们已经学习到了分支与循环&#xff0c;函数&#xff0c;数组这三大块知识&#xff0c;那么我们现在就可以尝试综合运用前面所学的知识&#xff0c;来完成一个简单的小游戏-----三子棋&#xff08;井字棋&#xf…

Allegro DFM Ravel Rule工具使用指导书

Allegro DFM Ravel Rule工具使用指导书 Allegro任何一个版本都支持DFM Ravel Rule检查,即便是166的版本 打开后的界面如下所示 可以检查项目 测试点,阻焊,走线,丝印,过孔,milling,装配,outline相关的DFM检查 可以让违反规则的设计处以DRC的形式报出来 避免加工问题 …

基于数字孪生打造智慧园区运营平台,助力园区数字化转型

在各行各业数字化转型的浪潮中&#xff0c;园区也在经历数字化转型发展&#xff0c;从传统园区向智慧园区不断演进。传统园区缺乏系统性规划&#xff0c;基于单点功能建设&#xff0c;存在系统孤立、管理粗放且服务不足等问题&#xff0c;难以满足人们日益增长的多样化需求。在…

第四章. Pandas进阶—数据合并

第四章. Pandas进阶 4.6 数据合并 数据合并主要使用的是Merge方法和Concat方法 1.数据合并(merge函数) 1).语法&#xff1a; pandas.merge(right,how‘inner’, on“None”, left_on“None”, right_on“None”, left_indexFalse, right_indexFalse... )参数说明: right&…

甘露糖-聚乙二醇-马来酰亚胺 mannose-PEG-MAL 马来酰亚胺-PEG-甘露糖

甘露糖-聚乙二醇-马来酰亚胺 mannose-PEG-MAL 马来酰亚胺-PEG-甘露糖&#xff0c;溶于大部分有机溶剂&#xff0c;如&#xff1a;DCM、DMF、DMSO、THF等等。在水中有很好的溶解性 中文名称&#xff1a;甘露糖-马来酰亚胺 英文名称&#xff1a;mannose-MAL 别称&#xff1a;…

【LeetCode 每日一题】53. 最大子数组和

01 题目描述 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 02 示例 示例1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5…

从 React 源码彻底搞懂 Ref 的全部 api

ref 是 React 里常用的特性&#xff0c;我们会用它来拿到 dom 的引用。 它一般是这么用的&#xff1a; 函数组件里用 useRef&#xff1a; import React, { useRef, useEffect } from "react";export default function App() {const inputRef useRef();useEffect(…

几乎涵盖了近半年90%的Java面试题,可以肝起来了

前言 很多人在问&#xff1a;八股文还有必要背吗&#xff1f; 近半年来大家听到的、用到的不少&#xff0c;带来的争议也不断。 有人奉为面试神器&#xff0c;全文背诵。有人觉得八股文铺天盖地实际作用不大&#xff0c;还害人不浅… 我觉得不是背不背八股文的问题&#xff0c…

【机器学习并行计算】2 parameter server参数服务器

使用ps实现异步梯度下降。 14年提出的。 异步 vs 同步 可以看出异步运行效率非常高。 异步梯度下降的流程 ps架构流程 worker&#xff1a; 首先从参数服务器拉取最新的参数&#xff1b;然后用自己节点上的数据计算梯度&#xff1b;最后把梯度推给参数服务器参数服务器&#xf…