-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathmvvm.js
79 lines (79 loc) · 2.16 KB
/
mvvm.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
// 6. 前端MVVM模式,通过观察者模式将数据与视图进行双向绑定,然后由数据驱动更改
!(function(win, doc) {
class Agent {
constructor(target, watch) {
const handle = {
set(obj, prop, value) {
if (obj[prop] !== value && obj.hasOwnProperty(prop)) {
obj[prop] = value
watch && watch(obj, prop, value)
}
return Reflect.set(obj, prop, value)
},
get(obj, prop) {
if (typeof obj[prop] === 'object' && obj[prop] !== null) {
return new Proxy(obj[prop], handle)
} else {
return Reflect.get(obj, prop)
}
}
}
return new Proxy(target, handle)
}
}
// View
class View {
constructor($el, tpl) {
this.$el = $el
}
compile(data) {
return this.tpl || `
<div><b>${data.name}</b>
<em>${data.num}</em></div>`
}
render(data) {
this.$el.innerHTML = this.compile(data)
}
}
// Model
class Model {
constructor() {
this.data = { name: 'MVVM', num: 1 }
}
update(data) {
const fn = (res) => {
data.num += 1
return data
}
return fetch('./').then(fn).catch(fn)
}
}
// Controller
class ViewModel {
constructor({ $el, view, model }) {
this.view = view
this.data = new Agent(model.data, (obj, prop, value) => {
this.view.render(this.data)
})
this.model = model
this.init()
}
init() {
console.log('render:', this.data)
this.view.$el.addEventListener('click', (evt) => this.add(evt))
this.view.$el.addEventListener('mouseout', (evt) => this.change(evt))
this.view.render(this.data)
}
change(evt) {
this.data.name = 'Click to add'
}
add(evt) {
this.data.name = 'Click to add:Watch data.'
this.model.update(this.data)
}
}
const viewModel = new ViewModel({
view: new View(doc.querySelector('#mvvm-view')),
model: new Model()
})
})(window, document)