vue数组刷新_vue 数组更新视图不更新的问题

0. 解决方案

1.当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue

2.当你修改数组的长度时,例如:vm.items.length = newLength

对于第一种情况,可以使用:Vue.set(example1.items, indexOfItem, newValue);而对于第二种情况,可以使用 vm.items.splice(newLength)。

-----------------------原理浅析----------------------------分割线--

1.demo

我们实际中会用到的场景

初始化的时候arr定义的是:[]

源码中简化的原理,初始化的时候执行如下逻辑:

data = {arr: []}

val = []

Object.defineProperty(data, 'arr', {

enumerable: true,

configurable: true,

get: function () {

console.log('你获取数组')

return val

},

set: function(value) {

console.log('你更新数组,我检测到了')

val = value

}

})

data.arr.forEach((v,i, array) => {

var value = v

Object.defineProperty(array, i, {

enumerable: true,

configurable: true,

get: function () {

console.log(`你在访问arr${i}`)

return v

},

set: function(newVal) {

console.log(`你在更新arr${i},我检测到了`)

v = newVal

}

})

})

chrome中测试如下:

data.arr

VM485:7 你获取数组

[]

VM485:7 你获取数组

data.arr[1]

VM485:7 你获取数组

undefined

VM485:7 你获取数组

data.arr = [1,2,3]

VM485:11 你更新数组,我检测到了

(3) [1, 2, 3]

VM485:7 你获取数组

data.arr[1]

VM485:7 你获取数组

2

data.arr[1] = 'new'

VM485:7 你获取数组

"new"

VM485:7 你获取数组

data.arr[2] = 'new2'

VM485:7 你获取数组

"new2"

2VM485:7 你获取数组

data.arr[1]

VM485:7 你获取数组

"new"

VM485:7 你获取数组

data.arr[3]

VM485:7 你获取数组

undefined

data.arr[3]

VM485:7 你获取数组

undefined

VM485:7 你获取数组

data.arr.length = 100

VM485:7 你获取数组

可以发现当data.arr初始值为[],你直接改变data.arr的值是可以触发更新的,但是通过data.arr[index] = newVal的方式无法检测到变化,并且你直接通过

splice等方法改变数组长度的方法都没有办法检测到更新

data.arr.splice(0,1,'fake')

VM485:7 你获取数组

[1]

data.arr

VM485:7 你获取数组

(100) ["fake", "new", "new2", empty × 97],

2.vue中的处理

1.当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue

2.当你修改数组的长度时,例如:vm.items.length = newLength

对于第一种情况,可以使用:Vue.set(example1.items, indexOfItem, newValue);而对于第二种情况,可以使用 vm.items.splice(newLength)。

其实通过splice的方式,在vue中是可以检测到更新的

为什么呢?

看一下源码:

部分图解

// vue-dev\src\core\util\lang.js

def (obj, key,val,enumerable) {

Object.defineProperty(obj, key, {

value: val,

enumerable: !!enumerable,

writable: true,

configurable: true

})

}

// src/core/observer/array.js

const arrayProto = Array.prototype

export const arrayMethods = Object.create(arrayProto)

const methodsToPatch = [

'push',

'pop',

'shift',

'unshift',

'splice',

'sort',

'reverse'

]

// 改造了列举的数组方法

methodsToPatch.forEach(function (method) {

// cache original method

// 以push为例

const original = arrayProto[method] // Array.prototype.push

// def(arrayMethods,'push', function() {}) -> arrayMethods.push = function () {} 改造了push方法

def(arrayMethods, method, function mutator (...args) {

const result = original.apply(this, args) // this为data.arr

const ob = this.__ob__

let inserted

switch (method) {

case 'push':

case 'unshift':

inserted = args

break

case 'splice':

inserted = args.slice(2)

break

}

if (inserted) ob.observeArray(inserted)

// notify change

ob.dep.notify()// 派发更新了

return result

})

})

把data.arr.__proto __ = arrayMethods

当我执行data.arr.push(xxx)的时候就会派发更新了,自然更新了视图


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部