vue如何触发组件的更新

4,822 阅读2分钟

vue 数据来源是单向的有三种来源

1.来自父组件的属性
2.来自组件自身的状态data
3.来自vuex,Vue.observable
状态和属性的改变未必会触发试图更新


vue 数据变化的追踪

 vue 实例化的时候vue对data里的数据处理方式

 1.对象:Object.defineProperty 把属性全部转换成getter/setter。

 2.数组:通过劫持数组的原始方法,当这些数据调用原生方法时候dep.notify(),通知依赖此数据的视图update()

 3.data 里的属性且被模版render使用的数据 会被收集在依赖里面。当数据发生变化即有setter操作通知watcher监控,从而组件模版发生变化

这里改变name 和 obj.a,list都是不会引起组件更新的 updated() 不会触发 obj.b 如果被修改了数据会发生变化,但是并不会造成组件的更新 updated() 不会触发 数组push 数组里的数据发生变化了,数组是引用类型,其实数组本身并没有变化

vue初始化未定义的对象不会触发视图的改变

  •  已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性。 eg. Vue.set(this.obj, 'b', 2) this.$set(this.obj, 'a', 2) 
  •  需要为已有对象赋值多个新属性,比如使用 Object.assign() 或 _.extend()。添加到对象上的新属性不会触发更新 // 代替 `Object.assign(this.obj, { a: 1, b: 2 })` this.obj = Object.assign({}, this.obj, { a: 1, b: 2 })

数组原生的操作方法会触发视图的改变

 push() 数组末端添加项
 pop() 数组末端删除项
 shift() 数组头部添加项
 unshift() 数组头部删除项
 splice(index, num) 删除,num删除数量
 sort() 排序
 reverse() 反转
 filter()、concat() 和 slice()  可以赋值到愿数据 也会引起视图更新

vue不能检测数组变动的情况

 1.利用index设置某一项
    eg this.list[index] = newval
    解决方案
    Vue.set(this.list, index, newval)
    this.$set(this.list, index, newval)
    this.list.splice(index, 1, newval) 
 2.修改数组长度
    eg this.list.length = newLen
    解决方案
    this.list.splice(newLen)
    虽然这两个案例制图没有更新,但是数据是变化的,只是没有通知依赖的视图 
3.如果这两种操作数据的方式和数组原生发法一起使用,视图会更新

代码示例

<template>
  <div>
    <div>name = {{name}}</div> 
    <div>a= {{obj.a}}</div> 
    <div>c= {{obj.c}}</div> 
    <div>list = {{list}}</div> 
    <button @click="handleChangeName">更新name</button>
    <button @click="handleChangeObj">更新obj.a</button>
    <button @click="handleChangeList">更新list</button>
  </div>
</template>
<script>
const name ='hello'
export default {
  name: 'App',
  data () {
    // this.name = name // 1
    return {
        name: name, // 放在这里就改变了
        obj: {
            b: '22',
            // a: ''  // 放在这里就改变了
        },
        list: [1, 2, 3]
    }
  },
  updated () {
    console.log('更新了')
  },
  methods: {
    handleChangeName () {
      this.name = 'world'
      console.log(this.name)
    },
    handleChangeObj () {
      this.obj.a = 'world'
      this.$set(this.obj, 'a', 2)
      this.obj = Object.assign({}, this.obj, { c: 1111, d: 2222 })
      console.log(this.obj)
    },
    handleChangeList () {
        // this.list.reverse()
        // this.list[0] = 0
        // console.log(this.list) // 0,2,1

        // this.list.reverse()
        // this.list[0] = 0
        const arr = [7, 8, 9]
        this.list = this.list.concat(arr)
        console.log(this.list)
    }
  }
}
</script>