前言
上篇文章分析了Methods、Computed以及Moon中双向绑定的处理,本篇文章主要分析下自定义组件以及Moon内置的指令的实现。
具体分析
还是通过一个简单的实例来进行分析,实例代码如下:
<div id="app">
<mn-test></mn-test>
</div>
<script src="./moon.js"></script>
<script>
Moon.component('mn-test', {
template: '<p>{{msg}}</p>',
data: {
msg: 'hello world'
}
});
new Moon({
el: '#app'
});
</script>
Moon.component
Moon中提供了component来实现自定义组件,它是Moon构造函数的方法,可以直接使用,下面就来看看component是如何实现的:
Moon.component = function (name, opts) {
// 此处this代表Moon构造函数
var Parent = this;
// 是否存在name属性
if (opts.name) {
name = opts.name;
} else {
opts.name = name;
}
// MoonComponent构造函数,可以看出实际上是调用Moon构造函数
function MoonComponent() {
Moon.call(this, opts);
}
// 设置MoonComponent构造函数的原型对象是Moon函数的原型对象,即MoonComponennt继承Moon
MoonComponent.prototype = Object.create(Parent.prototype);
MoonComponent.prototype.constructor = MoonComponent;
// 重定义init方法
MoonComponent.prototype.init = function () {
callHook(this, 'init');
this.$destroyed = false;
this.$props = this.$opts.props || [];
// 模板html
this.$template = this.$opts.template;
// 构建render函数生成html
if (this.$render === noop) {
this.$render = Moon.compile(this.$template);
}
};
// 在全局对象components中注册
components[name] = {
CTor: MoonComponent,
opts: opts
};
return MoonComponent;
};
从上面可以看出,如下几点:
- Moon.component实际上内部还是调用Moon构造函数
- Moon.component内部继承了Moon.prototype
- Moon.component内部重写了init方法
事件分发机制
Moon中也定义了Vue.js中事件分发机制(组件通信方式):on、off、emit,下面就具体来分析下它们内部的实现思想:
- on
// 事件注册
Moon.prototype.on = function (eventName, handler) {
var handlers = this.$events[eventName];
// 从处理逻辑可知支持多个回调函数
if (handlers === undefined) {
this.$events[eventName] = [handler];
} else {
handlers.push(handler);
}
};
- emit
// 使用形式:Moon实例.emit(事件名,参数对象)
Moon.prototype.emit = function (eventName, customMeta) {
var meta = customMeta || {};
meta.type = eventName;
// 获取指定事件的处理的回调函数
var handlers = this.$events[eventName];
var globalHandlers = this.$events["*"];
// 回调函数调用
for (var i = 0; i < handlers.length; i++) {
handlers[i](meta);
}
// 所有事件的回调函数
if (globalHandlers !== undefined) {
for (var i = 0; i < globalHandlers.length; i++) {
globalHandlers[i](meta);
}
}
};
- off
Moon.prototype.off = function (eventName, handler) {
// 支持off()、off(事件)等3种形式
if (eventName === undefined) {
this.$events = {};
} else if (handler === undefined) {
this.$events[eventName] = [];
} else {
var handlers = this.$events[eventName];
var index = handlers.indexOf(handler);
handlers.splice(index, 1);
}
};
总结
Moon是非常值得一读的开源框架,它实现了类似Vue.js的功能,可以将其看成Vue.js的简化版,需要注意的是Moon的双向绑定与Vue.js实现的双向绑定还是存在一定区别。
之后的文章的大概顺序是:
- 虚拟DOM相关
- 指令以及slot相关
- monx相关
- moon-router相关
- moon-cli相关
- moon项目(moon-cli + monx+moon-router)整体分析