事实上如果组件里 data
直接写了一个对象的话,那么如果你在模板中多次声明这个组件,组件中的 data
会指向同一个引用。
# 那么为什么会这样呢?
举个栗子:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>demo4</title>
<script src="../lib/vue.js"></script>
</head>
<body>
<div id="app">
<counter id="a"></counter>
<counter id="b"></counter>
</div>
<script>
var Counter = {
template: `<span @click="count++">{{ count }}</span>`,
data: {
count: 0
}
// data: function () {
// return {
// count: 0
// }
// }
}
const curVue = new Vue({
components: {
Counter,
},
data: {
},
methods: {
},
}).$mount('#app')
console.log(curVue)
console.log(curVue.$options.render.toString())
</script>
</body>
</html>
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
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
点击 counter
的时,两个组件的数字会变成一样,这无疑证实了,上述的判断是正确的,这两个组件的 data
使用的是同一个索引,其实在 vue
的内部会检测组件内部的 data
是不是 function
,如果不是,会直接报错的。如下,
strats.data = function ( parentVal, childVal, vm ) {
if (!vm) {
if (childVal && typeof childVal !== 'function') {
warn(
'The "data" option should be a function ' +
'that returns a per-instance value in component ' +
'definitions.',
vm
);
return parentVal
}
return mergeDataOrFn(parentVal, childVal)
}
return mergeDataOrFn(parentVal, childVal, vm)
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
在 meger 数据时,如果不是函数的话, merge 的就是一个对象,从而总成组件内部使用的是同一个对象索引。
typeof childVal === 'function' ? childVal.call(this, this) : childVal
1