代码功能更新
This commit is contained in:
+335
@@ -0,0 +1,335 @@
|
||||
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);
|
||||
});
|
||||
Reference in New Issue
Block a user