Vue数组更新没有导致页面刷新

Vue数组更新视图不更新

前言

在做项目的时候,发现了数组变化然后视图不发生变化的情况,附上代码

<van-tabs
      title-active-color="#ffb001"
      title-inactive-color="#838a96"
      line-height=".06rem"
      swipeable
      lazy-render
      @rendered="changeCate"
      offset-top=".8rem"
    >
      <van-tab
        v-for="item in cateList"
        :key="item.id"
        :title="item.type_name"
        class="header"
      >
        <div v-if="item.list">
          <van-list
            v-model="load"
            :finished="item.finished"
            finished-text="没有更多了"
            :error.sync="error"
            error-text="请求失败,点击重新加载"
            @load="getMoreGame(item.id, 1)"
          >
            <van-pull-refresh
              v-model="load"
              @refresh="getMoreGame(item.id, 2)"
              success-text="刷新成功"
              :disabled="item.finished"
            >
            </van-pull-refresh>
          </van-list>
        </div>
      </van-tab>
    </van-tabs>

逻辑结构如下

<script>
export default {
  components: {
  },
  data() {
    return {
      cateList: [],
      cateId: 0,
      queryInfo: {
        pageindex: 1,
        pagesize: 50,
        type_id: '',
        key: ''
      },
      load: false,
      error: false
    }
  },
  created() {
    this.getCateList()
  },
  methods: {
    async getCateList(num) {
      const res = await this.$http.get('/api/?ac=get_gametype')
      this.cateList = res.data
      this.cateList.unshift({
        id: 0,
        type_name: '全部'
      })
    },
    async getCateGame(num) {
      this.load = true
      this.queryInfo.type_id = num
      const res = await this.$http.get(
        '/api/?ac=get_gamelist_by_typeid',
        this.queryInfo
      )
      res.data.list.forEach(
        item =>
          (item.online_users = Math.ceil(item.online_users / 10000).toString())
      )
      Object.assign(this.cateList[num], res.data, {
        queryInfo: Object.assign({}, this.queryInfo),
        finished: false,
        load: false
      })
      this.load = false
      this.$forceUpdate()
    },
    changeCate(name, title) {
      this.getCateGame(name)
    }
}
</script>

然后呢就是在获取数组的时候初次渲染回调用rendered的回调changeCate,
在里面,然后会对刚开始的数组进行赋值,但是发现数组改变之后视图不进行更新会报错。后来查资料发现是因为vue不能检测一下数组的变动:
如用索引直接设置一个数组项
vm.a[index]=value;
或者修改数组的长度
vm.a.length=2;
这样的修改都不是响应式的。

Vue的响应式原理

当把js对象传给Vue的实例的data的时候,vue将遍历此对象的所有属性,把属性用object.defineproperty全部转化成为getter/setter也就是当属性改变的时候会调用setter函数进行更改,但setter和getter是有局限性的。
如下面的例子:

var person = {};
Object.defineProperties( person, { 
      age: { 
        defaultValue: 11, 
        get: function () {
          return this.defaultValue;
        }, 
        set: function (val) { 
          this.defaultValue = val; 
          console.log("触发了set") 
        }
      } 
    });
 person.age=12;//这里会触发setter
 //属性值变成数组的时候也会调用setter
 person.arr=[1,2,3]
 //但是下面这样不会调用setter
 person.arr[0]=222
 //同理设置对象的时候也一样,把某个属性设置为对象的时候会调用setter,但是设置这个对象的某个属性的时候不会触发setter 如下
 person.aaa={bbb:1}   //触发
 person.aaa.bbb=2  //不触发

为了解决当你利用索引直接设置一个数组项问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将在响应式系统内触发状态更新

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

你也可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名:

vm.$set(vm.items, indexOfItem, newValue)

为了解决当你修改数组的长度问题,你可以使用 splice:

vm.items.splice(newLength)

当修改对象的属性或为对象添加属性时,应该使用以下方法:

vm.$set(vm.userProfile, 'age', 27)
或者
Vue.set(vm.userProfile, 'age', 27)

有时你可能需要为已有对象赋值多个新属性,比如使用 Object.assign() 或 _.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。所以,如果你想添加新的响应式属性,不要像这样:

Object.assign(vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

你应该这样做:

vm.userProfile = Object.assign({}, vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

由于数据响应原理机制, Vue 不允许动态添加根级响应式属性,所以你必须在初始化实例前声明所有可能用到的根级响应式属性,且为这些属性都设一个初值,哪怕只是一个空值。

回归正题,我项目中遇到的这个问题,解决方法:

  1. 运用this.$forceUpdate()强制刷新。

  2. 使用vm.$set(vm.items, indexOfItem, newValue)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值