当前位置: 首页 > news >正文

用 Delphi 做了一个简单的 CMS

Delphi 代码上面花的时间最少。

前提是你要熟悉 Delphi 的 WebBroker 框架。不熟悉也没关系,5分钟就可以入门,10分钟就熟悉了。

CMS 就是个基于 WEB 的内容管理嘛。相当于一个简单的没有跟贴功能的 BBS。这样的东西,后边是数据库,存储帖子。前边是表现层,也就是 WEB 前端。对于数据库来说,Delphi 的数据库操作那是简单得不能再简单了。

花费时间最多的还是和前端有关的事情。相关的技术细节,我在本博客之前的文章里面都有提到。这里总结一下。

花费时间最多的前端

当然,前端花费时间多,也有一部分原因是前端我不熟悉。

这里记录一下时间都用到哪里去了。

1. 找了一个简单的 CSS 用来美化页面。熟悉这个 CSS 框架的使用,看它的例子和文档。这个 CSS 功能不是很强大,但确实不错。好处就是它体积小,加载不会花很多网络流量和时间;

2. 找了10来个富文本编辑器,评估一下哪个好用,哪个更简单,哪个的体积更小。单单是评估10多个编辑器,就花掉2天时间。最后选择了 Quill 这个编辑器。

3. 学会使用 Quill 编辑器花了很多时间。如果只是简单地在页面里面使用它,大概几分钟或者十分钟就能用起来。但是,当发现它会被页面上的 Pico.CSS 影响,要解决这个问题,花了我三天时间。上网查资料,各种搜索,评估各种方案,比如我就在采用 iframe 还是采用 Shadow DOM 这两种方案上,花了很多时间测试,看看哪个更好用。最后发现 Shadow DOM 方式对于 Quill 来说是不能用的。

4. 因为想用 Delphi 12.2 最新版的 WebStencils 控件,又要花时间去学习如何使用它。当然也遇到过一些不知道如何解决的问题,花费很多时间摸索和测试。

5. 开发完成后,想采用 IIS CGI 的方式,放到 IIS 下面去使用。然后又想让链接地址简单一些,不要暴露后台程序是 MyCMS.exe 这样的东西,又上网查资料,发现 IIS 可以采用【URL 重写】的方式来实现。然后去搜索资料学习这个 URL 重写该怎么做,又花费了一天。

6. 页面里面使用了 HTMX 来做一些 AJAX 的动作。HTMX 大概是从完全不懂到能够使用,入门最快的前端技术。看着官方页面上的文档和例子,几分钟,就能把它用起来。

总结一下心得

本来做这个玩意,就是想评估一下 Delphi 最新推出的 WebStencils 控件,实际做点东西才能知道它好不好用。东西并不复杂,页面也没有几个。顺便也评估一下 HTMX 是否好用。

选择各种框架,工具,最重要的一点是,要能够达到代码封装,代码重用。不要在很多地方复制粘贴相同的代码。

关于 WebSencils

Delphi 的 WebBroker 框架下,原来就有的 PageProducer 控件,能够让我们把很多个页面里面相同的部分提取出来作为一个单独的文件,也就是组件化了。最后在需要的时候,把需要的页面的各个部分组装到一起。因为页面其实就是字符串文件,所以 PageProducer 提供的功能就是让我们能够在程序里面通过字符串替换掉标记的方式,组装页面。可能需要写一些 Delphi 的代码。

新推出的 WebStencils 则是通过在页面里面嵌入一些标记后,由 WebStencils 自己的代码自动去替换。这样一来,就少写了很多代码。需要修改时,也仅仅改页面代码,Delphi 程序很多时候不需要修改,因此也就不需要重新编译。这样做,非常方便把页面代码组件化。页面代码里面,有很多重复的东西,比如页头,页脚,都不用每个页面都写了。也不用写把这些页面组件组装到一起的代码。确实省了很多代码和开发时间。

更进一步,WebStencils 支持页面上的字符串标记,可以在运行时被 Delphi 程序的对象的值替换,这就给我们带来了更多的便利。我们无需写代码来实现页面上内容被运行期的数据变化了。比如,如果采用 PageProducer 或者我们自己写和页面有关的代码,都需要对页面文件的字符串进行处理。比如我们有个页面是以下代码:

<div>
<label>价格 </label>
<#MyPrice>
</div>

Delphi 程序大概要这样写:

var SL: TStringList;SL := TStringList.LoadFromFile('MyPage.html');var S := SL.Text;S := S.ReplaceText('<#MyPrice>', MyDataSet.FieldByName('Price').ToString);Response.Content := S;

也就是加载页面文件,把里面的标记找出来,替换为数据库里面的价格字段的值。

如果用了 WebStencils,则上面的 Delphi 代码一行都不用写。只要页面里有对应价格字段的相关标记, WebStencils 加载页面后就会自动找到对应的 DataSet 对象,把价格字段的值替换掉标记。

关于 HTMX

HTMX 更有意思。使用它,可以把页面拆成很多零碎的小组件,然后通过 AJAX 的方式逐个组装页面。而 WEB 程序的不同的路径,就变成了输出不同页面组件的一个 API 接口。更妙的是,这个完全是后端实现,完全不需要在前面用很复杂的前端 JavaScript 框架。

这个就涉及到开发的哲学和方法论的问题了。

简单说,最初的 WEB 开发,就是在后端服务器代码里面,把 HTML 字符串组装好,发送给浏览器呈现。浏览器仅仅是解释 HTML 然后呈现这个页面。

经过了很多年以后,现在比较流行的几个大的前端框架,是用 JavaScript 在前端浏览器里面运行,用运行的代码画出页面。而后端 WEB 服务器只需要输出页面上变化的部分需要的数据就行了。数据则是用 JSON 格式来封装。

这是两种完全不同的极端情况。

HTMX 则是提倡后端输出的不是 JSON 数据,而应该是 HTML 格式的页面元素。HTMX 作为前端的 JavaScript 库,只是把 JavaScript 对于后端的调用(AJAX)和调用后收到的来自后端的 HTML 字符串在页面里面如何呈现,做了封装。使用 HTMX 不需要写代码,只需要写【描述】,或者说写一些属性定义,就能完成工作。

我使用 HTMX 下来的感受是,完全不懂 JavaScript 和类似 jQuery 之类的 JavaScript 代码库,也能做出动态的页面来。我这里说动态页面,是指页面 AJAX 方式局部更新。

从代码架构上来说,使用 HTMX 就可以让后端 WEB SERVER 程序,尤其是 Delphi WebBroker 程序,变成一个有很多特定功能的 WEB 接口。就好比常见的代码里面的各种函数调用。这样做的好处是代码逻辑更清晰,模块化更好。

比较 Delphi WebStencils 和 HTMX

这两个都可以让页面变成组件,把相同的页面代码抽离出来,而不是重复的复制粘贴到很多页面文件里面。

使用 WebStencils 是在服务器上的代码组装页面。一次性组装完成后,发送给浏览器。

HTMX 则是在浏览器页面加载完成后,还可以继续向后端服务器请求某个页面元素,将获得的页面组件显示到 HTMX 代码指定的位置。也就是当页面上有局部的更新时,不需要刷新整个页面,服务器只需要输出对应的页面的局部的代码,可能就是几个 DIV 相关的字符串,数据量很小,因此服务器压力也会很小,占用的流量带宽也很小。

因此,要正确评估某个页面的当前需求,来决定采用哪个方案。

更复杂的页面

对 Delphi 的开发者来说,后端用 Delphi 代码开发完全没问题。可能不熟悉 CSS / JAVASCRIPT 等等前端技术。要开发一个功能强大的前端网页,可能会觉得很难。

1. 页面美化:直接套一个现成的 CSS;比如我这次套了个 PICO.CSS 页面立马变漂亮,不用自己去考虑页面排版之类的事情。当然,要是套个 BootStrap 之类的大框架也不错。

2. 复杂的页面组件,比如动态编辑的表格,或者图表(Chart),那就去找一个开源的组件,直接用起来。甚至还可以用 Delphi 代码把它封装为一个 Delphi 的组件(对象),写 WEB 程序的时候就完全不用考虑它的细节,只需要调用 Delphi 的对象的方法/属性,就可以实现页面上的复杂内容。

3. 页面呈现期间的动态局部内容更新,采用 HTMX,则不需要写 JAVASCRIPT 代码就能实现。

相关文章:

用 Delphi 做了一个简单的 CMS

Delphi 代码上面花的时间最少。 前提是你要熟悉 Delphi 的 WebBroker 框架。不熟悉也没关系&#xff0c;5分钟就可以入门&#xff0c;10分钟就熟悉了。 CMS 就是个基于 WEB 的内容管理嘛。相当于一个简单的没有跟贴功能的 BBS。这样的东西&#xff0c;后边是数据库&#xff0…...

ASK, PSK, FSK, DPSK

ASK, PSK, FSK, DPSK详解&#xff1a; 这四种调制方式都是数字调制技术&#xff0c;用于将数字信号转换成适合在信道上传输的模拟信号。它们的主要区别在于如何用模拟信号的变化来表示数字信息。 1. ASK (Amplitude Shift Keying) 幅移键控: 原理: ASK 通过改变载波信号的幅…...

【Linux】认识Linux内核中进程级别的文件结构体【files_struct】&文件IO模型初步演示

前言 大家好吖&#xff0c;欢迎来到 YY 滴 系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《Linux》…...

[Offsec Lab] ICMP Monitorr-RCE+hping3权限提升

信息收集 IP AddressOpening Ports192.168.52.218TCP:22,80 $ nmap -p- 192.168.52.218 --min-rate 1000 -sC -sV -Pn PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.9p1 Debian 10deb10u2 (protocol 2.0) | ssh-hostkey: | 2048 de:b5:23:89:bb:9f:d4:1…...

Studying-多线程学习Part4 - 异步并发——async future、packaged_task、promise

异步并发——async future packaged_task promise 1.async、future 是C11引入的一个函数模版&#xff0c;用于异步执行一个函数&#xff0c;并返回一个future对象&#xff0c;表示异步操作的结果。使用 async 可以方便地进行异步编程&#xff0c;避免了手动创建线程和管理线程…...

【Java基础】用Scanner类获取控制台输入

目录 Scanner类是什么导入并创建读取一个数读取字符串读取一行读取直到空白字符为止读取多个数直到^z读取一个字符 Scanner类是什么 在Java中&#xff0c;Scanner 是一个非常有用的类&#xff0c;用于从各种输入源&#xff08;如键盘、文件或其他输入流&#xff09;读取数据。…...

微服务seata解析部署使用全流程

官网地址&#xff1a; Seata 是什么&#xff1f; | Apache Seata 1、Seata术语 用来管理分布式事务&#xff0c;由阿里巴巴出品。 【1、TC (Transaction Coordinator) - 事务协调者】 用来维护事务的&#xff0c;包括主事务和分支事务。 【2、TM (Transaction Manager) - …...

Linux性能调优技巧

目录 前言1. CPU性能优化1.1 调整CPU调度策略1.2 合理分配多核处理 2. 内存性能优化2.1 调整内存分配策略2.2 缓存和分页优化 3. 磁盘I/O性能优化3.1 使用合适的I/O调度器3.2 磁盘分区和文件系统优化 4. 网络性能优化4.1 优化网络参数4.2 调整网络拥塞控制算法 5. 系统监控与优…...

python 实现sha1算法

sha1算法介绍 SHA-1&#xff08;Secure Hash Algorithm 1&#xff0c;安全散列算法1&#xff09;是一种密码散列函数&#xff0c;由美国国家安全局&#xff08;NSA&#xff09;设计&#xff0c;并由美国国家标准技术研究所&#xff08;NIST&#xff09;发布为联邦数据处理标准…...

ejb-ref元素

ejb-ref 是用于在 Java EE (现在称为 Jakarta EE) 中引用 Enterprise JavaBeans (EJB) 的一个元素&#xff0c;主要用于定义和配置 SLEE (Service Logic Execution Environment) 组件中的 EJB 依赖关系。通过这个引用&#xff0c;SBB (Service Building Block) 可以轻松地访问和…...

Perl 子程序(函数)

Perl 子程序&#xff08;函数&#xff09; Perl 是一种高级、解释型、动态编程语言&#xff0c;广泛用于CGI脚本、系统管理、网络编程、 finance, bioinformatics, 以及其他领域。在Perl中&#xff0c;子程序&#xff08;也称为函数&#xff09;是组织代码和重用代码块的重要方…...

ElasticSearch 备考 -- Snapshot Restore

一、题目 备份集群下的索引 task&#xff0c;存储快照名称为 snapshot_1 二、思考 这个涉及的是集群的备份&#xff0c;主要是通过创建快照&#xff0c;涉及到以下2步骤 Setp1&#xff1a;注册一个备份 snapshot repository Setp2&#xff1a;创建 snapshot 可以通过两种方…...

【Linux】进程替换、命令行参数及环境变量(超详解)

目录 进程替换 替换函数的含义 命令行参数 环境变量 PATH 进程替换 我们先看代码&#xff1a; 1 #include<stdio.h>2 #include<unistd.h>3 int main()4 {5 printf("process...begin!\n");6 7 execl("/usr/bin/ls","ls"…...

MySQL事务日志—redo日志介绍

MySQL事务日志—redo日志 事务有4种特性&#xff1a; 原子性、一致性、隔离性和持久性。 那么事务的四种特性到底是基于什么机制实现? 事务的原子性、一致性由事务的 undo 日志事务的隔离性由锁机制和MVCC实现。事务的持久性由redo 日志来保证。 两类日志概述&#xff1a;…...

告别音乐小白!字节跳动AI音乐创作工具,让你一键变作曲家!

还在羡慕别人能创作动听的音乐&#xff1f;五音不全的你&#xff0c;也梦想着谱写属于自己的乐章&#xff1f;现在&#xff0c;机会来了&#xff01;字节跳动推出了一款AI音乐创作工具——抖音推出的海绵音乐&#xff0c;它能让你轻松一键创作音乐&#xff0c;即使是“音乐小白…...

空心正方形图案

KiKi学习了循环&#xff0c;BoBo老师给他出了一系列打印图案的练习&#xff0c;该任务是打印用“*”组成的“空心”正方形图案。 输入描述&#xff1a; 多组输入&#xff0c;一个整数(3~20)&#xff0c;表示输出的行数&#xff0c;也表示组成正方形边的“ * ”的数量。 输出描述…...

【EXCEL数据处理】000020 案例 保姆级教程,附多个操作案例。EXCEL使用表格。

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【EXCEL数据处理】000020 案例 保姆级教程&#xff0c;附多个操作案例。…...

虾皮Shopee大数据面试题及参考答案

Cube 表性能优化,还有其他优化的方法吗? Cube 表性能优化可以从多个方面入手。 一方面,可以优化数据存储格式。选择合适的存储格式能够减少存储空间占用,提高数据读取速度。例如,Parquet 格式是一种高效的列式存储格式,它可以按列进行数据压缩,大大减少磁盘 I/O 和内存占…...

重学SpringBoot3-集成Redis(六)之消息队列

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成Redis&#xff08;六&#xff09;之消息队列 1. 什么是发布/订阅&#xff08;Pub/Sub&#xff09;&#xff1f;2. 场景应用3. Spring Boot 3 整合 R…...

LeetCode 134 Gas Station 解题思路和python代码

题目&#xff1a; There are n gas stations along a circular route, where the amount of gas at the ith station is gas[i]. You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from the ith station to its next (i 1)th station. You …...

服务攻防

171、一次完整的 HTTP 请求过程 域名解析 --> 发起 TCP 的 3 次握手 --> 建立 TCP 连接后发起 http 请求 --> 服务器 响应 http 请求&#xff0c;浏览器得到 html 代码 --> 浏览器解析 html 代码&#xff0c;并请求 html 代码中的资源&#xff08;如 js、 css…...

leetcode 力扣算法题 快慢指针 双指针 19.删除链表的倒数第n个结点

删除链表的倒数第N个结点 题目要求题目示例解题思路从题目中的已知出发思考寻找目标结点条件转换核心思路 需要注意的点改进建议 完整代码提交结果 题目要求 给你一个链表&#xff0c;删除链表的倒数第n个结点&#xff0c;并且返回链表的头结点。 题目示例 示例 1&#xff1…...

网络五层模型:物理层、数据链路层、网络层、传输层、应用层,分别解决了什么问题?

网络五层模型&#xff08;也称为TCP/IP模型的简化版本&#xff09;将网络通信过程分为五个层次&#xff0c;每一层都解决了特定的问题。以下是每一层的详细解释及其解决的问题&#xff1a; 1. 物理层&#xff08;Physical Layer&#xff09; 解决的问题&#xff1a;数据的物理…...

OpenCV视频I/O(18)视频写入类VideoWriter之初始化 VideoWriter 对象的函数open()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 初始化或重新初始化视频编写器。 该方法打开视频编写器。参数与构造函数 VideoWriter::VideoWriter 中的相同。 cv::VideoWriter::open() 函数用…...

大数据处理从零开始————4.认识HDFS分布式文件系统

1.分布式文件系统HDFS 1.1 认识HDFS 当单台服务器的存储容量和计算性能已经无法处理大文件时&#xff0c;分布式文件系统应运而生。什么是分布式系统&#xff0c;分布式系统是由多个独立的计算机或节点组成的系统&#xff0c;这些计算机通过网络连接&#xff…...

jwt认证课件讲解

JWT 基本概念 在用户登录后&#xff0c;我们需要在不同请求之间记录用户的登录状态&#xff0c;常用方式一般有三种&#xff1a;Cookie&#xff0c;Session和Token。 这里我们使用第三种Token令牌方式来实现认证鉴权&#xff0c;采用Json Web Token认证机制&#xff08;简称…...

【判断推理】逻辑基础

1.1 命题 用语言、符号或者式子表达的&#xff0c;可以判断真假的陈述句称为命题&#xff0c;一般写为 若p&#xff0c;则q 真命题&#xff1a;判断为真的语句假命题&#xff1a;判断为假的语句 eg1&#xff1a;小张是中国人&#xff08;若是小张&#xff0c;则是中国人&#…...

AcWing 655:天数转换 ← 整除、求余

【题目来源】https://www.acwing.com/problem/content/657/【题目描述】 读取对应于一个人的年龄&#xff08;以天为单位&#xff09;的整数值&#xff0c;并转化为年&#xff0c;月和日表示方式输出&#xff0c;年、月、日分别对应 ano(s), mes(es), dia(s)。 注意&#xff1a…...

【解决办法】git clone报错unable to access ‘xxx‘: SSL certificate problem:

使用git clone 时报错unable to access xxx: SSL certificate problem: 这个报错通常是由于SSL证书问题引起的。通常可以按照以下步骤进行排查&#xff1a; 检查网络连接&#xff1a;确保你的网络连接正常&#xff0c;可以访问互联网。尝试使用其他网站或工具测试网络连接是否正…...

算法笔记(十三)——BFS 解决最短路问题

文章目录 迷宫中离入口最近的出口最小基因变化单词接龙为高尔夫比赛砍树 BFS 解决最短路问题 BFS(广度优先搜索) 是解决最短路径问题的一种常见算法。在这种情况下&#xff0c;我们通常使用BFS来查找从一个起始点到目标点的最短路径。 迷宫中离入口最近的出口 题目&#xff1a;…...