组件交互模式的非主流研究

  • 1,586 views
Uploaded on

 

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,586
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
21
Comments
0
Likes
2

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. 组件交互模式的 非主流研究 —— QWrap 2.0 前瞻:亚模块组件的设计
  • 2. 概要
    • 我是概要,不是提纲 =.=
    • 为什么要说这个?
    • 模块之间的交互
    • 直接调用的简单模式
    • 传统的事件模型 —— 电话模式
    • 组合和建立联系 —— IM 模式
    • 发出全局信息 —— 广播模式
    • 更有效传播信息 —— 微博模式
    • 还有没有别的方法?
    • 接下来要做什么?
    观察者模式的变体
  • 3. 为什么要说这个?
    • 模块之间交互存在的问题
      • 独立的模块之间有时候难于交互
    • 业务需求的零散与模块独立完整之间的差异
      • 业务需求变化意味着组件产品的功能增加
      • 但是组件产品功能不断增加会导致问题
    • 臃肿与适应性之间的平衡
      • 组件随着不断升级功能越来越完善,但是。。。
      • 完善也意味着更复杂了,从一定程度上更难使用了。。。
    • “ 亚模块组件”的设计
      • 比模块更细粒度的代码复用
  • 4. 模块之间的交互
    • 数据交互
      • A 模块给 B 模块提供数据
    • 控制流程
      • A 模块状态改变引起 B 模块变化
    • 多模块之间复杂交互(数据 + 控制)
      • 多个模块的组合和互相影响(例如:相册)
  • 5. 最简单的直接调用
    • 模块 B 调用模块 A 的方法
      • B.someMethod.call(this, A);
    • 模块有可能调用一系列其他模块的方法
      • function(){
      • A.some.call…
      • B.some.call…
      • C.some.call…
      • ……
      • }
    • 优点? 缺点?
  • 6. 事件模型
    • 事件模型可能会写出这样的代码
      • void function () {
      • // 加一个 proxy 属性
      • var d = new BB.SimpleDrag(
      • { target : BB.Dom.query("td"), withProxy : true }
      • , [
      • { source : BB.$('drag1'), proxy : BB.$('drag1-proxy') }
      • , { source : BB.$('drag2') }
      • ]
      • );
      • d.ondragenter = function (e) {
      • BB.Dom.setStyle(e.context.target, 'background-color', '#F00');
      • };
      • d.ondragover = function (e) {
      • if (e.context.previousTarget && e.context.previousTarget != e.context.target) {
      • BB.Dom.setStyle(e.context.previousTarget, 'background-color', 'transparent');
      • }
      • e.context.previousTarget = e.context.target;
      • BB.Dom.setStyle(e.context.target, 'background-color', '#F00');
      • };
      • d.ondragleave = function (e) {
      • BB.Dom.setStyle(e.context.target, 'background-color', 'transparent');
      • };
      • d.ondragdrop = function (e) {
      • alert('dragdrop');
      • };
      • d.oninvaliddrop = function (e) {
      • alert('invaliddrop');
      • };
      • }();
  • 7. 事件模型
      • d.ondragenter = function (e) {
      • BB.Dom.setStyle(e.context.target, 'background-color', '#F00');
      • };
      • d.ondragover = function (e) {
      • if (e.context.previousTarget && e.context.previousTarget != e.context.target) {
      • BB.Dom.setStyle(e.context.previousTarget, 'background-color', 'transparent');
      • }
      • e.context.previousTarget = e.context.target;
      • BB.Dom.setStyle(e.context.target, 'background-color', '#F00');
      • };
      • d.ondragleave = function (e) {
      • BB.Dom.setStyle(e.context.target, 'background-color', 'transparent');
      • };
  • 8. 事件模型
    • 事件模型要求我们:
      • 记住组件有哪些事件
      • 一般在一个 handler 内要求完成所有的业务操作
        • 需求变了往往意味着修改 handler 对应的执行代码
      • 有时候用多投,但是多投有时候也很麻烦
      • 每个组件都有一堆 onXxx
      • 如果 pm 跟我们提需求, onXxx 可能会越来越多
      • 交叉事件响应异常麻烦
        • 例如 A 的 click 触发 B 的 focus , B 的 focus 又触发 C 和 D 的 update……
  • 9. 事件模型
    • 组件之间的交互多了,事件模型会有很大的问题
      • 组件耦合是一件痛苦的事情
      • click -> focus -> update
      • drop -> selected -> highlight
      • ……
    • 那我们一般怎么做的?
      • 组件尽量功能独立
      • 一般很少考虑组件间的复杂交互
      • 配置式的封装使用(如 panel 封装成 dialog )
      • 和 pm 砍需求,不给做
  • 10. 事件模型
    • 有问题还是没问题?
    • 逃避原理
      • 一件事情我不想发生,我可以让它不发生
      • 于是我说,没有这个问题
      • 一个需求满足不了,我可以让这个需求不产生
      • 于是我说,没有这个需求
  • 11. 事件模型
    • 事实的真相
      • 也许我们从来很少怀疑的设计出了问题
      • 也许我们可以做得更好
    • 让我们看看有什么别的方法可以做
  • 12. 广播模式
    • 我改变了,不用亲自去处理,我可以说出来
      • a.broadcast({target:a.id,text:”I’ve been changed”});
      • b.receive(
      • function(message){
      • if(message.target == someid){
      • b.doSomeChange();
      • b.broadcast({target:b, text:”I’ve been changed,too”,reason:a});
      • }
      • }
      • );
  • 13. 广播模式
    • 好处?
      • 模块 A 不需要知道模块 B 的存在
      • 模块 A 只需要广播它状态的变化
      • 模块 B 只知有消息存在,不关心 A
      • 模块 A 和 B 的耦合度很低了
    • 坏处?
      • 广播意味着所有组件都能收到,不太好吧?
      • 如何保证实现效率?
      • 可能 receive 里有很多很多分支
  • 14. 新的模式
    • 怎么做更好?
      • 思考一下
  • 15. 新的模式
    • 也许我们只需要改变一点点:
      • // 类似 twitter 的观察者模式,可以看作是事件强化版,感觉比广播好,也更灵活
      • function Twitter(){
      • this.followers = [];
      • }
      • Twitter.prototype. tweet = function(msg){
      • for(var i = 0; i < this.followers.length; i++){
      • var follower = this.followers[i];
      • if(follower.handler){
      • follower.handler.call(follower.target, msg); //deal
      • }
      • }
      • }
      • Twitter.prototype. follow = function(master, handler){
      • master.followers.push({target:this, handler:handler});
      • }
  • 16. 新的模式
    • 简单试试看:
      • // 用 tabView 做一个简单的实验,但是这个不是组件,这个是散的
      • var tab = new Twitter();
      • var view = new Twitter();
      • view.follow (tab, function(msg){
      • var view = document.getElementById(&quot;view&quot;).getElementsByTagName(&quot;span&quot;);
      • for(var i = 0; i < view.length; i++){
      • if(i == msg){
      • view[i].className = &quot;active&quot;;
      • }else{
      • view[i].className = &quot;&quot;;
      • }
      • }
      • });
      • var tabContainer = document.getElementById(&quot;tab&quot;);
      • tabContainer.onclick = function(event){
      • var evt = event || window.event;
      • var target = evt.srcElement || evt.target;
      • if(target != this){
      • tab.tweet (target.innerHTML-1);
      • }
      • }
  • 17. 新的模式
    • 和事件模型有什么区别?
      • 单点发布
      • 自愿收听
      • 单向联接
      • 分散传播
  • 18. 新的模式
    • 还有哪些事情可以做
      • 利用模式匹配解决分支很多的问题
      • b.follow(a,{
      • “ mouseover a”:function(message) {
      • },
      • “ click a”:function(message) {
      • }
      • });
  • 19. 新的模式
    • var matcher = FunctionH.overload. curry (
    • [function(){},,function(args){
    • return args.type+” a”;
    • }]
    • );
    • Twitter.prototype.tweet = function(msg){
    • for(var i = 0; i < this.followers.length; i++){
    • var follower = this.followers[i];
    • if(follower.handler){
    • matcher(follower.handler).call(follower.target,msg);
    • }
    • }
    • }
  • 20. 新的模式
    • 还有哪些事情可以做
      • 信息的传播—— retweet
      • b.follow(a, function(msg){
      • this.tweet(ObjectH.mix(addition,msg)); //retweet
      • });
      • 信息的非实时处理
        • 改改看?
      • 其他好玩的事情?
        • 就像我们在 twitter 上玩的那些花样
  • 21. 还有没有别的方法?
    • 大家讨论
  • 22. Q & A
    • 谢谢!