Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

events/base/widget 相关问题总结 #247

Closed
2 of 3 tasks
lianqin7 opened this issue Mar 29, 2013 · 12 comments
Closed
2 of 3 tasks

events/base/widget 相关问题总结 #247

lianqin7 opened this issue Mar 29, 2013 · 12 comments

Comments

@lianqin7
Copy link
Member

@popomore

使用arale也一段时间了,针对团队中比较常见的问题做个总结

  • Aspect的功能强化 base#5 使用 aspect 的时候,before:method 事件无法通过 return false 来阻止 method 的继续运行
  • plugin 机制 widget#15 widget没有提供插件机制
  • widget的template的性能问题 这个可以通过 模板引擎runtime 的方式解决
@popomore
Copy link
Member

能否详细描述下你们在开发时希望使用插件机制的场景?

@yunfour
Copy link

yunfour commented Mar 29, 2013

就是之前写好的一些jquery的插件,现在怎么能快速融入的seajs中使用

@lianqin7
Copy link
Member Author

lianqin7 commented Apr 1, 2013

@popomore

  1. 首先先明确一点,此插件非 jQuery 的插件,这个都懂的:)
  2. 理论点的说法, 插件 是从 实例 层面对相同功能的封装及复用,区别于 组合,继承与接口原型 层面的相关操作。是功能复用性的另一种实现形式。

所以从上面来说,其实 插件 能做的事情, 继承与接口 也一定能做,只是代码实现细节及使用方式的不同

那为什么要插件呢?我这里有个简单的例子:


假设已经有了拖拽的组件,有如下的使用方式(api先参考YUI3的):

var Drag = require('drag');
new Drag({
    element: '#id1',
    handle: 'h2'      // 这个api表示在 '#id1 h2' 上触发拖拽,拖拽的dom是 '#id1'
}).render();

需求来了: 让 Overlay 组件具有拖拽的功能,并且的可配的
那大概的,overlay的源码要修改:

var Drag = require('drag');
var Widget = require('widget');

// .....省略

var Overlay = Widget.extend({
    attrs: {
        // ... 省略
        dragable: false,   // 是否启动拖拽功能
        handle: null        // 拖拽的相关配置
    },
    // ... 省略
    setup: function(){
        // ... 省略
        // 加上 Drag 组件初始化的代码
    }
});

以上代码从原型上实现了overlay的拖拽功能,而且也没什么问题

但是需求又来了: Drag的功能升级了(比如拖拽的区域限制等),Overlay的拖拽功能也要升级

于是,又要 修改Overlay的源码,比如增加新的attr神马的,去给内部的Drag实例调用,周而复始

这种复用的方式,怎么看起来就那么的不爽呢?:(


分析下 Overlay 与 Drag 之间的关系:

  1. Drag 只是让某个dom具有拖拽的功能,没有特指定某个组件
  2. Drag 对 Overlay 的内部实现没有修改
  3. Drag 有自己独立的配置及实现,这部分内容 Overlay 完全可以不关心,但是因为是组合的代码实现,导致每次 Drag 的修改都会引起 Overlay 的代码修改
  4. 如果只有很少的情况下在 Overlay 中去启用 Drag 的功能,其他大部分情况下的 Ovelay 代码都要额外加载 Drag 的相关代码,有性能的损失

在这种关系下,用对 原型 的修改,都无法 “完美” 的解决这些问题


换个思路,用对 实例 的修改来达到复用的目的,这就是 插件(plugins)

api参考YUI3

var DragPlugin = require('drag-plugin');
var Overlay = require('overlay');

var o = new Overlay({
    element: '#id2'
}).plug(DragPlugin, {
    handle: 'h2'
}).render();

// or

var o = new Overlay({
    element: '#id2',
    plugins: [{
      fn: DragPlugin,
      cfg: {
          handle: 'h2'
      }
    }]
}).render();

DragPlugin 作为 Drag 的一个子模块,有同样的 Drag 内核,只是封装成了 插件 的形式,这样就把 Overlay 与 Drag 的关系分开了,分别独立发展,在 实例化 的时候才组合。实现了另一种形式的复用

@lepture
Copy link
Contributor

lepture commented Apr 1, 2013

@lianqin7 drag 的这个例子,我觉得更好的方法是这样:

var o = new Overlay(...)

draggable(o, {..})

@lifesinger
Copy link
Member

@lianqin7 让我想起 position
position 是个纯粹的工具类,与其他模块只有组合关系

对于 draggable 来说,是否也有可能做成一个纯工具类?这样,只要 draggable 的 api 比较稳定,当升级时,就不会太影响组合了 draggable 类的源码,甚至可以在使用时直接:

var o = new Overlay(...)

draggable(o, {..})

就是南伯的示例

@lifesinger
Copy link
Member

YUI3 的 extension 和 plugin 有不少内部约定,这些约定让代码维护起来并不简单,有点担心。

@lepture
Copy link
Contributor

lepture commented Apr 1, 2013

@lifesinger draggable 还是和 widget 也解耦一下:

draggable(o.element, ...)

@lianqin7
Copy link
Member Author

lianqin7 commented Apr 1, 2013

@lifesinger @lepture

关于 position 和 dragable 还是有些区别的

  1. position 主要是一次性的调用工具方法。dragable 大部分功能是通过配置的,但是还可能有一部分的 方法调用(比如getXY等)事件(比如 draging,draged 等)
  2. position 的调用都是在 原型 中完成的。dragable 的初始化及调用是在 实例 中完成的
  3. position 不需要考虑 destory 的问题。dragable 需要考虑dom,事件的 destory等。

draggable(o, {..}) 的方式可以解决问题2,却很难解决问题1及问题3

而用了 plugin 的方式后, 问题1可以通过 o.plugins[NS].getXY() 的方式解决,而问题3可以通过宿主(host)统一的destory方式处理


@lifesinger

关于内部约定的问题,我觉得除了 plugin 的 NS 外,其他约定都可以通过api的设计规避(也许NS也能规避,只是目前没想到方法:( )


@lepture @lifesinger @popomore

最后说说,用 dragable 举 plugin 的例子只是比较贴近 widget 的设计,并不是说一定要用 plugin 的方式去实现,别为了 api 设计纠结了

而提供 plugin 机制是为了: 一种在实例层面的,有一定规约,生命周期管理及方法调用的代码/功能复用的机制

@lepture
Copy link
Contributor

lepture commented Apr 1, 2013

@lianqin7 问题 1, 3 都是可以解决的呀

var o = new Overlay(...)

o = draggable(o, {..})

o.on('dragging', function() {
})
o.getXY()

这个没什么问题吧。

这样的话,就不能和 widget 解耦了。

@afc163
Copy link
Member

afc163 commented Apr 1, 2013

在这个生态圈,每一个模块都有其自己的生命力,draggable(element, {...}); 的方式更简洁和独立,放到别的地方也能使用。

draggable-plugin 的话就只能依附于 Arale Widget 的实现,单独使用已不可能。

所以我们是典型的类库,不是框架。

@lianqin7
Copy link
Member Author

lianqin7 commented Apr 1, 2013

@afc163

我举 drag 的例子只是为了说明 plugin 对 widget 的作用,结果大家都跑到 dragable 的设计上来了:(
看来举例不好,得修改修改

draggable 能做为生态圈独立模块存在是很好的,对 plugin 来说也没有任何冲突,我想说明的 plugin 机制是为了: 一种在AraleWidget实例层面的,有一定规约,生命周期管理及方法调用的代码/功能复用的机制
是为了对 widget 的一种功能补全

@popomore
Copy link
Member

plugin 的问题还是放在 widget 讨论吧,那里有一个链接了。其他问题已经改完,计划月底稳定可以使用。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants