335 lines
10 KiB
JavaScript
Executable File
335 lines
10 KiB
JavaScript
Executable File
layui.define([], function (exports) {
|
|
const MOD_NAME = "react";
|
|
|
|
// 监听数据,后面可以用一个WeakMap + 存放key的数组替换
|
|
let proxyData = {
|
|
data: [], // 数据
|
|
methods: [], // 方法
|
|
hooks: [], // 钩子
|
|
};
|
|
|
|
let react = {
|
|
/**
|
|
* @abstract 通知并执行钩子函数
|
|
*
|
|
* @param {String} hook 监听的变量名
|
|
* @param {'pre'|'post'} type 类型
|
|
* @param {...any} args
|
|
*/
|
|
notifyHooks: (hook, type = 'pre', ...args) => {
|
|
for (const f of proxyData.hooks.filter(v => {
|
|
return v.target === hook && v.type === type;
|
|
})) {
|
|
f.handler(args);
|
|
}
|
|
},
|
|
/**
|
|
* @abstract 注册一些钩子,当托管变量发生改变时触发
|
|
*
|
|
* 注册钩子:
|
|
* @example
|
|
* ```javascript
|
|
* // 注册托管变量
|
|
* laytp.react.regData({
|
|
* hello: 0,
|
|
* world: 2
|
|
* });
|
|
*
|
|
* // 注册钩子
|
|
* laytp.react.regHooks({
|
|
* // 监听名为hello的变量改变
|
|
* hello: () => {
|
|
* console.log('Here!');
|
|
* },
|
|
*
|
|
* world: {
|
|
* type: 'post', // 默认都为'pre',为变量修改前回调,'post'为变量修改后回调
|
|
* handler: (target, prop, data) => {
|
|
* data.value = 50;
|
|
* }
|
|
* }
|
|
* });
|
|
* ```
|
|
*
|
|
* 调用:
|
|
* @example
|
|
* ```javascript
|
|
* laytp.data.hello = 10;
|
|
* // laytp.data.hello -> 10
|
|
*
|
|
* laytp.data.world = 20;
|
|
* // laytp.data.world -> 50
|
|
* ```
|
|
*
|
|
* @param {Object} obj 需注册的钩子的Object
|
|
* @returns
|
|
*/
|
|
regHooks: function (obj) {
|
|
if (typeof obj !== 'function' && typeof obj !== 'object') {
|
|
console.error('请传入钩子对象或一个具名函数');
|
|
return;
|
|
}
|
|
|
|
if (typeof obj === 'function') {
|
|
if (obj.name === '') {
|
|
console.error('不支持传入闭包');
|
|
return;
|
|
}
|
|
|
|
proxyData.hooks.push({
|
|
target: obj.name,
|
|
type: 'pre',
|
|
handler: obj
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
for (const key in obj) {
|
|
if (Object.hasOwnProperty.call(obj, key)) {
|
|
const func = obj[key];
|
|
|
|
if (typeof func === 'object' && typeof func.type === 'string' && typeof func.handler === 'function')
|
|
proxyData.hooks.push({
|
|
target: key,
|
|
type: func.type,
|
|
handler: func.handler
|
|
});
|
|
else if (typeof func === 'function')
|
|
proxyData.hooks.push({
|
|
target: key,
|
|
type: 'pre',
|
|
handler: func
|
|
});
|
|
else
|
|
console.warn(`${key} 不是一个合法的钩子`);
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* @abstract 注册一些托管方法
|
|
*
|
|
* 注册:
|
|
* @example
|
|
* ```javascript
|
|
* laytp.react.regMethods({
|
|
* alert() {
|
|
* alert('warning');
|
|
* }
|
|
* });
|
|
* ```
|
|
*
|
|
* 调用:
|
|
* @example
|
|
* ```javascript
|
|
* laytp.methods.alert();
|
|
* ```
|
|
*
|
|
* @param {Object} obj 需注册的方法的Object
|
|
* @returns
|
|
*/
|
|
regMethods: function (obj) {
|
|
if (typeof obj === 'function') {
|
|
if (obj.name === '') {
|
|
console.error('不支持传入闭包');
|
|
return;
|
|
}
|
|
|
|
if (proxyData.methods.findIndex(v => { return v.key === key; }) > -1) {
|
|
proxyData.methods.find(v => { return v.key === key }).handler = func;
|
|
return;
|
|
}
|
|
|
|
proxyData.methods.push({
|
|
key: obj.name,
|
|
handler: func
|
|
});
|
|
|
|
Object.defineProperty(laytp.methods, `${obj.name}`, {
|
|
get() {
|
|
let q = proxyData.methods.find(v => {
|
|
return v.key === obj.name;
|
|
});
|
|
return q === undefined ? undefined : q.handler;
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
for (const key in obj) {
|
|
if (Object.hasOwnProperty.call(obj, key)) {
|
|
const func = obj[key];
|
|
|
|
if (typeof func !== 'function') {
|
|
console.warn(`${key} 不是一个合法的函数`);
|
|
continue;
|
|
}
|
|
|
|
if (proxyData.methods.findIndex(v => { return v.key === key; }) > -1) {
|
|
proxyData.methods.find(v => { return v.key === key }).handler = func;
|
|
continue;
|
|
}
|
|
|
|
proxyData.methods.push({
|
|
key,
|
|
handler: func
|
|
});
|
|
|
|
Object.defineProperty(react.methods, `${key}`, {
|
|
get() {
|
|
let q = proxyData.methods.find(v => {
|
|
return v.key === key;
|
|
});
|
|
return q === undefined ? undefined : q.handler;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @abstract 注册一些托管数据,当托管数据发生变化时调用同名钩子函数,暂不支持深度监听
|
|
*
|
|
* 注册:
|
|
* @example
|
|
* ```javascript
|
|
* laytp.react.regData({
|
|
* some: 1,
|
|
* other: 10,
|
|
* meow: "I'm hungry"
|
|
* });
|
|
* ```
|
|
*
|
|
* 调用:
|
|
* @example
|
|
* ```javascript
|
|
* laytp.data.some = 10;
|
|
* laytp.data.other = 'Ok';
|
|
* ```
|
|
*
|
|
* @param {Object} obj 需注册的数据的Object
|
|
* @returns
|
|
*/
|
|
regData: function (obj) {
|
|
if (typeof obj !== 'object') {
|
|
console.error('请传入数据对象');
|
|
return;
|
|
}
|
|
|
|
const handler = {
|
|
setByOutside(hooks, target, prop, value) {
|
|
for (const h of hooks) {
|
|
let data = {
|
|
get value() {
|
|
return value;
|
|
},
|
|
|
|
set value(v) {
|
|
value = v;
|
|
}
|
|
};
|
|
|
|
h.handler(target, prop, data);
|
|
target[prop] = value;
|
|
}
|
|
},
|
|
|
|
set(target, prop, value) {
|
|
// 写入前钩子
|
|
try {
|
|
handler.setByOutside(proxyData.hooks.filter(o => {
|
|
return o.target === target.key && o.type === 'pre';
|
|
}), target, prop, value);
|
|
} catch (error) {
|
|
console.error(error);
|
|
return;
|
|
}
|
|
|
|
// 写入
|
|
target[prop] = value;
|
|
|
|
// 写入后钩子
|
|
try {
|
|
handler.setByOutside(proxyData.hooks.filter(o => {
|
|
return o.target === target.key && o.type === 'post';
|
|
}), target, prop, value);
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
},
|
|
|
|
get(target, prop) {
|
|
return target[prop];
|
|
}
|
|
};
|
|
|
|
for (const key in obj) {
|
|
if (Object.hasOwnProperty.call(obj, key)) {
|
|
const element = obj[key];
|
|
|
|
if (proxyData.data.findIndex(v => { return v.key === key }) > -1) {
|
|
proxyData.data.find(v => { return v.key === key }).value = element;
|
|
continue;
|
|
}
|
|
|
|
proxyData.data.push(new Proxy({
|
|
key,
|
|
value: element
|
|
}, handler));
|
|
|
|
Object.defineProperty(react.data, `${key}`, {
|
|
get() {
|
|
let q = proxyData.data.find(v => {
|
|
return v.key === key;
|
|
});
|
|
return q === undefined ? undefined : q.value;
|
|
},
|
|
|
|
set(v) {
|
|
let q = proxyData.data.find(v => {
|
|
return v.key === key;
|
|
});
|
|
(q) && (q.value = v);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
},
|
|
data: new Proxy({}, {
|
|
set(target, p, newVal) {
|
|
react.regData({
|
|
[p]: newVal
|
|
});
|
|
},
|
|
|
|
get(target, p) {
|
|
return target[p];
|
|
}
|
|
}),
|
|
methods: new Proxy({}, {
|
|
set(target, p, newVal) {
|
|
react.regMethods({
|
|
[p]: newVal
|
|
});
|
|
},
|
|
|
|
get(target, p) {
|
|
return target[p];
|
|
}
|
|
}),
|
|
hooks: new Proxy({}, {
|
|
set(target, p, newVal) {
|
|
react.regHooks({
|
|
[p]: newVal
|
|
});
|
|
},
|
|
|
|
get(target, p) {
|
|
return target[p];
|
|
}
|
|
})
|
|
};
|
|
|
|
//输出模块
|
|
exports(MOD_NAME, react);
|
|
}); |