-
Notifications
You must be signed in to change notification settings - Fork 9
/
index.js
95 lines (82 loc) · 2.36 KB
/
index.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
import { create } from 'evx'
const isObj = v => typeof v === 'object' && !Array.isArray(v)
const isFn = v => typeof v === 'function'
// make sure evx and picoapp don't destroy the same events
export function component (create) {
return function initialize (node, ctx) {
let subs = []
return {
subs,
unmount: create(node, {
...ctx,
on: (evs, fn) => {
const u = ctx.on(evs, fn)
subs.push(u)
return u
}
}),
node
}
}
}
export function picoapp (components = {}, initialState = {}, plugins = []) {
const evx = create(initialState)
let cache = []
return {
on: evx.on,
emit: evx.emit,
getState () {
return evx.getState()
},
add (index) {
if (!isObj(index)) throw 'components should be an object'
Object.assign(components, index)
},
use (fn) {
if (!isFn(fn)) throw 'plugins should be a function'
plugins.push(fn);
},
hydrate (data) {
return evx.hydrate(data)
},
mount (attrs = 'data-component') {
attrs = [].concat(attrs)
for (let a = 0; a < attrs.length; a++) {
const attr = attrs[a]
const nodes = [].slice.call(document.querySelectorAll('[' + attr + ']'))
while (nodes.length) {
const node = nodes.pop()
const modules = node.getAttribute(attr).split(/\s/)
for (let m = 0; m < modules.length; m++) {
const comp = components[modules[m]]
if (comp) {
node.removeAttribute(attr) // so can't be bound twice
try {
const ext = plugins.reduce((res, fn) => {
const obj = fn(node, evx)
return isObj(obj) ? Object.assign(res, obj) : res
}, {})
const instance = comp(node, {...ext, ...evx})
isFn(instance.unmount) && cache.push(instance)
} catch (e) {
console.error(e)
evx.emit('error', {error: e})
evx.hydrate({ error: undefined })
}
}
}
}
evx.emit('mount')
}
},
unmount () {
for (let i = cache.length - 1; i > -1; i--) {
const { unmount, node, subs } = cache[i]
unmount(node)
subs.map(u => u())
cache.splice(i, 1)
}
evx.emit('unmount')
}
}
}