【Clojure】re-frame for SPA

栏目: 编程语言 · Clojure · 发布时间: 5年前

内容简介:事件来源:用户输入、用户点击、定时器、远程调用响应等。事件作为一个数据被投入到类似于事件总线的队列,其数据结构为:

re-frame介绍

re-frame 是一个帮助我们快速开发WEB单页面应用的框架,是一个基于数据驱动的框架。其主要流程是如下的一个永无止境大循环:

【Clojure】re-frame for SPA

dispatch——事件分发

事件来源:用户输入、用户点击、定时器、远程调用响应等。事件作为一个数据被投入到类似于事件总线的队列,其数据结构为:

[event-id event-arg1 event-arg2 ...]

re-frame事件分发函数:

(re-frame.core/dispatch [event-id event-arg1 event-arg2])

event-handler——事件处理

对于分发过来的事件,re-frame会根据事件ID(`event-id)找到注册的事件处理函数,进行处理。event-handler是整个应用的业务核心,re-frame使得事件处理过程变成了一个纯函数(稳定、可测试)。

(defn remove-item
  "删除元素事件处理"
  [coeffects event]               ;; `coeffects` holds the current state of the world.  
     (let [item-id (second event)         ;; extract id from event vector
           db      (:db coeffects)]       ;; extract the current application state
       {:db  (dissoc-in db [:items item-id])
        :request {:request-id :some-thing}}))))

;; 注册事件处理
(re-frame.core/reg-event-fx   ;; a part of the re-frame API
  :remove-item                   ;; event id
  remove-item)

事件处理函数的输入参数: [coeffects event]

  • coeffects:包含了事件处理函数执行时当前"世界"的全部状态,包括 db(应用的本地状态) 以及其他事件处理上下文数据,如当前时间,随机数等...

    {:db app-state ;; 当前app的状态,re-frame默认设置的
     :now 事件执行时的时刻 ;; 需要自定义注册
     :random-num 随机数  ;; 需要自定义注册
     ...
     }
  • event:事件,参见上述 事件数据结构

事件处理函数拿都输入参数中的数据,通过计算之后,输出effects,如:

{:db new-db ;; 更新应用状态的效果
 :request request-data ;; 远程调用的效果
 :cookie cookie-data ;; 更新cookie的效果
 :timer timer-data ;; 启动或关闭定时器的效果
 ...}

即用一个数据结构来描述事件处理之后要做的一些"副作用"操作,而不是直接在事件处理函数中调用这些副作用操作,如修改数据库,执行远程调用,修改cookie的值,这样会使得事件处理函数变成非纯函数。

PS:上述结构中,key为effect的ID,标志一类effect。

effects handler——效果处理

re-frame会根据effect id 找到事先注册好的效果处理函数,对效果进行处理。如对于 :db 这个默认的效果,re-frame会用新的db替换旧的db(这是re-frame的默认处理)。对于那些自定义效果,则需要注册自定义处理函数,以远程调用效果request为例:

(defn request-effect-handler
  "远程调用效果处理函数"
  [{:keys [event params resp-event] :as request-data}]
    (case event
      :query-user-balance
      ;; 模拟远程调用
      (js/setTimeout #(re-frame/dispatch [resp-event 20000]) 5000)))

;; 注册效果处理函数
(re-frame/reg-fx
  :request         ;; effect id
  request-effect-handler)

效果处理完之后,应用的状态被更新改变。

query——查询应用状态中用于显示的相关数据

应用状态被更新之后,负责显示的视图层会从新的状态中,查找出它展示所需要的数据:

(defn query-fn
    "定义从应用状态db中查询出所需数据函数"
  [db]         ;; db is current app state
  (:items db))   ;; not much of a materialised view

;; 注册查询函数
(re-frame/reg-sub
  :query-items ;; 查询ID :query-id
  query-fn)

;; 因为clojure中关键字也可以作为函数,所以上面的代码等价于:
(re-frame/reg-sub :query-items :items)

view——生成新的视图

视图层根据query-id订阅所需要的数据,然后根据数据生成新的视图:

(defn items-view
  "定义视图生成函数"
  []
  (let [items  (re-frame/subscribe [:query-items])]  ;; source items from app state
    [:div (map item-render @items)]))   ;; assume item-render already written

subscribe 函数向应用状态中订阅query-id(:query-items)指定的数据,每当应用状态中这个数据发生改变时,都会重新生成新的视图。

Reagent/React——渲染视图

生成的新的视图会被重新渲染到DOM,展现给用户:

(reagent/render [views/items-view] (.getElementById js/document "app"))

示例Demo1—— re-frame simple template

示例Demo2—— Demo1重构后的版本

为什么重构?

re-frame

re-frame核心设计思想:数据

db

以上所述就是小编给大家介绍的《【Clojure】re-frame for SPA》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Anatomy

Web Anatomy

Robert Hoekman Jr.、Jared Spool / New Riders / 2009-12-11 / USD 39.99

At the start of every web design project, the ongoing struggles reappear. We want to design highly usable and self-evident applications, but we also want to devise innovative, compelling, and exciting......一起来看看 《Web Anatomy》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具