这个问题时不时的冒出来困扰我几天时间,网上也搜了很久,一直没有解决,我在想会不会是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>
注意:代码没测试可能有错误,但在项目中已经验证过了。