-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwatch.js
More file actions
134 lines (126 loc) · 3.73 KB
/
watch.js
File metadata and controls
134 lines (126 loc) · 3.73 KB
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
import AngularController from './AngularController'
import {todo} from './_common'
function $watch (...args) {
const options = args.pop()
const expressions = args
let immediate = false
let strict = false
let deep = false
let callback
if (typeof options === 'function') {
callback = options.bind(this)
} else {
callback = options.callback.bind(this)
immediate = Boolean(options.immediate)
strict = Boolean(options.strict)
deep = Boolean(options.deep)
}
if (!immediate) {
const originCallback = callback
let isFirst = true
callback = function (...args) {
if (isFirst) {
isFirst = false
return
}
originCallback(...args)
}
}
const scope = this.$scope
if (expressions.length > 1) {
return scope.$watchGroup(expressions, callback)
}
const [expression] = expressions
if (deep) {
return scope.$watchCollection(expression, callback)
} else {
return scope.$watch(expression, callback, strict)
}
}
function _makeComputed (target, getter, sync) {
let value
const evaluate = () => {
value = getter.call(target)
}
if (sync) {
return function commputed () {
if (arguments.length === 0) {
return value
}
evaluate()
}
}
let dirty = true
return function commputed () {
if (arguments.length === 0) {
if (dirty) {
evaluate()
dirty = false
}
return value
}
dirty = true
}
}
function watch (...expressions) {
let immediate = false
let strict = false
let deep = false
let sync = false
return function doWatch (methodDescriptor) {
const lastArg = expressions[expressions.length - 1] || false
if (typeof lastArg === 'boolean') {
immediate = lastArg
expressions.pop()
} else if (typeof lastArg === 'object' && lastArg !== null) {
immediate = Boolean(lastArg.immediate)
strict = Boolean(lastArg.strict)
deep = Boolean(lastArg.deep)
sync = Boolean(lastArg.sync)
expressions.pop()
}
const {descriptor, key} = methodDescriptor
let afterWatch
if (descriptor.hasOwnProperty('value')) {
afterWatch = function watch () {
this.$watch(...expressions, {
callback: descriptor.value,
immediate,
strict,
deep
})
}
} else {
afterWatch = function commpute () {
const {get: getter, set: setter} = descriptor
const commputed = _makeComputed(this, getter, sync)
this.$watch(...expressions, {
callback: commputed,
immediate: true,
strict,
deep
})
const scope = this.$scope
if (scope.hasOwnProperty(key)) {
return
}
Object.defineProperty(scope, key, {
get: commputed,
set: setter ? setter.bind(this) : undefined,
enumerable: true,
configurable: true
})
}
descriptor.configurable = false
}
return {
...methodDescriptor,
finisher (Controller) {
todo(Controller, afterWatch)
}
}
}
}
AngularController.prototype.$watch = $watch
AngularController.watch = watch
export default watch