Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
KISSY.Base - all about that Base
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
ningzbruc
August 06, 2015
Programming
140
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
KISSY.Base - all about that Base
KISSY.Base的设计方法和最佳实践
ningzbruc
August 06, 2015
More Decks by ningzbruc
See All by ningzbruc
如何写出一个优秀的开源库
ningzbruc
0
68
去啊无线前端的一天
ningzbruc
1
200
React & Component
ningzbruc
0
54
阿里旅行去啊H5首页总结&Promise
ningzbruc
0
280
Hammer.js
ningzbruc
1
350
淘宝旅行门票iPad版开发
ningzbruc
0
150
Travel on KISSY mini
ningzbruc
0
210
Events
ningzbruc
2
130
Why YUI3
ningzbruc
0
190
Other Decks in Programming
See All in Programming
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
480
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
190
パーソナライズPodcastを作った話
repunit11
0
120
カツオ、ご期待ください
suneo3476
0
150
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
330
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
460
【加筆修正版】Laravel のアプリケーションをどこにデプロイするか #phpcon_ehime
akase244
0
150
Findy - エンジニア向け会社紹介/Findy Company Deck
findyinc
6
400k
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
480
動作中のプログラムの中身をリアルタイムに覗く / Realtime Debugger for CSharp with Roslyn
prota
1
1.8k
Ghostty + Neovimで作る 透明でカッコ良い開発環境
j341nono
0
150
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
350
Featured
See All Featured
Heart Work Chapter 1 - Part 1
lfama
PRO
10
36k
The agentic SEO stack - context over prompts
schlessera
0
970
Color Theory Basics | Prateek | Gurzu
gurzu
1
480
Music & Morning Musume
bryan
48
7.4k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.7k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Facilitating Awesome Meetings
lara
57
7.2k
GraphQLとの向き合い方2022年版
quramy
50
15k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
Ruling the World: When Life Gets Gamed
codingconduct
0
390
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
74
42k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
340
Transcript
纗䔺 ⚜⠫
None
Base • 组件标准化 • 继承与组合
#1 组件标准化
⼀一个简单组件的三要素 • ⽣生命周期(LifeCycle) • 参数配置(Config) • 事件通信(Event)
# Example - Box
API var box = new Box({ content: 'this is a
box!', parent: '#container', onShow: function() { alert('visible'); } }); box.show(); box.hide(); box.destroy(); # Example - Box
-JGF$ZDMF ളଁᇛ௹ var box = new Box({ content: 'this is
a box!', parent: '#container', onShow: function() { alert('visible'); } }); box.show(); box.hide(); box.destroy(); # Example - Box
$POGJH ҕඔᇂ var box = new Box({ content: 'this is
a box!', parent: '#container', onShow: function() { alert('visible'); } }); box.show(); box.hide(); box.destroy(); # Example - Box
&WFOU ൙ࡱ๙ྐ var box = new Box({ content: 'this is
a box!', parent: '#container', onShow: function() { alert('visible'); } }); box.show(); box.hide(); box.destroy(); # Example - Box
/** * 构造函数 */ function Box() { this.init.apply(this, arguments); }
/** * 原型 */ Box.prototype = { /** * 构造函数 */ constructor: Box, /** * 初始化 */ init: function() { /* ... */ }, /** * 销毁 */ destroy: function() { /* ... */ } }; -JGF$ZDMF ളଁᇛ௹ Step 1
Step 1 /** * 初始化 */ init: function() { this.render();
}, /** * 渲染 */ render: function() { this.box = document.createElement('div'); this.box.style.display = 'none'; this.box.innerHTML = this.cfg.content; this.cfg.parent.appendChild(this.box); }, /** * 销毁 */ destroy: function() { this.cfg.parent.removeChild(this.box); this.cfg = null; this.box = null; } -JGF$ZDMF ളଁᇛ௹
/** * 初始化 */ init: function() { this.config(cfg); this.render(); },
/** * 参数配置 */ config: function(cfg) { cfg = cfg || {}; cfg.parent = typeof cfg.parent == 'string' ? document.querySelector(cfg.parent) : cfg.parent; this.cfg = mix({ content: '', parent: document.body }, cfg); }, $POGJH ҕඔᇂ Step 2
/** * 初始化 */ init: function() { this.config(cfg); this.render(); },
/** * 参数配置 */ config: function(cfg) { cfg = cfg || {}; cfg.parent = typeof cfg.parent == 'string' ? document.querySelector(cfg.parent) : cfg.parent; this.cfg = mix({ content: '', parent: document.body }, cfg); }, Step 2 ਅݺ֥࡙ಸྟ
/** * 展⽰示 */ show: function() { this.box.style.display = 'block';
this.cfg.onShow && this.cfg.onShow.call(this); } Step 3 &WFOU ൙ࡱ๙ྐ
Problems?
/** * 初始化 */ init: function() { this.config(cfg); this.render(); },
/** * 参数配置 */ config: function(cfg) { cfg = cfg || {}; cfg.parent = typeof cfg.parent == 'string' ? document.querySelector(cfg.parent) : cfg.parent; this.cfg = mix({ content: '', parent: document.body }, cfg); }, َ෫֥ҕඔᇂ Step 2
buildParam : function(o) { var that = this; var o
= ( typeof o == 'undefined' || o == null) ? {} : o; that.autoSlide = ( typeof o.autoSlide == 'undefined' || o.autoSlide == null) ? false : o.autoSlide; that.speed = ( typeof o.speed == 'undefined' || o.speed == null) ? 0.5 : o.speed; that.timeout = ( typeof o.timeout == 'undefined' || o.timeout == null) ? 1000 : o.timeout; that.timedelay = ( typeof o.timedelay == 'undefined' || o.timedelay == null) ? -1 : o.timedelay; that.effect = ( typeof o.effect == 'undefined' || o.effect == null) ? 'none' : o.effect; that.eventype = ( typeof o.eventype == 'undefined' || o.eventype == null) ? 'click' : o.eventype; that.easing = ( typeof o.easing == 'undefined' || o.easing == null) ? 'easeBoth' : o.easing; that.hoverStop = ( typeof o.hoverStop == 'undefined' || o.hoverStop == null) ? true : o.hoverStop; that.selectedClass = ( typeof o.selectedClass == 'undefined' || o.selectedClass == null) ? 'selected' : o.selectedClass; that.conClass = ( typeof o.conClass == 'undefined' || o.conClass == null) ? 't-slide' : o.conClass; that.navClass = ( typeof o.navClass == 'undefined' || o.navClass == null) ? 'tab-nav' : o.navClass; that.contentClass = ( typeof o.contentClass == 'undefined' || o.contentClass == null) ? 'tab-content' : o.contentClass; that.pannelClass = ( typeof o.pannelClass == 'undefined' || o.pannelClass == null) ? 'tab-pannel' : o.pannelClass; that.before_switch = ( typeof o.before_switch == 'undefined' || o.before_switch == null) ? new Function : o.before_switch; that.ready = ( typeof o.ready == 'undefined' || o.ready == null) ? new Function : o.ready; that.carousel = ( typeof o.carousel == 'undefined' || o.carousel == null) ? false : o.carousel; that.id = that.id; that.tabs = []; that.animcon = null; that.pannels = []; that.timer = null; that.defaultTab = ( typeof o.defaultTab == 'undefined' || o.defaultTab == null) ? 0 : Number(o.defaultTab) - 1; that.current_tab = that.defaultTab; return this; },
buildParam : function(o) { var that = this; var o
= ( typeof o == 'undefined' || o == null) ? {} : o; that.autoSlide = ( typeof o.autoSlide == 'undefined' || o.autoSlide == null) ? false : o.autoSlide; that.speed = ( typeof o.speed == 'undefined' || o.speed == null) ? 0.5 : o.speed; that.timeout = ( typeof o.timeout == 'undefined' || o.timeout == null) ? 1000 : o.timeout; that.timedelay = ( typeof o.timedelay == 'undefined' || o.timedelay == null) ? -1 : o.timedelay; that.effect = ( typeof o.effect == 'undefined' || o.effect == null) ? 'none' : o.effect; that.eventype = ( typeof o.eventype == 'undefined' || o.eventype == null) ? 'click' : o.eventype; that.easing = ( typeof o.easing == 'undefined' || o.easing == null) ? 'easeBoth' : o.easing; that.hoverStop = ( typeof o.hoverStop == 'undefined' || o.hoverStop == null) ? true : o.hoverStop; that.selectedClass = ( typeof o.selectedClass == 'undefined' || o.selectedClass == null) ? 'selected' : o.selectedClass; that.conClass = ( typeof o.conClass == 'undefined' || o.conClass == null) ? 't-slide' : o.conClass; that.navClass = ( typeof o.navClass == 'undefined' || o.navClass == null) ? 'tab-nav' : o.navClass; that.contentClass = ( typeof o.contentClass == 'undefined' || o.contentClass == null) ? 'tab-content' : o.contentClass; that.pannelClass = ( typeof o.pannelClass == 'undefined' || o.pannelClass == null) ? 'tab-pannel' : o.pannelClass; that.before_switch = ( typeof o.before_switch == 'undefined' || o.before_switch == null) ? new Function : o.before_switch; that.ready = ( typeof o.ready == 'undefined' || o.ready == null) ? new Function : o.ready; that.carousel = ( typeof o.carousel == 'undefined' || o.carousel == null) ? false : o.carousel; that.id = that.id; that.tabs = []; that.animcon = null; that.pannels = []; that.timer = null; that.defaultTab = ( typeof o.defaultTab == 'undefined' || o.defaultTab == null) ? 0 : Number(o.defaultTab) - 1; that.current_tab = that.defaultTab; return this; }, 85'
var box = new Box({ content: 'this is a box!',
parent: '#container', onShow: function() { doA(); } }); /** * 展⽰示 */ show: function() { this.box.style.display = 'block'; this.cfg.onShow && this.cfg.onShow.call(this); } Step 3 &WFOU ൙ࡱ๙ྐ
var box = new Box({ content: 'this is a box!',
parent: '#container', onShow: function() { doA(); } }); /** * 展⽰示 */ show: function() { this.box.style.display = 'block'; this.cfg.onShow && this.cfg.onShow.call(this); } Step 3 &WFOU ൙ࡱ๙ྐ window.onload = loadFn; රᄻཌྷ്
var box = new Box({ content: 'this is a box!',
parent: '#container', onShow: function() { doA(); } }); /** * 展⽰示 */ show: function() { this.box.style.display = 'block'; this.cfg.onShow && this.cfg.onShow.call(this); } box.cfg.onShow = function() { doA(); doB(); }; Step 3 &WFOU ൙ࡱ๙ྐ window.onload = loadFn; රᄻཌྷ്
var box = new Box({ content: 'this is a box!',
parent: '#container', onShow: function() { doA(); } }); /** * 展⽰示 */ show: function() { this.box.style.display = 'block'; this.cfg.onShow && this.cfg.onShow.call(this); } var originOnShow = box.cfg.onShow; box.cfg.onShow = function() { originOnShow.apply(this, arguments); doB(); }; Step 3 &WFOU ൙ࡱ๙ྐ window.onload = loadFn; රᄻཌྷ്
var box = new Box({ content: 'this is a box!',
parent: '#container', onShow: function() { doA(); } }); /** * 展⽰示 */ show: function() { this.box.style.display = 'block'; this.cfg.onShow && this.cfg.onShow.call(this); } var originOnShow = box.cfg.onShow; box.cfg.onShow = function() { originOnShow.apply(this, arguments); doB(); }; Step 3 &WFOU ൙ࡱ๙ྐ ൙ࡱگႨ window.onload = loadFn; රᄻཌྷ്
‘Base’ of Base • ⽣生命周期(LifeCycle) • 参数配置(Attribute) • 事件通信(CustomEvent)
Step 1 -JGF$ZDMF ളଁᇛ௹ // 继承Base var Box = Base.extend({
/** * 初始化 */ initializer: function() { this.render(); }, /** * 渲染 */ render: function() { /* ... */ }, /** * 销毁 */ destructor: function() { this.cfg.parent.removeChild(this.box); this.cfg = null; this.box = null; } });
Step 1 -JGF$ZDMF ളଁᇛ௹ // 继承Base var Box = Base.extend({
/** * 初始化 */ initializer: function() { this.render(); }, /** * 渲染 */ render: function() { /* ... */ }, /** * 销毁 */ destructor: function() { this.cfg.parent.removeChild(this.box); this.cfg = null; this.box = null; } }); //初始化 var box = new Box({ /* ... */ }); //销毁 box.destroy();
Step 1 -JGF$ZDMF ളଁᇛ௹ // 继承Base var Box = Base.extend({
/** * 初始化 */ initializer: function() { this.render(); }, /** * 渲染 */ render: function() { /* ... */ }, /** * 销毁 */ destructor: function() { this.cfg.parent.removeChild(this.box); this.cfg = null; this.box = null; } }); //初始化 var box = new Box({ /* ... */ }); //销毁 box.destroy();
Step 2 // 继承Base var Box = Base.extend({ /* ...
*/ }, { /** * 参数配置 */ ATTRS: { parent: { // 默认值 value: document.body, // 校验 validator: function(v) { return !!v; }, //获取 getter: function(v) { return v; }, //设置 setter: function(v) { return typeof v == 'string' ? document.querySelector(v) : v; } } } }); "UUSJCVUF ҕඔᇂ
Step 2 // 继承Base var Box = Base.extend({ /* ...
*/ }, { /** * 参数配置 */ ATTRS: { parent: { // 默认值 value: document.body, // 校验 validator: function(v) { return !!v; }, //获取 getter: function(v) { return v; }, //设置 setter: function(v) { return typeof v == 'string' ? document.querySelector(v) : v; } } } }); "UUSJCVUF ҕඔᇂ var box = new Box({ parent: '#container', }); box.get('parent');
Step 2 // 继承Base var Box = Base.extend({ /* ...
*/ }, { /** * 参数配置 */ ATTRS: { parent: { // 默认值 value: document.body, // 校验 validator: function(v) { return !!v; }, //获取 getter: function(v) { return v; }, //设置 setter: function(v) { return typeof v == 'string' ? document.querySelector(v) : v; } } } }); "UUSJCVUF ҕඔᇂ var box = new Box({ parent: '#container', }); box.get('parent');
Step 2 // 继承Base var Box = Base.extend({ /* ...
*/ }, { /** * 参数配置 */ ATTRS: { parent: { // 默认值 value: document.body, // 校验 validator: function(v) { return !!v; }, //获取 getter: function(v) { return v; }, //设置 setter: function(v) { return typeof v == 'string' ? document.querySelector(v) : v; } } } }); "UUSJCVUF ҕඔᇂ var box = new Box({ parent: '#container', }); box.get('parent');
Step 2 // 继承Base var Box = Base.extend({ /* ...
*/ }, { /** * 参数配置 */ ATTRS: { parent: { // 默认值 value: document.body, // 校验 validator: function(v) { return !!v; }, //获取 getter: function(v) { return v; }, //设置 setter: function(v) { return typeof v == 'string' ? document.querySelector(v) : v; } } } }); "UUSJCVUF ҕඔᇂ var box = new Box({ parent: '#container', }); box.get('parent');
Step 2 // 继承Base var Box = Base.extend({ /* ...
*/ }, { /** * 参数配置 */ ATTRS: { parent: { // 默认值 value: document.body, // 校验 validator: function(v) { return !!v; }, //获取 getter: function(v) { return v; }, //设置 setter: function(v) { return typeof v == 'string' ? document.querySelector(v) : v; } } } }); "UUSJCVUF ҕඔᇂ var box = new Box({ parent: '#container', }); box.get('parent');
Step 2 // 继承Base var Box = Base.extend({ /* ...
*/ }, { /** * 参数配置 */ ATTRS: { parent: { // 默认值 value: document.body, // 校验 validator: function(v) { return !!v; }, //获取 getter: function(v) { return v; }, //设置 setter: function(v) { return typeof v == 'string' ? document.querySelector(v) : v; } } } }); "UUSJCVUF ҕඔᇂ var box = new Box({ parent: '#container', }); box.get('parent');
/** * 展⽰示 */ show: function() { this.box.style.display = 'block';
this.fire('show'); } var box = new Box({ /* ... */ }); box.on('show', doA); box.on('show', doB); box.on('show', doC); Step 3 $VTUPN&WFOU ሱקၬ൙ࡱ
/** * 展⽰示 */ show: function() { this.box.style.display = 'block';
this.fire('show'); } var box = new Box({ /* ... */ }); box.on('show', doA); box.on('show', doB); box.on('show', doC); Step 3 $VTUPN&WFOU ሱקၬ൙ࡱ
/** * 展⽰示 */ show: function() { this.box.style.display = 'block';
this.fire('show'); } var box = new Box({ /* ... */ }); box.on('show', doA); box.on('show', doB); box.on('show', doC); Step 3 $VTUPN&WFOU ሱקၬ൙ࡱ window.onload = loadFn; window.addEventListener('load', loadFn, false); රᄻཌྷ്
# AttributeCore
AttributeCore • 规范化参数配置 • 处理好参数兼容
get/set box.set('parent', '#page'); box.get('parent'); // div#page ѓሙ߄ҕඔ౼ഡᇂٚൔ
// 继承Base var Box = Base.extend({ /* ... */ },
{ /** * 参数配置 */ ATTRS: { /** * ⽗父节点 * @attribute parent * @type HTMLElement * @default document.body */ parent: { /* ... */ }, /** * 内容 * @attribute content * @type String */ content: { /* ... */ } /* ... */ } }); ၂ଢਔಖ ಸၞົ
• value(默认值) • validator(校验器) • getter(获取值) • setter(设置值) • valueFn(默认值函数)
ATTRS
• value(默认值) • validator(校验器) • getter(获取值) • setter(设置值) • valueFn(默认值函数)
ATTRS 常⽤用属性
parent: { // 默认值 value: document.body, // 校验 validator: function(v)
{ return !!v; }, //获取 getter: function(v) { return v; }, //设置 setter: function(v) { return typeof v == 'string' ? document.querySelector(v) : v; } } parent: { // 默认值 value: document.body, //设置 setter: function(v) { if (!v) { return Attribute.INVALID; } return typeof v == 'string' ? document.querySelector(v) : v; } } ATTRS
value vs. valueFn parent: { // 默认值 value: document.body, //设置
setter: function(v) { if (!v) { return Attribute.INVALID; } return typeof v == 'string' ? document.querySelector(v) : v; } } parent: { // 默认值函数 valueFn: function() { return document.body; }, //设置 setter: function(v) { if (!v) { return Attribute.INVALID; } return typeof v == 'string' ? document.querySelector(v) : v; } } 防⽌止值未初始化
value vs. valueFn data: { value: { a: 1, b:
2 } } boxA.get('data').a = 2; boxB.get('data').a; // 2 data: { valueFn: function() { return { a: 1, b: 2 }; } } boxA.get('data').a = 2; boxB.get('data').a; // 1 防⽌止多实例间参数对象共同引⽤用
# CustomEvent
DOM Event Features • 绑定/移除 • 捕获/冒泡 • 阻⽌止默认⾏行为 •
阻⽌止传播 • …
on // DOM Event node.on('click', clickFn); node.on('click', clickFn, context); //
Custom Event box.on('show', showFn); box.on('show', showFn, context);
fire box.on('show', function(e) { e.visible; // true }); box.fire('show', {
visible: true });
defaultFn /** * 初始化 */ initializer: function() { //发布事件 this.publish('show',
{ defaultFn: this._defShowFn }); }, /** * 展⽰示 */ show: function() { this.fire('show'); }, /** * 默认展⽰示回调 */ _defShowFn: function() { this.box.style.display = 'block'; } box.on('show', function(e) { console.log(e); }); box.fire('show');
/** * 渲染事件 * @event render * @param {EventFacade} e
事件对象 */ this.publish('render', { defaultTargetOnly: true }); /** * 清除查询字段(query)和结果(results)事件 * @event clear * @param {EventFacade} e 事件对象 * @preventable _defClearFn */ this.publish('clear', { defaultFn: this._defClearFn }); /** * 查询事件 * @event query * @param {EventFacade} e 事件对象 * @preventable _defQueryFn */ this.publish('query', { defaultFn: this._defQueryFn }); /** * 查询结果返回事件 * @event results * @param {EventFacade} e 事件对象 e.results * @preventable _defResultsFn */ this.publish('results', { defaultFn: this._defResultsFn }); we love defaultFns! NQJBVUPDPNQMFUFCBTFKT
preventDefault /** * 初始化 */ initializer: function() { //发布事件 this.publish('show',
{ defaultFn: this._defShowFn }); }, /** * 展⽰示 */ show: function() { this.fire('show'); }, /** * 默认展⽰示回调 */ _defShowFn: function() { this.box.style.display = 'block'; } box.on('show', function(e) { e.preventDefault(); }); box.fire('show');
preventDefault box.fire(“show"); execute subscribers defaultFn prevented? end yes no
<ul> <li>one</li> <li>two</li> <li>three</li> <li>four</li> <li>five</li> <li>six</li> DOM Event bubbles
ul.delegate('click', 'li', doSomething);
Custom Event bubbles? ManagerClass instance1 instance2 instance3 instance4 instance5 instance6
manager.delegate('event', 'instance', doSomething);
bubbles //添加冒泡对象 box.addTarget(parent); box.on('show', function(e) { console.log('box'); }); parent.on('show', function(e)
{ console.log('parent'); }); box.fire('show'); /** * 初始化 */ initializer: function() { //发布事件 this.publish('show', { bubbles: true, // 默认为true defaultFn: this._defShowFn }); }, /** * 展⽰示 */ show: function() { this.fire('show'); }, /** * 默认展⽰示回调 */ _defShowFn: function() { this.box.style.display = 'block'; } વஞ
FilterPanel:select Radio:select CheckBox:select Cascade:select
stopPropagation //添加冒泡对象 box.addTarget(parent); box.on('show', function(e) { e.stopPropagation(); }); parent.on('show', function(e)
{ console.log('parent'); }); box.fire('show'); ቅᆸવஞ x
stopImmediatePropagation box.on('show', function(e) { e.stopImmediatePropagation(); }); box.on('show', function(e) { console.log('box');
}); parent.on('show', function(e) { console.log('parent'); }); box.fire('show'); ቅᆸવஞ x ቅᆸԮѬ x
defaultTargetOnly /** * 初始化 */ initializer: function() { //发布事件 this.publish('render',
{ defaultFn: this._defRenderFn, defaultTargetOnly: true }); }, /** * 渲染 */ render: function() { this.fire('render'); }, /** * 默认渲染回调 */ _defRenderFn: function() { this.box = document.createElement('div'); this.get('parent').appendChild(this.box); } //添加冒泡对象 box.addTarget(parent); box.on('render', function(e) { console.log('box'); }); parent.on('render', function(e) { console.log('parent'); }); box.render(); વஞ ቅᆸଏಪྛູવஞ
⾃自定义事件系统的实现
# AttributeObserve
/** * 展⽰示 */ show: function() { this.fire('show'); }, /**
* 默认展⽰示回调 */ _defShowFn: function() { this.box.style.display = 'block'; } box.show(); box.show(); box.show(); Y State? ીႵ؎֒భሑ
/** * 展⽰示 */ show: function() { if (!this.visible) {
this.fire('show'); this.visible = true; } }, /** * 默认展⽰示回调 */ _defShowFn: function() { this.box.style.display = 'block'; } box.show(); box.show(); box.show(); Y State ݖႿَ෫
What we expect? /** * 展⽰示 */ show: function() {
this.visible = true; }, /** * 默认展⽰示回调 */ _defShowFn: function() { this.box.style.display = 'block'; } box.show(); box.show(); box.show(); Y ሑэ߄આࠠэ߄
attrChange /** * 初始化 */ initializer: function() { // 绑定状态变化回调
this.on('afterVisibleChange', this._afterVisibleChange); }, /** * 展⽰示 */ show: function() { this.set('visible', true); }, /** * 隐藏 */ hide: function() { this.set('visible', false); }, /** * 默认展⽰示回调 */ _afterVisibleChange: function(e) { this.box.style.display = e.newVal ? 'block' : 'none'; }, box.show(); box.show(); box.show(); Y ሑэ߄આࠠэ߄
attrChange • beforeAttrChange(状态即将发⽣生变化) • afterAttrChange(状态已经发⽣生变化) • e.newVal(新值) • e.prevVal(旧值)
attrChange • beforeAttrChange(状态即将发⽣生变化) • afterAttrChange(状态已经发⽣生变化) • e.newVal(新值) • e.prevVal(旧值) 常⽤用
attrChangeData box.on('afterVisibleChange', function(e) { e.src; // UI }); // 传⼊入额外参数
box.set('visible', true, { data: { src: 'UI' } }); // 静默更新 box.set('visible', true, { silent: true }); x ҂Ԩؿ൙ࡱ
#2 继承与组合
继承与组合 • 复⽤用性 • 扩展性 • 维护性 • 低耦合 •
易通信
extend /** * 继承 * @method extend * @param {Object}
r ⼦子类 * @param {Object} s ⽗父类 * @param {Object} px 原型属性 * @param {Object} sx 静态属性 */ function extend(r, s, px, sx) { var sp = s.prototype, rp = Object.create(sp); rp.constructor = r; r.prototype = rp; r.superclass = sp; mix(rp, px); mix(r, sx); return r; } ӵჰđ҂ӵൌ২උྟ function SuperClass() { this.a = 1; } SuperClass.prototype.add = function() { console.log('add'); }; function SubClass() { this.b = 2; } SubClass.prototype.remove = function() { console.log('remove'); }; S.extend(SubClass, SuperClass, {}, {}); var sub = new SubClass(); sub instanceof SubClass; // true sub instanceof SuperClass; // true sub.add(); // add sub.remove(); // remove sub.b; // 2 sub.a; // undefined
function SuperClass() { this.a = 1; } SuperClass.prototype.add = function()
{ console.log('add'); }; function SubClass() { SubClass.superclass.constructor.apply(this, arguments); // SuperClass.apply(this, arguments); 同上 this.b = 2; } SubClass.prototype.remove = function() { console.log('remove'); }; S.extend(SubClass, SuperClass, {}, {}); sub.b; // 2 sub.a; // 1 extend טႨڳো֥ܒᄯݦඔ Ԛ߄ൌ২උྟ
extend & lifecycle function Box() { this.init.apply(this, arguments); } Box.prototype.init
= function() { this.box = document.createElement('div'); document.body.appendChild(this.box); }; function Dialog() { Dialog.superclass.constructor.apply(this, arguments); } S.extend(Dialog, Box, { init: function() { this.box.innerHTML = 'this is a dialog'; } });
extend & lifecycle function Box() { this.init.apply(this, arguments); } Box.prototype.init
= function() { this.box = document.createElement('div'); document.body.appendChild(this.box); }; function Dialog() { Dialog.superclass.constructor.apply(this, arguments); } S.extend(Dialog, Box, { init: function() { this.box.innerHTML = 'this is a dialog'; } }); FSSPSUIJTCPYJTVOEFGJOFE ڭۂ
extend & lifecycle function Box() { this.init.apply(this, arguments); } Box.prototype.init
= function() { this.box = document.createElement('div'); document.body.appendChild(this.box); }; function Dialog() { Dialog.superclass.constructor.apply(this, arguments); } S.extend(Dialog, Box, { init: function() { Dialog.superclass.init.apply(this, arguments); this.box.innerHTML = 'this is a dialog'; } });
extend & lifecycle function Box() { this.init.apply(this, arguments); } Box.prototype.init
= function() { this.box = document.createElement('div'); document.body.appendChild(this.box); }; function Dialog() { Dialog.superclass.constructor.apply(this, arguments); } S.extend(Dialog, Box, { init: function() { Dialog.superclass.init.apply(this, arguments); this.box.innerHTML = 'this is a dialog'; } }); ԩَ෫
Base.extend // 继承Base var Box = Base.extend({ /** * 初始化
*/ initializer: function() { this.box = document.createElement('div'); document.body.appendChild(this.box); }, /** * 销毁 */ destructor: function() { this.box = null; } }); // 继承Box var Dialog = Box.extend({ /** * 初始化 */ initializer: function() { this.box.innerHTML = 'this is a dialog'; }, /** * 销毁 */ destructor: function() { this.box.innerHTML = ''; } }); // 1. Box: constructor // 2. Dialog: constructor // 3. Box: initializer // 4. Dialog: initializer var dialog = new Dialog(); // 5. Dialog: destructor // 6. Box: destructor dialog.destroy(); οඨԚ߄აཧ߮
Base.extend & ATTRS // 继承Base var Box = Base.extend({ /*
... */ }, { /** * 配置参数 */ ATTRS: { parent: { /* ... */ } } }); // 继承Box var Dialog = Box.extend({ /* ... */ }, { /** * 配置参数 */ ATTRS: { type: { /* ... */ } } }); var dialog = new Dialog({ parent: '#container', type: 'alert' }); dialog.get('parent'); // div#container dialog.get('type'); // alert ᆦӻކѩҕඔᇂ
Extensions
Extensions function Mask() { this.initMask(); } Mask.ATTRS = { opacity:
{ value: 0.5 } }; Mask.prototype.initMask = function() { this.mask = document.createElement('div'); this.mask.style.opacity = this.get('opacity'); this.get('parent').appendChild(this.mask); }; // 继承Box var Dialog = Box.extend([Mask], { /* ... */ }, { /* ... */ }); var dialog = new Dialog({ parent: '#container', type: 'alert', opacity: 0.8 }); dialog.mask; // div.mask dialog.get('opacity'); // 0.8 ࢳᯒଆॶđьႿົ
KISSY.add(function(S, ACBase, ACList) { /** * ⾃自动完成组件(搜索联想) * @module autocomplete
*/ /** * ⾃自动完成组件 * @class AutoComplete * @extends AutoCompleteBase * @uses AutoCompleteList * @constructor */ var AutoComplete = ACBase.extend([ACList], {}, { name: 'AutoComplete' }); return AutoComplete; }, { requires: ['./base', './list', './index.css'] }); we love extensions! NQJBVUPDPNQMFUFJOEFYKT
KISSY.add(function (S, Pad, Radio, Mask) { /** * 单选滑动组件 *
@module slide-radio */ /** * 单选滑动组件 * @class SlideRadio * @extends Pad * @uses RadioExt * @uses MaskExt * @constructor */ var SlideRadio = Pad.extend([Radio.Ext, Mask.Ext], { /* ... */ }); return SlideRadio; }, { requires:['../pad/', '../radio/', '../mask/', './index.css'] }); we love extensions!
Extension Problems • 没有⽣生命周期 • 在形成类之后⽆无法再继续扩展
What we expect function Mask() {} Mask.ATTRS = { opacity:
{ value: 0.5 } }; S.mix(Mask.prototype, { /** * 初始化 */ initializer: function() { this.mask = document.createElement('div'); this.mask.className = 'mask'; this.mask.style.opacity = this.get('opacity'); this.get('parent').appendChild(this.mask); }, /** * 销毁 */ destructor: function() { this.get('parent').removeChild(this.mask); } }); var Dialog = Box.extend([Mask], { /* ... */ }, { /* ... */ }); // 扩充额外的扩展 Dialog.mix(OtherExt); -JGF$ZDMF ളଁᇛ௹ ᆦӻحຓঔᅚ֥ঔԉ
plugins what’s plugins?
plugins • 有依赖的宿主(PluginHost) • 插拔不影响宿主功能 • 拥有⾃自主配置 • 与宿主有交互
plugins
plugins var optimus = new Transformer(); // 初始化宿主环境 var gun
= new Gun(); // 初始化插件 optimus.gun = gun; // 插⼊入插件 optimus.gun.fire(); // 调⽤用插件⽅方法 gun.destroy(); // 销毁插件 delete optimus.gun; // 拔出插件
Base plugins function Gun() {} S.mix(Gun.prototype, { /** * 插件ID
*/ pluginId: 'Gun', /** * 插件初始化 */ pluginInitializer: function() {}, /** * 插件销毁 */ pluginDestructor: function() {}, /** * 开⽕火 */ fire: function() { } }); var optimus = new Transformer(); // 初始化宿主环境 optimus.plug(Gun); // 初始化并插⼊入插件 optimus.getPlugin('Gun').fire(); // 调⽤用插件⽅方法 optimus.unplug('Gun'); // 销毁插件
Base plugin problems • 有依赖的宿主(PluginHost) • 插拔不影响宿主功能 • 拥有⾃自主配置(过于简单不⽀支持传参) •
与宿主有交互(没有⽅方法与宿主交互)
What we expect var Gun = Plugin.extend({ pid: 'Gun', /**
* 初始化 */ initializer: function() { console.log(this.get('host')); console.log(this.get('bullets')); }, /** * 初始化 */ destructor: function() { /* ... */ } }, { ATTRS: { bullets: { value: 1000 } } }); var optimus = new Transformer(); optimus.plug(Gun, { bullets: 2000 }); // optimus // 2000
Extension vs. Plugin • 类级别 • 修改原型 • 必要的功能 •
实例级别 • 不修改原型 • ⾮非必要的功能
Base • LifeCycle • CustomEvent • Attribute • Extension •
Plugin
Base • LifeCycle • CustomEvent • Attribute • Extension •
Plugin "MM'SFF
None
SuperBase what’s SB?
SuperBase • Fix Extension Problems • After Event • AOP
Fix Extension Problems • 增加扩展⽣生命周期 • ⽀支持额外扩展的扩充
var Calendar = Pad.extend([Mask.Ext], { /** * 选中⽇日期节点 */ select:
function(item) { this.fire('select', { item: item }); }, /** * 默认选中⽇日期节点 */ _defSelectFn: function(e) { this._selectedItem = e.item; this._selectedItem.addClass('selected'); } }); After Event var calendar = new Calendar(); calendar.on('select', function(e) { console.log(this._selectedItem); // null }); calendar.select(item); ೂޅᄝଏಪྛູᆭުԩઆࠠĤ
var Calendar = Pad.extend([Mask.Ext], { /** * 选中⽇日期节点 */ select:
function(item) { this.fire('select', { item: item }); }, /** * 默认选中⽇日期节点 */ _defSelectFn: function(e) { this._selectedItem = e.item; this._selectedItem.addClass('selected'); } }); What we expect োරႿBUUS$IBOHF ᄝଏಪྛູᆭުԩઆࠠ var calendar = new Calendar(); calendar.after('select', function(e) { console.log(this._selectedItem); // item }); calendar.select(item);
instance event _defEventFn instance.on(event,handler) instance.after(event,handler) after
AOP what’s AOP? ⾯面向切⾯面编程
AOP function Mask() {} Mask.prototype.renderMask = function() { this.mask =
document.createElement('div'); this.get('parent').insertBefore(this.box, this.mask); }; var Box = Base.extend({ render: function() { this.box = document.createElement('div'); this.get('parent').appendChild(this.box); } }); var Dialog = Box.extend([Mask], {}); ೂޅᄝ҂ྩڿჰٚم֥భิ༯ ࡼSFOEFS.BTL٢֞SFOEFSުᆳྛĤ
function Mask() { this.doAfter(this.renderMask, this, 'render', this); } Mask.prototype.renderMask =
function() { this.mask = document.createElement('div'); this.get('parent').insertBefore(this.box, this.mask); }; var Box = Base.extend({ render: function() { this.box = document.createElement('div'); this.get('parent').appendChild(this.box); } }); var Dialog = Box.extend([Mask], {}); AOP SFOEFS.BTLࡼᄝSFOEFSުᆳྛ
more AOP • ⽆无缝侵⼊入⽅方法(before,after) • 阻⽌止原⽅方法的执⾏行(prevent) • 阻⽌止AOP⽅方法的传播(halt) • 修改传参(before,AlterArgs)
• 修改返回值(after,AlterReturn) • …
SuperBase • LifeCycle • CustomEvent+ • Attribute • Extension+ •
Plugin • AOP
SuperBase • LifeCycle • CustomEvent+ • Attribute • Extension+ •
Plugin • AOP "MM'SFF
None
# Q&A