uniapp更改组件值页面不更新怎么回事
在uniapp开发中,页面的数据处理是必不可少的,我们需要动态地改变页面中某些组件的值。但有时候发现,即使我们已经更改了组件的值,但是页面并没有更新,那么这种情况是因为什么呢?接下来就让我们来探讨一下uniapp更改组件值页面不更新的问题。
1. uniapp数据响应式系统
首先,我们需要了解uniapp的数据响应式系统是什么。我们知道,在vue框架中,数据响应式系统利用了ES5的Object.defineProperty()方法来实现双向绑定。而在uniapp当中,虽然在底层也是用了Object.defineProperty()方法,但是在使用过程中会有所不同。在uniapp中,我们使用的是this.setData()方法来更新数据,而this.setData()方法则会调用内部的响应式系统,决定了组件如何更新。
从这里我们也可以看到,uniapp中的数据处理是非常重要的。除了this.setData()方法外,还有computed属性、watcher等。注意,这些特性,只有组件的data中的属性才能享受到他们的便利。
2. 引用类型的数据在setData()中的问题
在uniapp中,我们需要注意的是,在this.setData()方法中仅会触发那些有对应 setData() 的数据改变。因此,this.setData() 只能改变组件中根 data 下的数据,而无法改变嵌套的对象或数组。这里的嵌套对象或数组指的是类似于以下代码的情况。
data: {
obj: {
name: 'Jack',
age: 18
}
},
// 更改obj的数据
this.setData({
obj: {
name: 'Tom'
}
})
这种情况下,更改数据的操作是不会生效的,因为在setData()方法中,只会更新根data中的数据。
那如果需要在setData()中修改嵌套对象或数组的数据怎么办呢?这时我们需要借助ES6的扩展运算符将原对象解构出来,然后修改其指定的属性,最后再使用this.setData()来更新。
// 更改obj的数据
this.setData({
obj: {
...this.data.obj,
name: 'Tom'
}
})
3. 封装组件导致页面不更新的问题
与引用类型的数据有关的问题解决了,但还有一种情况,就是使用封装组件时,会出现页面不更新的问题。
假设我们有以下简单的组件:
<template>
<view class="my-component">
<view>组件中的数据:{{msg}}</view>
<button @click="changeMsg">改变数据</button>
</view>
</template>
<script>
export default {
data() {
return {
msg: '这是组件的数据'
}
},
methods: {
changeMsg() {
// 改变组件数据
this.msg = '改变后的数据'
}
}
}
</script>
<style>
.my-component {
background-color: #ddd;
padding: 10px;
text-align: center;
}
</style>
我们可以发现,在这个组件中,点击按钮会触发changeMsg()方法,改变this.msg的值。
changeMsg() {
this.msg = '改变后的数据'
}
但是,如果我们在外部使用这个自定义组件,发现点击按钮并没有改变 {{msg}} 的值。屏幕上的文本仍然是“这是组件的数据”。
这是因为自定义组件中如果需要更改自身数据,必须使用 this.$emit() 方法触发自定义事件,然后从父级传递参数给自身组件,这样才能达到更新数据的效果。这就是自定义组件的数据更新问题。
<template>
<view class="my-component">
<view>组件中的数据:{{msg}}</view>
<button @click="changeMsg">改变数据</button>
</view>
</template>
<script>
export default {
data() {
return {
msg: '这是组件的数据'
}
},
methods: {
changeMsg() {
// 触发事件改变数据
this.$emit('changeMsg', '改变后的数据')
}
}
}
</script>
<style>
.my-component {
background-color: #ddd;
padding: 10px;
text-align: center;
}
</style>
在父组件中,我们需要监听自定义事件,并在事件处理程序中调用 this.setData() 方法更新组件的数据。
<template>
<view>
<my-component :msg="content" @changeMsg="changeMsg"></my-component>
</view>
</template>
<script>
import MyComponent from '@/components/MyComponent.vue';
export default {
components: {
MyComponent
},
data() {
return {
content: '从父组件中传递的数据'
}
},
methods: {
changeMsg(val) {
this.setData({
content: val
})
}
}
}
</script>
<style scoped>
page {
background-color: #fff;
padding: 10px;
}
</style>
这样以来,就完成了自定义组件数据更新过程。
总结
在uniapp开发过程中,组件的数据处理是非常重要的。采用this.setData()方法来更新数据时,需要注意数据的嵌套类型以及自定义组件的数据更新,以免页面不更新的问题。
引用类型的数据需要注意,采用ES6的扩展运算符来解构对象,并修改变化的属性。而在封装组件时,需要使用 this.$emit() 方法触发自定义事件,并在事件处理程序中调用 this.setData() 方法来更新父组件传递的数据。