今天学习vue组件的时候,发现组件里面的东西,其实和定义的root实例里面的东西时一样的,除了data。这个data必须是function类型,而且必须返回一个实例对象的值,里面的值就是定义的data。这是为什么呢下面举一个小例子来类比一下
正确的定义一个组件:
//定义组件
<template id="cpn">
<div>
<h2>我是{
{
name}}</h2>
</div>
</template>
//使用组件
<div class="app">
<cpn-text></cpn-text>
</div>
//注册组件
const appbox = new Vue({
el:".app",
data:{
msg:'haha'
},
components:{
cpnText:{
template:'#cpn',
data(){
return {
name:'小小的一个组件'
}
}
}
}
})
效果:
但是如果将组件的data写成:
data:{
name:'小小的一个组件'
}
会报这样的错误:
分析
如果data允许这么写,那么就像所有复用这个组件的地方,都在使用这个组件里面的唯一一个data,所有使用组件的地方的data都会指向栈内这一个data的地址,那么会造成一个改data的值,所有的data都会改,因为vue中如果直接写成像root实例当中data那样会直接报错,那么可以转换一下思路,重新将组件中的这一情况类比成一下这种情况:
<template id="cpn">
<div>
<h2>我是{
{
name}}</h2>
<button @click="change()">改变</button> <!-- 多增加一个按钮用于改变data的值 -->
</div>
</template>
//使用组件
<div class="app">
<!-- 复用多次组件 -->
<cpn-text></cpn-text>
<cpn-text></cpn-text>
<cpn-text></cpn-text>
</div>
//注册组件
const obj = {
name:'我是一个小小的组件'
}//定义一个存放数据的对象,假设这里就是data:{}
const appbox = new Vue({
el:".app",
data:{
msg:'haha'
},
components:{
cpnText:{
template:'#cpn',
data(){
return obj;//这里类比只有一个data对象
},
methods:{
change(){
this.name = '一个改变了的组件'
}
}
}
}
})
效果:
点击改变
如果返回实例对象
<template id="cpn">
<div>
<h2>我是{
{
name}}</h2>
<button @click="change()">改变</button> <!-- 多增加一个按钮用于改变data的值 -->
</div>
</template>
//使用组件
<div class="app">
<!-- 复用多次组件 -->
<cpn-text></cpn-text>
<cpn-text></cpn-text>
<cpn-text></cpn-text>
</div>
//注册组件
const appbox = new Vue({
el:".app",
data:{
msg:'haha'
},
components:{
cpnText:{
template:'#cpn',
data(){
return {
name:'我是一个小小的组件'
}
},
methods:{
change(){
this.name = '一个改变了的组件'
}
}
}
}
})
总结
当我们开发人员使用组件的时候,肯定希望各个部分除了基本功能通信,自己基本的值不会变,比如一个轮播组件,一个页面需要两个轮播,但是你在因为自己的需求改变第一个轮播组件其中的某些data值的时候,另外一个也跟着改变了,这就会出现很多矛盾和错误,所以为了避免这种情况的发生,VUE组件当中将data 编写为定义的时候需要以函数的形式出现,而且必须返回一个实例对象的值。
因为返回实例对象的值的时候,如果你每次都复用一次,在内存栈里面会另外开辟一片内存空间,每个组件指向的数据栈是不同的,这样就实现了互不影响,如果改变一个的值,那么另外的组件根本不会收到影响。而不是都指向同一个内存地址,影响其他组件的使用