manbetx手机版登陆从0到Om -第四幕

到目前为止,这个应用程序相当无聊。它只显示数据。但我们真的想用它!在这篇文章中,我们将看看应用程序对用户输入的反应(没有双关语)。源代码可以在GitHub

注意:我强烈建议阅读以前的文章首先,如果你还没有这样做的话。

管理状态很棘手。每个框架都有自己的机制来检测和处理状态更改。这是Om的。

内部状态

在本节中,我们将研究如何管理组件内部的状态。

组件状态

在前一篇文章中,我们已经了解到组件可以有内部的瞬态状态。在我们的示例中待办事项项目组件使用符号:编辑文本指定当前文本字段的值。这段片段应该会让你重新想起:

(defn todo-item [todo owner] (reify om/IInitState (init-state [_] {:edit-text (:title todo)}) om/IRenderState (render-state [_ state]…(dom/input #js {:className "edit":value (om/get-state owner:edit-text):onChange #(change % todo owner)…})))

现在,让我们来看看事件处理程序的onChange:

更改[e todo所有者](om/set-state!所有者:编辑-文本(-> e .-目标.-值))

处理程序更改:编辑文本状态输入字段的值。- >是它允许没有附加嵌套写语句的宏(即(。检查(。—target e))),但在“线程”。以上示出了片段的两个选项来更新组件的一个内部状态:

两者都将触发Om重新呈现。

应用程序状态

我们之前已经了解到,整个应用程序状态保存在单个原子中,即the根原子。但是,我们只能传递一个子集到组件(例如待办事项待办事项项目)。我们如何保持子集与根状态同步?

游标!从嗡的文档:

游标将一个大的可变原子分裂成更小的亚原子,这些亚原子与根原子的状态保持同步。

基本上,您可以将光标想象成指向根状态的一部分的指针。组件可以对其光标应用更改,应用程序状态就会更改。当应用程序中的数据状态发生变化时(例如来自HTTP请求),Om将重新呈现依赖于更改值的所有组件。因此,这种绑定是双向的。

要从游标读取值,需要解除对它的引用(例如@my-cursor) -除了在渲染阶段(即内部)渲染绘制状态),它可以像处理常规值一样处理。要更改游标值,您有两种选择:

让我们看看这在我们的应用程序中是如何工作的。

待办事项项目组件包含一个复选框字段,用于切换项的状态。它的的onChange事件处理在这里:

完成);完成);办理)待办事项:已完成#(不是%)))

办理!函数接收(1)组件的游标待办事项到todo项,(2)键:完成指定要更改数据的哪一部分,(3)一个简单地否定当前值的函数文字。

另一个例子是maintodo-app组件。它也包含一个复选框,但是这个复选框可以切换所有项目的状态:

(让[checked (-> e .-target .-checked)] (om/transact!状态:todos (fn [todos] (vec (map #(assoc %:已完成检查)))))

这里的复选框绑定到值检查。的办理!更新函数使用地图返回与待办事项顺序完成键设置为检查。不要忘记:我们是万古不易的数据,这样既工作地图ASSOC不修改数据,但返回新值。

注意:VEC我们确保返回值始终是一个向量,因为Om的游标只与关联的数据结构(如ClojureScript映射和索引顺序数据结构,如向量)一起工作。

要了解更多关于游标的信息,我建议阅读嗡的光标文件

外州

通常情况下,国家,我们希望管理不会直接可达范围内的组件。我们上面会了解到这两种机制还不够呢。

父组件

有时更改应用程序状态是不可行的,因为子组件通常只将光标指向状态的一部分。那么它的父母中就有一个应该负责任。但它们是如何与另一种动物交流的呢?

通常,在JavaScript中这是通过回调或事件冒泡来处理的。但在ClojureScript中,我们有更好的东西:类似队列的通道。的Clojure的博客描述了它完美的:

通道的一个关键特征是阻塞。在最原始的形式中,一个未缓冲的通道充当一个集合点,任何读取器将等待写入器,反之亦然。

基本上,这使我们能够轻松地同步两个或两个以上的异步操作 - 在编写顺序代码。这一切都可以追溯到托尼·霍尔的通信顺序进程(CSP)从1970年代。它最近通过在围棋编程语言

通道由图书馆提供core.async,只有宏的电力成为可能。在开始之前,我们需要在文件的开头加载库:

(ns todomvc。应用程序(:require-macros [cljs.core.async。(:require [cljs.core.])异步:参考[把!< !陈]])

todo-app组件使用的将贴装生命周期函数,用于在应用程序启动时创建新通道:

(reify om/IWillMount (will-mount [_] (let [comm (chan)]) (om/set-state!)(让[[type value]) (

(陈)返回一个新的无缓冲通道。这是加入到组件的状态的关键:COMM。最后,块打开:在里面我们发现一个无穷循环,它从通道读取一个值(<!COMM)把它分解成两个矢量,(类型的值)

的是要注意重要的是,从所述信道读取是阻塞操作,等待通过通道发送的数据永远。但不会应用,因为完全冻结的JavaScript是单线程的?好了,这就是为什么我们需要所有包裹<!电话与:它是一个宏,它允许拥有全球整体事件循环内的小,包含事件循环。而全球性的保持运行内的人阻止。

注意:COMM通道现在被传递到每个需要它的函数或组件。为了避免混淆:前一篇文章中的所有代码片段都省略了这一点。

回到我们的例子。从通道读取的数据被传递到手柄事件:

(DEFN手柄活动[式状态VAL](区分类型:破坏(破坏-待办事项状态VAL):编辑(编辑待办事项状态VAL):保存(SAVE-待办事项状态):取消(取消动作状态)无))

这个函数使用案件以选择的形式执行基于上的值类型。它处理的所有事件待办事项项目组件可能要发送。让我们来看看它的一个事件处理程序,当你点击一个待办事项红色的“X”火灾:

(DEFN破坏[TODO通讯(COMM放![:摧毁@todo]))

它使用把!发送矢量[:破坏@todo]通过该信道。注意@该解引用光标预先 - 这样的值被发送,而不是光标。然后它被无休止的循环中,我们看到上面阅读,传递给手柄事件并最终作为参数destroy-todo:

(defn destroy-todo [state {:keys [id]]])状态:todos (fn [todos] (vec (remove #(= (:id %) id) todos)))

在这里,我们看到,国家光标和待办事项的ID被用来更新应用程序的状态。该待办事项由所有待办事项的副本替代,不包括具有传入ID的任何项目。请记住,函数文本也可以写成(FN [待办事项](=(:ID待办事项)ID))

其他功能手柄事件基本上所有的工作方式都是一样的,没有什么是我们之前没见过的。

这仅仅触及了渠道的可能性的表面。要了解更多关于频道的信息,我建议阅读ClojureScript的核心。异步待办事项并尝试这种源代码示例

DOM节点

总会有一个在每一个应用程序的时候,你需要工作与实际的DOM节点,例如读取和改变其值。通过使用裁判关键字,参考名称可以分配给节点。稍后,例如在事件处理程序中,可以通过此名称访问节点。

在我们的应用程序,我们需要这个的“新”的文本字段todo-app组件。与新增的这里裁判键:

(dom/input #js {:id "new-todo":ref "newField":onKeyDown #(enter-new-todo % state owner)}…}……

随着裁判在地方,事件处理程序enter-new-todo可以访问节点:

(DEFN进入,新的待办事项[E国家所有者(当(==(-其中E)ENTER_KEY)(让[新场(OM / GET-节点拥有 “新野”)新油田文本(串/修剪)]时(而不是(串/空白的新油田文本?)(让[新待办事项(新域值。){:ID(GUID):标题新油田文字:完成假}](OM /事务处理的状态:待办事项#(连词%新的todo)))(套装(价值。新油田!) “”)))FALSE))

当用户点击回车键创建一个新的todo:使用OM / GET节点与参数老板(潜在的反应成分)和新野(参考名称)的文本字段中(天然浏览器的DOM节点)可以被检索。调用。-值在节点上读取其文本内容。如果它不是空的,将创建一个新项并保存到应用程序状态om /交易!。最后,输入的值复位。

另一个例子是对的“编辑”文本字段待办事项项目部件,现在用添加裁判键:

(DOM /输入#js {:REF “EDITFIELD”:类名 “编辑” ...} ...

在双击TODO标记编辑事件处理程序调用:

(DEFN编辑[E TODO所有者通讯(让[待办事项@todo节点(OM / GET-节点拥有 “编辑框”)(认沽通讯![编辑待办事项])(多托所有者(OM /设定状态:需求-focus真)(OM /设定状态:编辑文本(:标题待办事项)))))

还有的将了很多!的待办事项符号绑定到解除引用的游标和节点输入的DOM节点。向量[:编辑待办事项]被写入到与所述信道把!(并且由处理手柄事件功能我们前面看到的),将应用到“编辑”模式。最后,该组件的状态更新,以反映待办事项的编辑。

注意:小家伙需要老板并调用与它的每个后续形式作为第一个参数的函数。

如果你想了解更多关于裁判,我有你所需要的:更多关于参

到此结束今天的行为!我们已经看到状态如何嗡管理。我们没有考虑每一个但你看到了最重要的部分。请随意浏览完整的源代码探索剩下的部分

第5幕我们将学习如何正确地发布应用程序。与此同时,这里有一些链接,以便更深入地了解Om:

Stephan本克先生

通过贸易软件开发人员。大部分时间在不断持续追求简洁,优雅和美丽代码。或者刚刚做的东西在中间。

评论的Disqus