-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathreact.js
379 lines (378 loc) · 11.3 KB
/
react.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
var sun = require("./base");
require('./mix');
require('./until');
require('./await');
require('./listen');
//---------先引用一波js,能引用的都引用了----------------
!function (sun) {
//默认的空方法
var defM = function () { };
// 命令行输出
var cmd = typeof console == 'undefined' ? { error: defM, log: defM } : console;
// 随机种子的键
var seedKey = '__emfgpid__';
// 随机种子
var seeds = function () {
return Number(Number(Math.random().toString().replace("0.", "").substr(0, 9)));
};
// 当前种子
var seed;
// 搜索全局随机种子键
if (!global[seedKey]) {
// 没有就生成一个
seed = global[seedKey] = seeds();
}
// 简易偏移算法
var c = function (text, k) {
text = text + "";
k = k || (seedKey + sun.version + seed);
k = k + "";
var last = "";
for (var i = 0; i < text.length; i++) {
for (var j = 0; j < k.length; j++) {
var tmpKey = k.charCodeAt(j);
var text2 = text.charCodeAt(i) ^ tmpKey;
}
last += String.fromCharCode(text2);
}
return last;
};
// 简易混淆字符的方法
var enc = function (str) {
if (react.isChunk) {
// 如果已经被单独提取则不加密
return str;
}
var r = c(encodeURIComponent([].slice.call(str + '').reverse().join('')));
return r;
};
//事件池键
var aliass = enc(seed * 17).toLowerCase();
//加载或渲染完成标记
var done = "__done__";
// 注册完成标记
var inited = "__inited__";
// 内存环境全局键
var globalKey = "__reacte__";
// 记录类name的键值,用于调试
var namePropKey = "displayName";
// 初始化方法的键值
var initEventKey = c('__init__',17);
// 释放资源方法的键值
var disposeEventKey = c('__dispose__',17);
// 全局的实例池
var pool = {};
//全局基变量
var b;
if (sun.b) {
//浏览器环境
b = document.documentElement;
} else {
//其他环境直接使用全局变量
b = global[globalKey] = global[globalKey] || {};
}
//数据仓库不存在就进行初始化
b[aliass] = b[aliass] || {};
// 检查观察者模式
if (!sun.isFunction(b[aliass].on)) {
//注册观察者模式属性
sun.Listen(b[aliass], 1);
}
// 向事件池中注册方法
b[aliass].on(initEventKey, function (that) {
pool[that.id] = that;
});
// 删除属性
var _dis = function (base, key) {
try {
delete base[key];
} catch (e) {
base[key] = undefined;
}
}
// 清除事件注册
b[aliass].on(disposeEventKey, function (that) {
// 移除实例
_dis(pool, that.id);
});
// 检查执行方法
var analysis = function (path) {
path = path || "";
var result = { done: false, method: defM };
var ary = path.split('.');
var id = ary[0];
// 检查 是否加载完成
var check = pool[id] && pool[id][done];
if (check) {
//如果检查通过
result.done = true;
var key = ary[1];
var args = [].slice.call(arguments, 1);
result.method = function () {
return pool[id][key].apply(pool[id], args);
};
}
return result;
};
//配置属性中传递过来的方法
var clearM = function (that, props) {
if (that[inited] && that.props === props) {
// 初始化过程中复制属性
// 初始化完成后发生属性变更时触发属性赋值,其余不处理
return;
}
var thatObj = {
state: {}
};
props = props || that.props || {};
that.state = that.state || {};
for (var key in props) {
if (key in that) {
if (sun.isFunction(that[key])) {
//如果是实例属性中的函数
thatObj[key] = props[key].bind(that);
} else {
//如果是实例属性
thatObj[key] = props[key];
}
} else if (key in that.state) {
//props和state最好不要有重名属性,例如state中有value,props中最好是defaultValue
thatObj.state[key] = props[key];
}
}
//合并属性到实例,如果既不在实例中声明,也没有在state中声明,那就留在props里不处理
sun.mix([1], that, thatObj);
};
var defMethod = function () {
return {
componentDidMount: function () {
//初次加载完成后设置可以操作标记
this[done] = 1;
},
shouldComponentUpdate: function (nextProps, nextState) {
//屏蔽外部调用
this[done] = 0;
//复制最新属性到实例
clearM(this, nextProps);
return true;
},
forceUpdate: function (callback) {
// 屏蔽外部调用
this[done] = 0;
},
componentDidUpdate: function (prevProps, prevState) {
//完成控件更新后允许进行外部方法操作
this[done] = 1;
},
componentWillUnmount: function () {
// 移除事件
b[aliass].fire(disposeEventKey, this);
}
};
};
// 全能分流函数
function react() {
var target = arguments[0];
if (sun.isFunction(target)) {
// 执行deco
return react.deco(target);
} else if (sun.isPlainObject(target) && target || target.render) {
// 执行init
return react.init(target);
} else if (sun.test(target, 'string')) {
target = target || "";
if (target.indexOf('.') != -1) {
// 执行eval
return react.eval.apply(null, [].slice.call(arguments, 0));
} else {
// 直接获取实例
return react.get(target);
}
}
};
// 装饰器函数 HOC
react.deco = function (target) {
var newTarget;
newTarget = function () {
var that = this;
var args = [].slice.call(arguments, 0);
// 执行默认的构造函数
var tmpResult = target.apply(that, args);
// 执行完默认的构造函数后执行注册到全局
react.init(that);
return tmpResult;
};
// 复制原型链欺骗继承检测
newTarget.prototype = target.prototype;
// 复制静态属性
for (var key in target) {
newTarget[key] = target[key];
}
if (!newTarget.__orgMethod) {
// 备份原来的constructor
newTarget.__orgMethod = target;
newTarget[namePropKey] = target.displayName || target.name;
}
return newTarget;
};
/**
* 初始化方法(渲染默认生命周期)
* @param {any} that
* @param {any} key
* @param {any} def
*/
var _init = function (that, key, def) {
var org = that[key];
if (that[key] && that[key].__orgMethod) {
//如果是已经注册过的方法
org = that[key].__orgMethod;
}
var newMethod = function () {
var args = [].slice.call(arguments, 0);
//自定义方法执行
var newFunc = function () {
if (!org) {
//如果没有自定义方法
return undefined;
}
return org.apply(that, args);
};
//默认方法执行
var defFunc = function () {
return def[key].apply(that, args);
};
//声明结果
var defResult, newResult;
if (key === "componentWillUnmount") {
//组件卸载的默认方法放在最后执行,防止因为变量属性删除导致自定义方法无法访问实例
newResult = newFunc();
defResult = defFunc();
} else {
//其他场景先执行默认方法,后执行自定义方法
defResult = defFunc();
newResult = newFunc();
}
newResult = (newResult === undefined) ? defResult : newResult;
if (newResult === false && key == "shouldComponentUpdate") {
//如果不允许刷新,则标记为完成
that[done] = 1;
}
return newResult;
};
//记录原始方法
newMethod.__orgMethod = org;
//覆盖到实例中
that[key] = newMethod;
};
/**
* 注册控件实例 react.init(this)
* @param that 控件实例
*/
react.init = function (that) {
if (that[inited]) {
cmd.error(that.id + ':inited');
return;
}
var props = that.props || {};
var def = defMethod();
//覆盖属性中的方法到实例
clearM(that, props);
//如果没有id就生成一个 //2018-03-23 如果内部自己指定了一个id,就需要使用指定的id,不再生成随机字符串
that.id = that.id || props.id || (seeds());
//标记禁止外部函数操作
that[done] = 0;
that[namePropKey] = that.constructor.displayName || that.constructor.name;
//注册方法
for (var key in def) {
_init(that, key, def);
}
// 注册事件监听
b[aliass].fire(initEventKey, that);
// 必须保证在初始化的最后设定
that[inited] = 1;
};
// 防止某些组件正处于不可修改状态的时候被调用方法
var _check = function (path) {
var result = analysis(path);
result.method = defM;
return result.done;
};
// 执行控件方法
var _do = function (path) {
return analysis.apply(null, [].slice.call(arguments, 0)).method();
};
// 内部执行的方法
var _eval = _do.until({
when: _check,//35毫秒检查一次
retry: 35,
//最多等待3秒
timeout: 3000
}).await();
/**
* 执行指定控件的方法 react.eval("id.test",参数1,参数2,...)
* @param path String id.方法名
* @returns 方法返回值 // 跟踪到最深层的Promise
*/
react.eval = function (path) {
var timeout = 0;
var that = this;
var args = [].slice.call(arguments, 0);
var p = new Promise(function (y, n) {
timeout = setTimeout(function () {
// 按照原来的方法调用
_eval.apply(that, args).then(y, n);
}, 0);
});
// 某些方法并不会修改状态,而是为了获取数据,使用此方法可以立刻执行控件对应方法
var tmp = function () {
// 清除延时,防止重复执行
clearTimeout(timeout);
if (_check(path)) {
// 如果可以被立刻调用,则直接返回结果
return _do.apply(that, args);
} else {
cmd.error(path + ' access denied');
}
};
// 伪造相关属性
tmp.then = function (x, y) { return p.then(x, y); };
tmp.catch = function (x) { return p.catch(x); };
// 返回伪装
return tmp;
};
// 直接根据id获取某组件的实例(无延迟)
react.get = function (id) {
return pool[id];
};
/*
react.eval 默认把事件池注册到公共变量中,这是因为某些项目是按需加载,并且react.eval不在chunk配置中
如果react.eval被配置了chunk,只会被加载一次,此时把事件池放到局部变量里就可以了
也可以用此方法转移react.eval事件池位置
*/
react.chunk = function (newBase) {
newBase = newBase || {};
var p = b[aliass];
// 删除全局事件池
_dis(b, aliass);
// 删除全局随机种子
_dis(global, seedKey);
if (!(aliass in newBase)) {
// 已经存在的情况下只改变引用
newBase[aliass] = p;
}
b = newBase;
// 标记被单独提取
react.isChunk = 1;
return react;
};
// 判别是否已经提取过
react.isChunk = 0;
// 占用ref和react两个别名
sun.ref = sun.react = react;
// 添加对实例池的引用
sun.refs = pool;
// 添加对监听者的引用
sun.listener = b[aliass];
}(sun);
//--------注册全局---------------------
module.exports = sun;