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 ...
随机推荐
- Java使用JNA方式调用DLL(动态链接库)(原创,装载请注明出处)
Java使用JNA调用DLL 1.准备 1.JDK环境 2.Eclipse 3.JNA包 下载JNA包: (1).JNA的Github:https://github.com/java-native-a ...
- Python 文件修改-函数介绍
上节课复习:1.字符编码 1.1 如何解决乱码问题: 字符存取使用的编码标准不一致 1.2 文件头 在文件的首行写入文件头,用于控制Python解释器读取py文件内容时使用的编码 #coding:文件 ...
- Python使用Flask框架,结合Highchart,自定义导出菜单项目及顺序
参考链接: https://www.highcharts.com.cn/docs/export-module-overview https://api.hcharts.cn/highcharts#ex ...
- python_流程控制
1.if...else 语句 单分支 if 条件: 满足条件后要执行的代码 双分支: """ if 条件: 满足条件执行代码 else: if条件不满足就走这段 & ...
- 杭电1722 Cake (分蛋糕)
#include<cstdio> int f(int m,int n) { ) return n; else return f(n,m%n); } int main() { int m,n ...
- Overload重載和Override重写的区别。Overloaded的方法是否可以改变返回值的类型?
Overload是重载的意思,Override是覆盖的意思,也就是重写. 重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同). 重写Ove ...
- jquery给span赋值
span是最简单的容器,可以当作一个形式标签,其取值赋值方法有别于一般的页面元素. //赋值 $("#spanid").html(value) //取值 $("#span ...
- 将 Oracle VirtualBox 中运行的虚拟机导入 VMware Fusion、Workstation 或 Player
1.从virtualbox种导出电脑为 .ova格式镜像 要导入 Oracle VirtualBox 中运行的虚拟机,必须将该虚拟机从 VirtualBox 导出到开放虚拟化格式存档(.ova 文件) ...
- SPOJ GSS6 Can you answer these queries VI
Can you answer these queries VI Time Limit: 2000ms Memory Limit: 262144KB This problem will be judge ...
- Chrome & CORS & Fetch API & Chrome 多开,应用分身
Chrome & CORS & Fetch API Chrome 浏览器的跨域设置 https://www.cnblogs.com/cshi/p/5660039.html https: ...