-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathprops.js
More file actions
133 lines (107 loc) · 3.04 KB
/
props.js
File metadata and controls
133 lines (107 loc) · 3.04 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
/**
* diffProps
* @param {*} dom 当前虚拟dom对应的真实dom节点
* @param {*} newProps 新虚拟dom节点的props属性
* @param {*} oldProps 旧虚拟dom节点的props属性
*/
export function diffProps(dom, newProps, oldProps) {
let i
// 添加属性
for (i in newProps) {
if (
i !== 'children' &&
i !== 'key' &&
i !== 'ref' &&
oldProps[i] !== newProps[i]
) {
setProperty(dom, i, newProps[i], oldProps[i])
}
}
}
/**
* setProperty
* @param {*} dom 当前虚拟dom对应的真实dom节点
* @param {*} name 属性名
* @param {*} newValue 要设置成的值
* @param {*} oldValue 旧值
*/
function setProperty(dom, name, newValue, oldValue) {
// 如果新值旧值一致,不处理
if (newValue === oldValue) return
// 处理 className
if(name === 'className'){
if(newValue != oldValue){
dom.className = newValue
}
}
// 处理style
else if (name === 'style') {
setStyle(...arguments)
}
// 处理事件
else if (name[0] === 'o' && name[1] === 'n') {
setEventListener(...arguments)
}
// 处理其它属性
else {
if (oldValue && !newValue) {
dom.removeAttribute(name)
} else if (!oldValue && newValue || newValue !== oldValue) {
dom.setAttribute(name, newValue)
}
}
}
/**
* 设置样式
* @param {*} dom 当前虚拟dom对应的真实dom节点
* @param {*} name 属性名
* @param {*} newValue 要设置成的值
* @param {*} oldValue 旧值
*/
function setStyle(dom, name, newValue, oldValue) {
let isSame = true
let cssText = '', attribute, value
for (attribute in newValue) {
value = newValue[attribute]
// 判断是否相同
if (!oldValue || newValue[attribute] != oldValue[attribute]) {
isSame = false
}
// 把驼峰转化成 - 连接
attribute = attribute.replace(/[A-Z]/g, s => `-${s.toLocaleLowerCase()}`)
// 连接在一起
cssText += `${attribute}: ${value};`
}
// 设置样式
isSame || (dom.style.cssText = cssText)
}
/**
* 设置事件
* @param {*} dom 当前虚拟dom对应的真实dom节点
* @param {*} name 属性名
* @param {*} newValue 要设置成的值
* @param {*} oldValue 旧值
*/
function setEventListener(dom, name, newValue, oldValue) {
// 判断是否是捕获阶段
const useCapture = name !== (name = name.replace('Capture', ''))
// 转化成小写
name = name.slice(2).toLocaleLowerCase()
// 给dom上添加一个_listeners属性
if (!dom._listeners) dom._listeners = {}
// 直接把当前的事件存储到 _listeners 中
dom._listeners[name + (useCapture ? 'Capture' : '')] = newValue
// 判断事件绑定
const handler = useCapture ? eventProxyCapture : eventProxy
if (newValue && !oldValue) {
dom.addEventListener(name, handler, useCapture)
} else if (!newValue && oldValue) {
dom.removeEventListener(name, handler, useCapture)
}
}
function eventProxy(e) {
this._listeners[e.type](e)
}
function eventProxyCapture(e) {
this._listeners[e.type + 'Capture'](e)
}