v-for循环同一个自定义组件,只有最后一个有数据

这个问题时不时的冒出来困扰我几天时间,网上也搜了很久,一直没有解决,我在想会不会是vue本身的问题,但根据观察应该就是自定义组件才会出现该问题,突然有一天终于解决了。然后我回忆心路历程,终于知道发生了什么,不知道有没有跟我一样在学习VUE时出现类似心路历程的呢?

1.问题诱因:

        箭头函数this就是"该函数所在的作用域指向的对象"而不是vue页面的对象。所以为了解决这个问题,我们一般会这样写:

methods:{
    fun(){
        let that = this
        this.arrayList.forEach((item,index)=>{
            if(item.name==that.curName){
                ......
            }
        })
    }
}

BUT,当函数多了以后,就变成这样了:

methods:{
    fun(){
        let that = this
        this.arrayList.forEach((item,index)=>{
            if(item.name==that.curName){
                ......
            }
        })
    }
    fun1(){
        let that = this
        this.arrayList.forEach((item,index)=>{
            if(item.name==that.curName){
                ......
            }
        })
    }
    fun2(){
        let that = this
        this.arrayList.forEach((item,index)=>{
            if(item.name==that.curName){
                ......
            }
        })
    }
    fun3(){
        let that = this
        this.arrayList.forEach((item,index)=>{
            if(item.name==that.curName){
                ......
            }
        })
    }
}

每个方法开头都要写一句:let that = this   烦不烦?难受不难受?强迫症患者就开始想办法了:“能不能定义成全局变量,只在create中写一句that=this,然后就可以在每个方法中直接使用that”,于是:


<script>
	let that = null
	export default {
        data(){
            return:{
                curName:'right'
            }
        },
		created() {
			that = this
		},
        methods:{
            fun(){
                this.arrayList.forEach((item,index)=>{
                    if(item.name==that.curName){
                        ......
                    }
                })
            },
            fun1(){
                this.arrayList.forEach((item,index)=>{
                    if(item.name==that.curName){
                        ......
                    }
                })
            },
            fun2(){
                this.arrayList.forEach((item,index)=>{
                    if(item.name==that.curName){
                        ......
                    }
                })
            },
            fun3(){
                this.arrayList.forEach((item,index)=>{
                    if(item.name==that.curName){
                        ......
                    }
                })
            },
        }
    }
</script>

完美,perfect !!!代码看着清爽多了,于是每个VUE页面都这样写省事了!!!

2.编写自定义组件

        当需要写一个组件时,我们依然仿照上面的方式写:

(1)自定义组件:labelShow.vue

<template>
	<view class="wrapper">
        <view>{{curName}}:{{name}}</view>
	</view>
</template>


<script>
	let that = null
	export default {
        data(){
            return:{
                label:'',
                name:''
            }
        },
        props:{
            curName:{
                type:String,
                default:'性别'
            },
            curValue:{
                type:Number,
                default:0
            },
            arrayList:{
                type:Array,
                default:()=>[{name:'男',value:1},{name:'女',value:2}]
            }
        },
		created() {
			that = this
            this.fun()
		},
        methods:{
            fun(){
                this.arrayList.forEach((item,index)=>{
                    if(item.value==that.curValue){
                        that.name = item.name
                    }
                })
            },
        }
    }
</script>

(2)父组件调用:parent.vue

<template>
	<view class="wrapper">
        <labelShow :curName="curName" :curValue="curSex" :arrayList="sexList" ></labelShow>
	</view>
</template>


<script>
	let that = null
    import labelShow from './labelShow.vue'
	export default {
        components:{
            labelShow
        },
        data(){
            return:{
                curName:'性别',
                curSex:0,
                sexList:[{name:'未知', value:0},{name:'男',value:1},{name:'女',value:2}]
            }
        },
		created() {
			that = this
		}
    }
</script>

页面显示:  性别:未知    显示正常Good

3.问题出现:

当父组件用v-for循环显示子组件时:

<template>
	<view class="wrapper flex-col justify-center">
        <view v-for="(item,index) in userInfo" :key="label+index">
            <labelShow :curName="item.curName" :curValue="item.curSex" :arrayList="item.arrayList" />
        </view>
	</view>
</template>


<script>
	let that = null
    import labelShow from './labelShow.vue'
	export default {
        components:{
            labelShow
        },
        data(){
            return:{
                userInfo:[
                    {
                        curName:'性别',
                        curSex:1,
                        arrayList:[{name:'未知', value:0},{name:'男',value:1},{name:'女',value:2}]
                    },
                    {
                        curName:'学历',
                        curSex:3,
                        arrayList:[{name:'高中', value:0},{name:'学士',value:1},{name:'硕士',value:2},{name:'博士',value:3}]
                    }
                ]
            }
        },
		created() {
			that = this
		}
    }
</script>

显示效果:

                性别:     

                学历:博士

性别的内容总是出不来。然后把userInfo的数组元素换个位置,把学历放上边,把性别放下面

显示效果:

                学历:

                性别:男

至此,你已经成功的跳进沟里去了,

4.原因分析

        通过调整顺序发现只有循环的最后一个组件显示正常,可以感觉出来是for循环过程中数据没有隔离,造成多个组件使用了同一个(最后一个)数据。那如何进行数据隔离呢,第一想到的就是“深拷贝”,BUT,在你使用过深拷贝后,依然无法解决问题。所以思路不应该是“如何进行数据隔离”,而是应该考虑“为什么出现了数据复用”,最后发现就是那个万恶的   let that=null,因为that被定义在了VUE对象外面,而在VUE里面又对他赋了值,就这样,当循环时最后一个vue组件就会对that赋值,也就是说,多个自定义组件使用了同一个 that。

5.解决问题

自定义组件时,老老实实的把  let that = this 写在每个有箭头函数的方法里。

<template>
	<view class="wrapper">
        <view>{{curName}}:{{name}}</view>
	</view>
</template>


<script>
	export default {
        data(){
            return:{
                label:'',
                name:''
            }
        },
        props:{
            curName:{
                type:String,
                default:'性别'
            },
            curValue:{
                type:Number,
                default:0
            },
            arrayList:{
                type:Array,
                default:()=>[{name:'男',value:1},{name:'女',value:2}]
            }
        },
		created() {
            this.fun()
		},
        methods:{
            fun(){
			    let that = this
                this.arrayList.forEach((item,index)=>{
                    if(item.value==that.curValue){
                        that.name = item.name
                    }
                })
            },
        }
    }
</script>

注意:代码没测试可能有错误,但在项目中已经验证过了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值