forked from xlzy520/wx-qq-music
-
Notifications
You must be signed in to change notification settings - Fork 0
/
watch.js
135 lines (110 loc) · 2.97 KB
/
watch.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
class Watch{
constructor(context){
this.page = context;
this.observers = new Map(); //观察者队列
this.init(); //将watch数据写入观察者队列
}
/**
** 初始化观察队列,将已订阅的
**/
init(){
const that = this;
Object.keys(this.page.watch).forEach((key) => {
if(that.isSet(that.page.data, key)){
that.subscribe(key, that.page.watch[key]);
}
})
}
/**
** 只改变数据,不更新视图
**/
data(key, val){
if(this.isSet(this.page.data, key)){
this.setter(key, val);
}
}
/**
** 模拟小程序原生setData方法,改变更新视图前推送订阅事件
**/
setData(obj){
const that = this;
Object.keys(obj).forEach((key) => {
that.notify(key, that.page, obj[key], that.getter(that.page.data, key))
// if(that.observers.has(key)){
// that.observers.get(key).apply(that.page, [obj[key], that.getter(that.page.data, key)]);
// }
})
this.page.setData(obj);
}
/**
** 发布订阅事件
**/
notify(key, ctx, val, oldVal) {
if(this.observers.has(key)){
this.observers.get(key).apply(ctx, [val, oldVal]);
}
}
/**
** 获取所有的观察者对象
**/
getObs() {
return this.observers;
}
/**
** 添加观察者
**/
subscribe(key, cb){
if(this.observers.has(key)) this.observers.delete(key);
this.observers.set(key, cb);
}
/**
** 删除观察者
**/
unSubscribe(key){
if(this.observers.has(key)) this.observers.delete(key);
}
/**
** 根据路径设置data值
**/
setter(path, val) {
if(!path || !this.isSet(this.page.data, path)) return undefined;
const REG_KEY = /\[(['"a-zA-Z0-9]*)\]|\./gi;
const pathArr = path.split(REG_KEY).filter(item => !!item);
let depDataNote = [];
let oldVal;
pathArr.reduce((result, currentPath, currentIndex) => {
if(currentIndex === pathArr.length - 1){
oldVal = result[currentPath];
result[currentPath] = val
}
depDataNote.push({
key: currentPath,
value: result[currentPath]
})
return result[currentPath];
}, this.page.data)
this.page.data[pathArr[0]] = depDataNote[0].value;
this.notify(path, this.page, val, oldVal);
// console.log(this.path.data);
return oldVal === undefined ? undefined : val;
}
/**
** 根据路径获取data值
**/
getter(data, path) {
const REG_KEY = /\[(['"a-zA-Z0-9]*)\]|\./gi;
const pathArr = path.split(REG_KEY).filter(item => !!item);
const result = pathArr.reduce((result, currentPath, currentIndex) => {
const currentValueType = Object.prototype.toString.call(result);
return /String|Number|Boolean|Null|Undefined/.test(currentValueType) ? undefined : result[currentPath]
}, data)
return result;
}
/**
** 检查target[key]是否存在
**/
isSet(target, key) {
return this.getter(target, key) !== undefined ? true : false;
}
}
export default Watch;