LightTable的结构(二)
这节主要研究下object的一个属性,behaviors
定义一个behavior需要提供name,trigger,reaction
(behavior ::on-close-destroy
:triggers #{:close}
:reaction (fn [this]
(object/raise this :destroy)))
在创建object的时候传入
(object/object* ::user.hello
:tags [:user.hello]
:behaviors [::on-close-destroy]
:init (fn [this]
(hello-panel this)))
在object/object*和object/create的时候都可以传入behavior
那么怎么触发behavior呢
(object/raise app :closing)
(defn raise*
([obj reactions args] (raise* obj reactions args nil))
([obj reactions args trigger]
(doseq [r reactions
:let [func (:reaction (->behavior r))
args (if (coll? r)
(concat (rest r) args)
args)
meta (if (coll? r)
(meta r)
{})]
:when func]
(try
(with-time
(binding [*behavior-meta* meta]
(apply func obj args))
(when-not (= trigger :object.behavior.time)
(raise obj :object.behavior.time r time trigger)))
(catch js/Error e
(safe-report-error (str "Invalid behavior: " (-> (->behavior r) :name)))
(safe-report-error e)
)
(catch js/global.Error e
(safe-report-error (str "Invalid behavior: " (-> (->behavior r) :name)))
(safe-report-error e)
))))) (defn raise [obj k & args]
(let [reactions (-> @obj :listeners k)]
(raise* obj reactions args k)))
可以看出,object/raise会从obj的:listeners中获取对应trigger的reactions
object/raise*中,对这些reactions进行执行,那么behavior是如何变成:listener的呢,注意到 object/handle-redef 会使用update-listeners
(defn handle-redef [odef]
(let [id (::type odef)]
(doseq [o (instances-by-type id)
:let [o (deref o)
args (:args o)
old (:content o)
behs (set (:behaviors o))
inst (@instances (->id o))
neue (when (:init odef)
(apply (:init odef) inst args))
neue (if (vector? neue)
(crate/html neue)
neue)]]
(merge! inst {:tags (set/union (:tags o) (:tags odef))
:behaviors (set/union behs (set (:behaviors odef)))
:content neue})
(merge! inst (update-listeners inst))
(when (and old neue)
(replace-with old neue))
(raise inst :redef))
id)) (defn object* [name & r]
(-> (apply make-object* name r)
(store-object*)
(handle-redef)))
update-listeners利用->triggers将behavior转换成对应的 trigger,存入:listeners
(defn update-listeners
([obj] (update-listeners obj nil))
([obj instants]
(let [cur @obj
behs (set (concat (:behaviors cur) (tags->behaviors (:tags cur))))
trigs (->triggers behs)
;;We need to load new JS files here because they may define the behaviors that we're meant to
;;capture. If we have a load, then load and recalculate the triggers to pick up those newly
;;defined behaviors
trigs (if (:object.instant-load trigs)
(do
(raise* obj (:object.instant-load trigs) nil :object.instant-load)
(->triggers behs))
trigs)
trigs (if instants
trigs
(dissoc trigs :object.instant :object.instant-load))]
;;deref again in case :object.instant-load made any updates
(assoc @obj :listeners trigs))))
(defn ->triggers [behs]
(let [result (atom (transient {}))]
(doseq [beh behs
t (:triggers (->behavior beh))]
(swap! result assoc! t (conj (or (get @result t) '()) beh)))
(persistent! @result)))
--------------------------------------
注:
获取Ref, Atom 和Agent对应的value @ref (deref ref)
LightTable的结构(二)的更多相关文章
- PostgreSQL的存储系统二:REDOLOG文件存储结构二
REDOLOG文件里的用户数据和数据文件里的用户数据存储结构相同 几个月前同事给台湾一家公司培训<pg9 ad admin>时,有个学员提及WAL里记录的内容为Query时的SQL语句(比 ...
- JAVA的选择结构(二)
1.switch选择结构: 语法: switch (key) { ...
- update_engine-整体结构(二)
在update_engine-整体结构(一)中分析UpdateEngineDaemon::OnInit()的整体情况.下面先分析在该方法中涉及的DaemonStateAndroid和BinderUpd ...
- java虚拟机规范(se8)——java虚拟机结构(二)
2.5 运行时数据区域 java虚拟机定义了多个用于程序执行期间的运行时数据区域.这些数据区域中一些随着java虚拟机的启动而创建,随着虚拟机的退出而销毁.其他的数据区域时和线程相关的.线程相关数据区 ...
- Flask从入门到精通之大型程序的结构二
一.程序包 程序包用来保存程序的所有代码.模板和静态文件.我们可以把这个包直接称为app(应用),如果有需求,也可使用一个程序专用名字.templates 和static 文件夹是程序包的一部分,因此 ...
- PLSQL中使用二维存储结构---二维数组
代码如下: --PLSQL中没有数组的概念 用TYPE 和Table of Record来代替多维数组--create by jenrry 20171028-- 1.0 建立存放列的测试表creat ...
- LightTable的结构(一)
LightTable使用clojurescript来生成js,然后使用 node-webkit 来处理UI clojurescript非常适合做抽象程度很高的页面和编辑逻辑结构设计, 最近会对整体进行 ...
- Linux目录结构(二)
Linux文件系统结的结构是树形结构,其入口从/开始,了解Linux文件系统的结构,对于我们需要掌握的基础知识点之一. 2.文件系统的组织结构简说: 当您使用Linux的时候,如果您通过ls -la ...
- java6循环结构二
public class jh_01_回顾与作业点评 { public static void main(String[] args) { int val = 12345; System.out.pr ...
随机推荐
- 计算几何——认识基本object:点、线、面 。
认识基本object:点.线.面 一.点 点用P(x, y)来表示:如: typedef pair<double, double> _pair; _pair point[MAXN]; 二 ...
- VSCODE插件开发:用户输入输出
阅读这篇文章之前,假设你已经具有开发helloworld的插件的能力. vscode.window 简介 vscode.window 负责当前激活窗口的输入输出,比如展示信息,和用户输入等功能都是用v ...
- [Python3网络爬虫开发实战] 1.6.2-Tornado的安装
Tornado是一个支持异步的Web框架,通过使用非阻塞I/O流,它可以支撑成千上万的开放连接,效率非常高,本节就来介绍一下它的安装方式. 1. 相关链接 GitHub:https://github. ...
- JSON对象与JSON字符串之间的转换
JSON引用包:import net.sf.json 1.JSON字符串转JSON对象(例子中的AgencyExpand是java对象) JSONObject json = JSONObject.f ...
- Spider-Python爬虫之使用Selenium模拟浏览器行为
分析 他的代码比较简单,主要有以下的步骤:使用BeautifulSoup库,打开百度贴吧的首页地址,再解析得到id为new_list标签底下的img标签,最后将img标签的图片保存下来. header ...
- python接口测试之序列化与反序列化(四)
在python中,序列化可以理解为:把python的对象编码转换为json格式的字符串,反序列化可以理解为:把json格式 字符串解码为python数据对象.在python的标准库中,专门提供了jso ...
- 客户端用plsql进行中文条件查询时无结果的解决办法
1.SELECT * FROM v$nls_parameters ; 查看NLS_CHARACTERSET 的值是多少,我的AL32UTF8- 查找客户机器的注册表,查找NLS_LANG的值,改成AL ...
- [luoguP2444] [POI2000]病毒(AC自动机 + dfs)
传送门 先把所有串建一个AC自动机, 如果要找一个不包含任意一个串的串, 说明这个串一直在AC自动机上匹配但匹配不到, 也就是说,匹配时除去val值为1的点,除去fail指针指向val值为1的点,是否 ...
- linux 文件系统 磁盘分区 格式化
1.du -sh test #查看文件或者目录的大小 2.cat file | wc -l #查看文件的行数 3.ls dirname | wc -l #查看文件个数 4.stat install.l ...
- POJ——T 2728 Desert King
http://poj.org/problem?id=2728 Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 27191 ...