整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Web 程序员为什么要遵循 HTML 优先原则?

者通过实践来阐述HTML 优先原则的主要目标是扩大能够从事 Web 软件编程工作的人员范围。

原文链接:https://html-first.com/

未经允许,禁止转载!


作者 | Tony Ennis 译者 | 弯月
责编 | 夏萌
出品 | CSDN(ID:CSDNnews)

HTML优先是一组原则,旨在通过以下方式使构建 Web 软件更容易、更快、更具包容性且更易于维护:

  1. 利用现代网络浏览器的默认功能。

  2. 利用 HTML 属性语法的极致简单性。

  3. 利用 Web 的查看源代码功能。

目标

HTML优先原则的主要目标是扩大能够从事 Web 软件编程工作的人员范围。从个人角度来看,这是件好事,因为这可以让更多的人成为Web 程序员,构建出色的 Web 软件,并提高他们的收入。从业务角度来看,这些原则也有好处,因为这可以降低构建软件的成本,并减少招聘所需的资源量(众所周知,这是一个资源密集型流程)。

HTML优先原则的第二大目标是让构建 Web 软件的工作变得更加愉快和无缝。对于大多数 Web 程序员来说,在快速构建产品期间能够流畅地在文本编辑器和浏览器之间来回切换,而不会遇到各种磕磕绊绊,也不需要切换上下文,他们会感到非常兴奋。但如今程序员需要几年的时间来掌握工具和框架才能达到这个阶段。HTML 优先原则能够让人们在学习编程的早期阶段体会这种感觉,并达到这种水平。

为了实现这些目标,首先必须承认 HTML 非常容易理解,因此我们将 HTML 作为产品的基石,不仅用 HTML 来定义内容和结构,还用它来设置样式和行为。

原则

1. 推荐使用 HTML 原生的方法。

2. 使用 HTML 属性来设置样式和行为。

3. 使用利用了 HTML属性的库。

4. 避开构建过程。

5. 推荐使用“裸” HTML。

6. 保留查看源代码的功能。

1.使用 HTML 原有的方法通过外部框架实现所需的功能

浏览器支持的开箱即用的功能范围很广,而且数量还在不断增长。在将库或框架添加到代码库之前,请检查是否可以使用原汁原味的 html/css 来实现它。

鼓励的写法:

不鼓励的写法:

2.如有可能,默认使用内联 HTML 属性定义样式和行为

我们可以使用 Tailwind 或 Tachyons等 SPC 库来实现样式。同时使用 hyperscript、Alpine 或类似的库来实现行为。这意味着很多功能都需要使用 HTML 来实现。但这也意味着其他开发人员更容易找到和理解行为、浏览并修改它们。

鼓励的写法:

不鼓励的写法:

你可能会注意到,这种方法似乎违反了关注点分离——备受吹捧的软件设计原则之一。我们认为,非黑即白的关注点分离原则是有缺陷的,因此我们提倡采用一种考虑到行为局部性以及两者之间权衡的方法。

3.如果需要库,请使用利用 html 属性的库,不推荐使用围绕 JavaScript 或自定义语法构建的库

鼓励的写法:

不鼓励的写法:

4.避开构建过程

需要将文件从一种格式转换为另一种格式的库会导致维护开销增加大量,严重影响查看源代码的功能或导致其无法使用,而且通常开发人员需要学习新工具才能使用它们。现代浏览器已不再有当初引入这些实践时的性能限制。如果我们使用 HTML 优先的库(例如 static tailwind 或 htmx),则额外所需的 CSS 和JS 量为最少。

鼓励的写法:

不鼓励的写法:

5.推荐使用“裸” HTML,不推荐编译为 HTML的各个混乱层

这条原则适用于后端实现。基本思想是可读性。熟悉 HTML 但不熟悉后端框架的开发人员查看视图文件,仍然应该能够理解 90% 以上的内容。如上所述,这意味着牺牲简洁性而换取易于理解性。

鼓励的写法:

不鼓励的写法:

6.如有可能,保留右键单击查看源代码的功能

早期网络的美妙之处在于,我们总能 "窥探 "到网页任何部分的代码。对于有抱负的开发人员来说,这是一项福利,因为这为我们在理论(阅读代码如何工作)和实践之间架起了一座桥梁,将代码和界面并排展示在我们眼前。对于许多网站来说,我们只需复制并粘贴 html 或 css,然后放到自己的网站上运行,就可以获得近乎相同的复制品。新旧代码的混合不仅是一种学习方式,而且往往也是我们创作新作品的基础。

后来,业界采用了一些 "改进 "方法,导致这种做法变得更为罕见。例如,如果我们使用流行的前端框架 React,就不能点击 "查看源代码",复制代码并重新混合,因为首先 React 有构建过程,这意味着我们在开发人员工具中看到的代码与开发人员编写的代码不同;其次,React 代码片段必须封装在 react 应用程序中才能工作。

遵循 HTML 优先原则的网站能够重新获得查看源代码的功能。事实上,HTML 优先的网站往往更进一步。因为如果使用 HTML 属性定义用户界面交互,那么在复制粘贴到新的代码库时,也可以保留这些交互(前提是目标文件包含相同的 js 库)。我们打算将来将其扩展到 HTML 优先的代码片段库。

总结

本文中描述的实践和原则在整个行业中仍然很小众,而且使用的社区也很少。我希望通过建设网站(https://html-first.com/)的方式来寻找同道合的人,共同探讨并完善这些想法。

个是我用htmlcssrScrip写出来的东西,它包括两个部分,一个是上面的转盘,一个是下面的计时器。

·点击spin旋转,它就转,stop停止,停止以后就会反馈,就是获得了什么,学习两个小时。获得这个以后就可以start timer,开始学习。

·这个是重置,重置timer,计时器。如果学完了两个小时再转一次,转完以后又是学习两个小时,再开计时器,学完又重置一遍,再转一下,学习30分钟,再去学30分钟,再开,再关。

这么一个东西要怎么做?等一下我教你们怎么做。

·首先先在桌面新建一个文本文档,给它命名成learning,learning,will,叫什么?学习的转盘,带有WIS,WIS什么timer,计时timer,计时器。

·把它的后缀改一下,改成html覆盖,保存。

·保存完了以后用vs code打开,打开完以后就是一个空白的页面。

·接下来敲代码的时间,写一个前端代码,实现刚刚那个小东西。

·首先把框架给卸了,然后是Id doctyper,html,这个好像是浏览器之类的问题的,管它HML后,这是language的缩写,它就等于English的缩写。

·下面是made,chaset,这是设置一个字符编码的UTF-8,name,这是一个4口属性。

·内容是content,content的宽度是等于设备的宽度。

·它的initial SCA,SCA就是它的初始规模,是等于1.0,就是跟网页的大小是一样的。

·接下来是一个title,就是标题,标题就是learning,learning,will学习的,转盘带有time,就是带有计时器的一个学习的转盘。

·下面是CS的内容,就是style样式,这是CSS的内容。

·接下来就是到波底,接下来就是body的内容,body,head还没结束是吧?不对,我的head去哪了?问题好大,这里有一个head,我是觉得是先写大皇家是比较好的,就是the head。

·head里面包括几个部分,就是title,标题还有style,就是CSS,body,body里面,波波底下面是h,是HGL结束了。

·body里面包含两个东西,两个div就是两个块,这块一个是用来做抽奖的转盘的,一个是用来做timer,就是计时器。

·记下来是叫script东西,就是script,screw script。

·这就是整个的框架,就是这里是CSS的地方,这里是title,它的标题就是网页上它给出的标题,就是地址栏那里的标题。

·这里是两个div,就是两个块,到时候就是用两个容器来装抽奖的转盘和计时器。

·这里是加入script的代码。

大概就讲到这里。

家好,很高兴又见面了,我是"高级前端‬进阶‬",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。

什么是 Chrono (v2)

Chrono 是 Javascript 中的自然语言日期解析器,它旨在处理大多数日期/时间格式并从任何给定文本中提取信息,内容包括:

  • 今天、明天、昨天、上周五等
  • 2013 年 8 月 17 日 - 2013 年 8 月 19 日
  • 本周五 13:00 - 16:00
  • 5 天前
  • 2 周后
  • 2013 年 8 月 17 日星期六 18:40:39 GMT+0900 (JST)
  • 2014-11-30T08:15:30-05:30

目前 Chrono 在 Github 上通过 MIT 协议开源,有超过 3.5k 的 star,值得尝试。

如何使用 Chrono (v2)

基础使用

首先需要通过 NPM 安装:

npm install --save chrono-node

然后直接在代码中引入即可:

import * as chrono from 'chrono-node';

chrono.parseDate('An appointment on Sep 12-13');

如果是 Node.js 环境,可以使用下面的代码:

const chrono = require('chrono-node');

// or `import chrono from 'chrono-node'` for ECMAScript

对于 Chrono 库来说,只需将字符串传递给函数 chrono.parseDate 或 chrono.parse 即可。

import * as chrono from 'chrono-node';

chrono.parseDate('An appointment on Sep 12-13');
// Fri Sep 12 2014 12:00:00 GMT-0500 (CDT)

chrono.parse('An appointment on Sep 12-13');
/* [{ 
    index: 18,
    text: 'Sep 12-13',
    start: ...
}] */

解析参考(日期/时区)

今天的“星期五”与上个月的“星期五”不同,引用日期的含义取决于它们被提及的时间和地点。 Chrono 允许开发者将引用定义为 Date 或 ParsingReference 对象:

// (Note: the exmaples run on JST timezone)
chrono.parseDate('Friday', new Date(2012, 8 - 1, 23));
// Fri Aug 24 2012 12:00:00 GMT+0900 (JST)

chrono.parseDate('Friday', new Date(2012, 8 - 1, 1));
// Fri Aug 03 2012 12:00:00 GMT+0900 (JST)

chrono.parseDate('Friday at 4pm', {
  // Wed Jun 09 2021 21:00:00 GMT+0900 (JST)
  // = Wed Jun 09 2021 07:00:00 GMT-0500 (CDT)
  instant: new Date(1623240000000),
  timezone: 'CDT',
});
// Sat Jun 12 2021 06:00:00 GMT+0900 (JST)
// = Fri Jun 11 2021 16:00:00 GMT-0500 (CDT)

解析配置

forwardDate(布尔值)假设结果应该在参考日期之后发生。

const referenceDate = new Date(2012, 7, 25);
// Sat Aug 25 2012 00:00:00 GMT+0900 -- The reference date was Saturday

chrono.parseDate('Friday', referenceDate);
// Fri Aug 24 2012 12:00:00 GMT+0900 (JST) -- The day before was Friday

chrono.parseDate('Friday', referenceDate, { forwardDate: true });
// Fri Aug 31 2012 12:00:00 GMT+0900 (JST) -- The following Friday

timezones 覆盖或添加时区缩写和偏移量之间的自定义映射。 当希望 Chrono 将某些文本解析为给定的时区偏移量时,请使用此选项。 Chrono 支持明确的(正常)时区映射和模糊映射,其中夏令时期间和之外的偏移量不同。

// Chrono doesn't understand XYZ, so no timezone is parsed
chrono.parse('at 10:00 XYZ', new Date(2023, 3, 20))
// "knownValues": {"hour": 10, "minute": 0}

// Make Chrono parse XYZ as offset GMT-0300 (180 minutes)
chrono.parse('at 10:00 XYZ', new Date(2023, 3, 20), { timezones: { XYZ: -180 } })
// "knownValues": {"hour": 10, "minute": 0, "timezoneOffset": -180}

// Make Chrono parse XYZ as offset GMT-0300 outside of DST, and GMT-0200 during DST. Assume DST is between 
import { getLastDayOfMonthTransition } from "timezone";
import { Weekday, Month } from "parsing";

const parseXYZAsAmbiguousTz = {
  timezoneOffsetDuringDst: -120,
  timezoneOffsetNonDst: -180,
  dstStart: (year: number) => getLastWeekdayOfMonth(year, Month.FEBRUARY, Weekday.SUNDAY, 2),
  dstEnd: (year: number) => getLastWeekdayOfMonth(year, Month.SEPTEMBER, Weekday.SUNDAY, 3)
};
// Parsing a date which falls within DST
chrono.parse('Jan 1st 2023 at 10:00 XYZ', new Date(2023, 3, 20), { timezones: { XYZ: parseXYZAsAmbiguousTz } })
// "knownValues": {"month": 1, ..., "timezoneOffset": -180}

// Parsing a non-DST date
chrono.parse('Jun 1st 2023 at 10:00 XYZ', new Date(2023, 3, 20), { timezones: { XYZ: parseXYZAsAmbiguousTz } })
// "knownValues": {"month": 6, ..., "timezoneOffset": -120}

参考资料

https://github.com/wanasit/chrono

https://dexlock.com/blog/a-dive-into-nlp-date-parsers/