显然,关于
dap的第一
篇文章并没有成为我写作的成功:关于它的绝大多数评论都归结为“ niasilil”和“ niasilil,但我谴责”。 唯一具有建设性的顶级评论的奖项是
OldVitus ,它以
TodoMVC为例来说明演示dap的建议,以便进行比较。 我将在本文中做什么。
TodoMVC (如果没有人知道的话)就是这样一个标准的UI调用世界,它使您可以使用不同的框架比较相同问题(有条件的“待办事项列表”)的解决方案。 该任务非常简单(其
在dap上的解决方案 “在一个屏幕
上中断”)非常具有说明性。 因此,在她的示例中,我将尝试展示如何使用dap来实现Web前端的典型任务。
我没有搜索和研究问题的正式描述,而是决定简单地反转其中一个示例。 本文的后端对我们来说并不有趣,因此我们不会自己编写,而是使用网站
www.todobackend.com上的其中之一 ,然后从此处获取
示例客户端和标准
CSS文件 。
要使用dap,您无需下载和安装任何程序。 无需
npm install
,仅此
npm install
。 不需要创建具有特定目录结构,清单和IT成功其他属性的任何项目。 足够的文本编辑器和浏览器。 要调试XHR请求,您可能还需要一个Web服务器-一个简单的服务器,例如Chrome
扩展程序。 我们的整个前端将包含一个.html文件(当然,这是指dap引擎脚本和标准TodoMVC CSS文件)
因此,从头开始。
1.创建一个.html文件
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Todo -- dap sample</title> <link rel="stylesheet" href="https://www.todobackend.com/client/css/vendor/todomvc-common.css"/> <script src="https://dap.js.org/0.4.js"></script> </head> <body> <script> </script> </body> </html>
通常的html准备工作,其中包括网站
www.todobackend.com友好提供的CSS文件和
dap.js.org网站友好提供的dap引擎。
2.复制原始示例的DOM结构
要使用标准CSS文件而不进行更改,我们将坚持与
原始示例相同的DOM结构。 在Chrome浏览器中将其打开,按Ctr + Shift + I,选择“元素”标签,然后查看应用程序本身是否位于元素
section id="todo-app">

通过逐个打开此子树,我们将其结构重写为.html文件。 现在,我们只是以一种快速的方式进行草图绘制,而不是编写代码,因此我们仅在“单引号”及其子代括号中写下元素的签名。 如果没有孩子,我们画空括号。 我们监控指数和方括号的余额。
注意:重复元素(例如,这里是
LI
元素),即使原始元素中有多个元素,我们也会对其写入一次。 显然,这些是来自同一模式的数组。
我认为,用手写HTML和CSS的任何人都可以理解签名格式,因此,现在我不再详细介绍它。 我只能说标签是用大写字母写的,没有标签就等于有DIV标签。 #元素(带有id)的丰富之处是由于所包含的CSS文件的细节所致,它主要使用id选择器。
3.请记住,dap程序是Javascript
为了避免代码中不必要的括号,dap引擎将几种方法直接注入
String.prototype
(我知道在标准对象中实现您的方法是ayahay,但简而言之,我们已经通过了),它将签名字符串转换为dap模板。 一种这样的方法是
.d(rule, ...children)
。 它采用的第一个参数是生成规则(
d-rule ),其余参数是任意数量的子代。
基于此新知识,我们添加代码,以便代替每个左括号,而使用序列
.d(""
,并且在每个左引号之前,除了第一个引号之外,还带有逗号。生活技巧:您可以使用自动替换。
'#todoapp'.d("" ,'#header'.d("" ,'H1'.d("") ,'INPUT#new-todo placeholder="What needs to be done?" autofocus'.d("") ) ,'#main'.d("" ,'#toggle-all type=checkbox'.d("") ,'UL#todo-list'.d("" ,'LI'.d("" ,'INPUT.toggle type=checkbox'.d("") ,'LABEL'.d("") ,'BUTTON.destroy'.d("") ) ) ) ,'#footer'.d("" ,'#todo-count'.d("") ,'UL#filters'.d("" ,'LI'.d("") ) ,'#clear-completed'.d("") ) )
瞧! 我们得到了对
.d
方法的调用树,可以将其转换为dap模板。 空字符串
""
是将来d规则的种子,而子元素是用逗号分隔的参数。 正式地,这是一个有效的dap程序,尽管还不能完全满足我们的需求。 但是它已经可以启动了! 为此,请在右方括号后添加
.RENDER()
方法。 顾名思义,此方法将呈现结果模板。
因此,在此阶段,我们有一个包含以下内容的.html文件:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Todo -- dap sample</title> <link rel="stylesheet" href="https://www.todobackend.com/client/css/vendor/todomvc-common.css"/> <script src="https://dap.js.org/0.4.js"></script> </head> <body> <script> '#todoapp'.d("" ,'#header'.d("" ,'H1'.d("") ,'INPUT#new-todo placeholder="What needs to be done?" autofocus'.d("") ) ,'#main'.d("" ,'#toggle-all type=checkbox'.d("") ,'UL#todo-list'.d("" ,'LI'.d("" ,'INPUT.toggle type=checkbox'.d("") ,'LABEL'.d("") ,'BUTTON.destroy'.d("") ) ) ) ,'#footer'.d("" ,'#todo-count'.d("") ,'UL#filters'.d("" ,'LI'.d("") ) ,'#clear-completed'.d("") ) ) .RENDER() // dap </script> </body> </html>
您可以
在浏览器中将其打开,以确保生成DOM元素,应用CSS样式,仅将其填充为该模板即可。
4.获取数据
我们转到
原始页面 ,在工具中打开“网络”选项卡,打开XHR过滤器,然后查看数据的来源和格式。


好吧好吧 待办事项列表直接取自
todo-backend-express.herokuapp.com作为对象的json数组。 太好了
为了接收数据,dap有一个内置的converter
:query
,可将URL异步“转换”为从URL接收的数据。 URL本身,我们不会直接在规则中编写,而用常量
todos
表示; 那么整个数据挖掘设计将如下所示:
todos:query
并在字典中将
todos
常量本身写入-在
.RENDER()
之前的
.DICT
部分:
'#todoapp'.d("" ... ) .DICT({ todos : "https://todo-backend-express.herokuapp.com/" }) .RENDER()
收到
todos
数组后,我们从中构建一个待办事项列表:对于每种情况,我们从
.title
字段中获取名称,并将其写入
LABEL
元素,从
.completed
字段中
.completed
获取“ completeness”的符号,并写入至
checked
元素
INPUT.toggle
的
checked
属性。 这样做是这样的:
,'UL#todo-list'.d("*@ todos:query"
我们在浏览器中更新此页面,如果您从文件系统启动它,则什么也不会发生。 问题是现代浏览器不允许本地文档中的跨域XHR请求。

现在该使用任何本地Web服务器通过http观看我们的页面了。 好吧,或者如果您还没有准备好用自己的双手编写dap,请使用我的链接查看页面的顺序版本(别忘了查看源代码-在Chrome中,这是使用Ctrl + U完成的)
因此,我们
转到位于http://的页面,看到数据即将到来,列表正在构建中。 太好了! 您已经掌握了
*
和运算符
!
,converter
:query
,常量和访问当前数组元素的字段。 再次查看结果代码。 您仍然觉得它不可读吗?
5.添加状态
也许您已经尝试单击待办事项列表中的复选标记。 复选框本身会更改颜色,但是与原始复选框不同,
LI
父元素不会更改其样式(“已完成的工作”应变为灰色并划掉,但这不会发生)-事物不会更改其
状态 。 但是这些元素还没有任何状态,因此无法更改它。 现在我们将修复它。
向
LI
元素添加“完成”状态。 为此,请在其d规则中定义
$completed
状态变量 。 对于可以更改此状态的
INPUT.toggle
,我们将分配一个适当的反应规则(
ui-rule ),该
规则将根据其自己的
checked
标志(“ daw已打开”)来设置
$completed
变量。 根据
$completed
状态
$completed
LI
元素将启用或禁用CSS类“已完成”。
,'UL#todo-list'.d("*@ todos:query" ,'LI'.d("$completed=.completed"
CSS类的这种操作是很常见的事情,因此在dap中有一个特殊的运算符可用于它们!
请注意,我们在
a规则中执行此操作(从单词累计)。 为什么不在D规则中? 这两种规则之间的区别在于,更新时,d规则会完全重建元素的内容,并再次删除旧的和新的内容,而a规则不会触及元素的现有内容,而是将结果``附加''到现有内容中。 更改
LI
元素的单个属性不需要重组其其余内容,因此在a规则中执行此操作更为合理。
我们看一下
结果 。 效果已经更好:点击复选框更改相应待办事项的状态,并根据此状态更改元素的视觉样式。 但是仍然存在一个问题:如果最初存在已完成任务的列表,则它们不会是灰色的,因为默认情况下,在生成元素时不执行a规则。 为了即使在生成过程中也要执行它,我们将运算符
a!
添加到元素
LI
的d规则中
,'LI'.d("$completed=.completed; a!"
我们看 。 好吧 以
$completed
的状态
$completed
。 在初次启动时和随后的手动切换过程中,已完成的案例均会正确设置样式。
6.编辑案例名称
回到
原来 。 通过双击案例名称,将激活编辑模式,在该模式下可以更改此名称。 在此以完全隐藏“视图”视图模式模板(带有DAW,标题和删除按钮)的方式实现,并显示
INPUT class="edit"
元素。 我们将做一些不同的操作-我们将只隐藏
LABEL
元素,因为其他两个元素不会干扰我们的编辑。 只需将
view
类添加到
LABEL
元素。
对于“编辑”状态,在
LI
元素中定义
$editing
变量。 最初,它(状态)被重置,通过
dblclick
在
LABEL
元素上打开,并在
INPUT.edit
元素失去焦点时关闭。 所以我们写:
,'LI'.d("$completed=.completed $editing=; a!"
现在我们
可以编辑案例的名称。
7.将数据发送到服务器
好的,我们已经可以在浏览器中进行编辑了,但是这些更改也必须转移到服务器上。 我们看一下原始代码是怎么做的:

更改将使用具有特定URL的PATCH方法(以
http://todo-backend-express.herokuapp.com/28185
的形式)发送到服务器,这显然在每种情况下都是唯一的。 服务器在列表中的每种情况的
.url
字段中指示此URL。 也就是说,我们更新服务器上大小写所需要做的就是将PATCH请求发送到
.url
字段中指定的地址,更改后的数据以JSON格式发送:
,'INPUT.edit' .d("? $editing; !! .title@value") .ui(".title=#.value; (@method`PATCH .url (@Content-type`application/json)@headers (.title):json.encode@body):query") .e("blur","$editing=")
在这里,我们使用相同的converter
:query
,但是版本更详细。 如果将
:query
应用于简单字符串,则将该字符串视为URL,并执行GET请求。 如果
:query
收到一个复杂对象,在这种情况下,它将把它当作对请求的详细描述,包含字段
.method
,
.url
,
.headers
和
.body
,并根据它们执行请求。 在这里,在更新
.title
立即向服务器发送带有此更新的
.title
的PATCH请求。
但是有细微差别。 我们从服务器获取
.url
字段,它看起来像这样:
http://todo-backend-express.herokuapp.com/28185
:
http://todo-backend-express.herokuapp.com/28185
,也就是说,如果我们的客户端也通过http://打开,则http://协议是硬编码的那一切都很好 但是,如果客户端通过https://打开,则会出现问题:出于安全原因,浏览器会阻止来自https来源的http-traffic。
解决方法很简单:如果您从
.url
删除协议,则请求将通过页面协议。 因此,让我们开始吧:编写适当的转换器
dehttp
,然后将
.url
通过它。
.FUNC
部分中
.FUNC
了自定义转换器(和其他功能):
.ui(".title=#.value; (@method`PATCH .url:dehttp (@Content-type`application/json)@headers (.title):json.encode@body):query") ... .FUNC({ convert:{
将标头对象放在字典中也可以在其他查询中使用:
.ui(".title=#.value; (@method`PATCH .url:dehttp headers (.title):json.encode@body):query") ... .DICT({ todos : "//todo-backend-express.herokuapp.com/", headers: {"Content-type":"application/json"} })
好吧,对于完全风水,我们将使用转换器的另一个有用属性
:query
query-根据
Content-type:application/json
标头在json中自动编码请求主体。 结果,规则将如下所示:
.ui(".title=#.value; (@method`PATCH .url:dehttp headers (.title)):query")
所以,
看 。 好的,案例名称现在不仅在浏览器中更改,而且在服务器上也更改。 但是! 不仅案件的名称可以更改,而且完成状态也可以更改。 因此,它也需要发送到服务器。
您可以将相同的PATCH请求添加到
INPUT.toggle
元素,只需发送
(.completed)
而不是
(.completed)
:
,'INPUT.toggle type=checkbox' .d("#.checked=.completed") .ui("$completed=#.checked; (@method`PATCH .url:dehttp headers (.completed:?)):query")
您可以将此PATCH请求放在“括号之外”:
,'LI'.d("$completed=.completed $editing= $patch=; a!"
就是这个 反应规则属于“上规则”组,从“下至上”执行-从后代到父级,再到根本身(必要时可以中断此顺序)。 这有点像DOM中的弹出事件。 因此,可以将几个后代共有的一些反应片段分配给一个共同的祖先。
具体来说,在我们的案例中,从这种委托中获得的收益并不是特别明显,但是,如果存在更多可编辑的字段,那么将这一庞大的请求(当然是基于dap标准)放在一条通用规则中,将大大有助于保持代码的简单性和可读性。 所以我推荐它。
我们来看 :现在,名称更改和状态更改都发送到了服务器。
在下一篇文章中,如果您有兴趣,请考虑添加,删除和过滤案例。 同时,您可以在
dap.js.org/docs上查看
最终结果和dap代码的其他示例。