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 ...
随机推荐
- uLua-案例学习-API
LuaState.Start()初始化吧 LuaState.AddSearchPath(string fullPath)增加搜索路径,这样在执行lua文件时就不需要输入全路径,类似环境变量path. ...
- 【thinking in java】反射
前言 反射是框架设计的灵魂,使用的前提条件:必须先得到字节码的Class,Class类用于表示字节码,字节码即是.class文件 概述 JAVA反射机制:在程序运行的过程中,对于任意一个类,都可以知道 ...
- Linux思维导图之网络管理
查漏补缺,理解概念,及时总结,欢迎拍砖. IP地址和MAC地址: 1.设计形态不同.IP地址是基于网络拓扑设计出来的,可以人为改动:而MAC地址是制造商烧录好的不能改动,网卡决定了MAC地址,是固定的 ...
- rbac组件之菜单操作(三)
菜单包括菜单列表,菜单列表不仅将菜单列出来,而且将每个菜单下的权限也列出来.菜单的添加.删除.修改. urls.py ... re_path(r'^menus/list/$', MenuView.as ...
- vue中的表单验证
http://www.cnblogs.com/luoxuemei/p/9295506.html /*是否合法IP地址*/ export function validateIP(rule, value, ...
- 第十一节:pandas统计函数
1.pct_change()计算增长比例 2.cov()协方差 3.corr()相关系数 4.rank()数据排名 5.numpy聚合函数
- 图解使用IDEA创建第一个Java程序HelloWorld
前几次给大家分享了怎么在自己的电脑上配置 java 环境,准备工作做好了,我们就要开始我们真正的编码学习了.下面介绍使用 IDEA 创建我们的第一个 HelloWorld 程序. 1.打开 IDEA, ...
- 用mycat做读写分离:基于 MySQL主从复制
版权声明:本文为博主原创文章,未经博主允许不得转载. mycat是最近很火的一款国人发明的分布式数据库中间件,它是基于阿里的cobar的基础上进行开发的 搭建之前我们先要配置MySQL的主从复制,这个 ...
- jsp页面根据json数据动态生成table
根据需求由于不同的表要在同一个jsp展示,点击某个表名便显示某张表内容,对于java后台传给jsp页面的json形式的数据是怎么动态生成table的呢? 找了好久,终于找到某位前辈的答案,在此表示衷心 ...
- [bzoj1500][NOI2005]维修数列[Treap][可持久化Treap]
非旋转式Treap1500 :) #include <bits/stdc++.h> #pragma GCC optimize(3) using namespace std; const i ...