介绍
riot.observable是riot的一个订阅发布模式的实现。那么在中什么时候会用到这个,其实在riot源码自身大量运用到了这个,我们也可以自己手动去创建一个具有发布订阅的实体对象。我们先看看在riot源码自身是何时用到这个。
在这篇文章中,我们就遇到过一次:
看下他的输入输出:
再看源码:
/* istanbul ignore next */
var observable = function(el) {
/**
* Extend the original object or create a new empty one
* @type { Object }
*/
el = el || {};
/**
* Private variables
*/
var callbacks = {},
slice = Array.prototype.slice;
/**
* Public Api
*/
// extend the el object adding the observable methods
Object.defineProperties(el, {
/**
* Listen to the given `event` ands
* execute the `callback` each time an event is triggered.
* @param { String } event - event id
* @param { Function } fn - callback function
* @returns { Object } el
*/
on: {
value: function(event, fn) {
if (typeof fn == 'function')
{ (callbacks[event] = callbacks[event] || []).push(fn); }
return el
},
enumerable: false,
writable: false,
configurable: false
},
/**
* Removes the given `event` listeners
* @param { String } event - event id
* @param { Function } fn - callback function
* @returns { Object } el
*/
off: {
value: function(event, fn) {
if (event == '*' && !fn) { callbacks = {}; }
else {
if (fn) {
var arr = callbacks[event];
for (var i = 0, cb; cb = arr && arr[i]; ++i) {
if (cb == fn) { arr.splice(i--, 1); }
}
} else { delete callbacks[event]; }
}
return el
},
enumerable: false,
writable: false,
configurable: false
},
/**
* Listen to the given `event` and
* execute the `callback` at most once
* @param { String } event - event id
* @param { Function } fn - callback function
* @returns { Object } el
*/
one: {
value: function(event, fn) {
function on() {
el.off(event, on);
fn.apply(el, arguments);
}
return el.on(event, on)
},
enumerable: false,
writable: false,
configurable: false
},
/**
* Execute all callback functions that listen to
* the given `event`
* @param { String } event - event id
* @returns { Object } el
*/
trigger: {
value: function(event) {
var arguments$1 = arguments;
// getting the arguments
var arglen = arguments.length - 1,
args = new Array(arglen),
fns,
fn,
i;
for (i = 0; i < arglen; i++) {
args[i] = arguments$1[i + 1]; // skip first argument
}
fns = slice.call(callbacks[event] || [], 0);
for (i = 0; fn = fns[i]; ++i) {
fn.apply(el, args);
}
if (callbacks['*'] && event != '*')
{ el.trigger.apply(el, ['*', event].concat(args)); }
return el
},
enumerable: false,
writable: false,
configurable: false
}
});
return el
};
发现其实就是使用Object.defineProperty定义了四个函数,on/off/one/trigger
- on : 订阅事件,其实就是用一个对象把你要监听的函数以[事件名-fn]的形式存起来
- off:删除事件
- one:订阅只发生一次的事件
- trrigger:触发已经订阅好的事件 其实就是把订阅好的事件数组取出来一个一个执行。
然后再riot源码中,还有一个地方用到了:
这里的意思是,把创建的每一个tag对象都绑定上发布订阅模式,也就是说,我们在代码中的
this.on('mount', () => {
// ...
});
this.on('update', () => {]\
// ...
})
都是订阅一个事件。然后riot会在合适的时机,去trigger调用这些已经订阅好的事件。具体的后面再说。