vue 中directive功能的简单实现

2020-06-16 06:06:39易采站长站整理

directives: [] // 与该数据相关的指令
};
}
directive.el = el;
binding.directives.push(directive);
if (!seed.scope.hasOwnProperty(key)) {
bindAccessors(seed, key, binding);
}
}
/**
* 重写scope西乡属性的getter和setter
* @param {Seed} seed Seed实例
* @param {String} key 对象属性即opts.scope中的属性
* @param {Object} binding 数据绑定关系对象
*/
function bindAccessors(seed, key, binding) {
Object.defineProperty(seed.scope, key, {
get: function() {
return binding.value;
},
set: function(value) {
binding.value = value;
// 触发directive
binding.directives.forEach((directive) => {
// 如果有过滤器则先执行过滤器
if (typeof value !== 'undefined' && directive.filters) {
value = applyFilters(value, directive);
}
// 调用update方法
directive.update(directive.el, value, directive.argument, directive);
});
}
});
}
/**
* 调用filters依次处理value
* @param {任意类型} value 数据值
* @param {Object} directive 解析出来的指令对象
*/
function applyFilters(value, directive) {
if (directive.definition.customFilter) {
return directive.definition.customFilter(value, directive.filters);
} else {
directive.filters.forEach((name) => {
if (Filters[name]) {
value = Filters[name](value);
}
});
return value;
}
}

其中的bindings存放了数据和指令的关系,该对象中的key为opts.scope中的属性,value为Object,如下:


{
"msg": {
"value": undefined,
"directives": [] // 上面介绍的directive对象
}
}

数据与directive建立好关系之后, bindAccessors 中为seed的scope对象的属性重新定义了getter和setter,其中setter会调用指令update方法,到此就已经完事具备了。

Seed构造函数在实例化的最后会迭代bindings中的key,然后从opts.scope找到对应的value, 赋值给了scope对象,此时setter中的update就触发执行了。

下面再看一下 sd-on 指令的定义:


{
on: {
update: function(el, handler, event, directive) {
if (!directive.handlers) {
directive.handlers = {};
}
const handlers = directive.handlers;
if (handlers[event]) {
el.removeEventListener(event, handlers[event]);
}
if (handler) {
handler = handler.bind(el);
el.addEventListener(event, handler);
handlers[event] = handler;
}
},
customFilter: function(handler, selectors) {
return function(e) {
const match = selectors.every((selector) => e.target.matches(selector));
if (match) {