问题描述:
在一个子组件中用button控制div的显示隐藏(v-if实现),在两个div中都使用了同一个自定义组件,但是这两个组件的data相互影响。
- select_show的初始值为false,可以看到这里切换游戏属性到渠道属性,属性select_show同步变化。
<!--子组件-->
<div v-if="cur_attr === '游戏属性'">
<span class="c-fix-title wt">当前正在筛选:游戏属性</span>
<Divider />
<aSelect
attr_name="玩过的游戏"
btn_name="游戏组"
:attrList="cityData"
:stype="2"
></aSelect>
</div>
<div v-if="cur_attr === '渠道属性'">
<span class="c-fix-title wt">当前正在筛选:渠道属性</span>
<Divider />
<aSelect
attr_name="渠道"
btn_name="channel"
:attrList="cityData1"
></aSelect>
<aSelect
attr_name="渠道1"
btn_name="channel1"
:attrList="cityData"
:stype="2"
></aSelect>
</div>
<!--自定义组件-->
<Button type="primary" ghost @click="select_handle">{
{
btn_name }}</Button>
<div class="select-div" v-if="select_show">
<span>{
{
select_show }}</span>
<selecter
v-model="mult_group"
:data="selectList"
search
:title="['一级', '二级']"
@on-select="selectAll"
@on-delete="delTag"
@on-clear="clearTag"
/>
</div>
data () {
return {
checked: true,
select_show: false,
}
},
methods: {
select_handle () {
this.select_show = !this.select_show
},
}
问题分析:
测试发现在同一个div里复用两个自定义组件data就不会相互影响,考虑到初次渲染的时候有两个相同组件就会为他们的data分别分配一份内存,但是另一个div的v-if为true的时候和上一个div的data指向了同一份内存,不同变量指向了相同的地址,也有可能与keep-alive有关。
- 这里可以看到在同一个div里面就不会相互影响,因为在渲染的时候为两个子组件的data分别分配了内存。
问题解决:
- 比较粗暴的方式就是另外复制一份代码,重新写一个组件,但是这种方式就会造成代码冗余。
- 也可以考虑通过prop又父组件传参给子组件,这样就不会因为data公用而相互影响了,但是如果参数很多代码也会看起来很杂乱。
- 比较优雅地方式是使用v-show,因为v-show是会在一开始渲染的时候就渲染DOM,只要有DOM,就会为这几个相同的子组件的data分配不同的内存,也就不会相互影响了,但是缺点是会消耗更多的内存,但是这里的话影响不是很大。