javascript 物件註冊自定義監聽器
阿新 • • 發佈:2019-01-06
事件監聽的方式實現js 物件事件的訂閱/釋出。
eventEmitter 主要有三個介面方法:
- registe: 註冊事件監聽
- on: 訂閱事件
- emit: 釋出事件
使用示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
< meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script type="text/javascript" src="../bower_components/vue/dist/vue.min.js"></script>
<script type="text/javascript" src="./eventEmitter.js"></script>
</head>
<body>
<div id="app">
<span v-text="message"></span>
<button @click="bind">bind</button>
<button @click="call">call</button>
</div>
<script>
var component = Vue.extend({
el: '#app',
data: function(){
return {
message: 'Hello Vue.'
}
},
created(){
EventEmitter.registe(this)
},
methods: {
bind() {
this.on('hello', function(evt){
console.log('hello ' + evt)
})
},
call() {
this.emit('hello', 'world')
}
}
})
new Vue(component)
</script>
</body>
</html>
執行結果:
注意區分vue 自帶的$emit 和 $on
eventEmitter 原始碼如下:
;(function(global){
/**
* 遍歷執行陣列中的每個元素
* @param {*} ary
* @param {*} func
*/
function each(ary, func){
if (ary) {
var i;
for (i = 0; i < ary.length; i += 1) {
if (ary[i] && func(ary[i], i, ary)) {
break;
}
}
}
}
/**
* 遍歷執行物件中的每個屬性(不包含繼承鏈屬性)
* @param {*} obj
* @param {*} func
*/
function eachProp(obj, func) {
var prop;
for (prop in obj) {
if (obj.hasOwnProperty(prop)) {
if (func(obj[prop], prop)) {
break;
}
}
}
}
/**
* 將source 物件屬性混入到target 中
*/
function mixin(target, source, force, deepStringMixin) {
if (source) {
eachProp(source, function (value, prop) {
if (force || !target.hasOwnProperty(prop)) {
if (deepStringMixin && typeof value === 'object' && value &&
!isArray(value) && !isFunction(value) &&
!(value instanceof RegExp)) {
if (!target[prop]) {
target[prop] = {};
}
mixin(target[prop], value, force, deepStringMixin);
} else {
target[prop] = value;
}
}
});
}
return target;
}
/**
* 判斷是不是方法
* @param {*} target
*/
function isFunction(target){
return Object.prototype.toString.call(target) === '[object Function]';
}
/**
* 判斷是不是陣列
* @param {*} target
*/
function isArray(target){
return Object.prototype.toString.call(target) === '[object Array]';
}
var EventEmitter = {
events: [],
/**
* 繫結事件
* @param {*} name
* @param {*} cb
*/
on(name, cb){
var cbs = this.events[name];
if (!cbs) {
cbs = this.events[name] = [];
}
cbs.push(cb);
},
/**
* 觸發事件
* @param {*} name
* @param {*} evt
*/
emit(name, evt){
each(this.events[name], function (cb) {
cb(evt);
});
if (name === 'error') {
delete this.events[name];
}
}
}
var exp = {}
exp.eventEmitter = EventEmitter;
// 註冊事件監聽
exp.registe = function(target){
if(target.events || target.on || target.emit) throw new Error('target already has the mixin properties.');
else {
mixin(target, exp.eventEmitter)
}
}
global.EventEmitter = exp;
})(window);
至此,結束。