diff --git a/src/v2/guide/list.md b/src/v2/guide/list.md index e1a9622b01..4db31ee5e2 100644 --- a/src/v2/guide/list.md +++ b/src/v2/guide/list.md @@ -260,103 +260,7 @@ You might think this will cause Vue to throw away the existing DOM and re-render ### Caveats -Due to limitations in JavaScript, Vue **cannot** detect the following changes to an array: - -1. When you directly set an item with the index, e.g. `vm.items[indexOfItem] = newValue` -2. When you modify the length of the array, e.g. `vm.items.length = newLength` - -For example: - -``` js -var vm = new Vue({ - data: { - items: ['a', 'b', 'c'] - } -}) -vm.items[1] = 'x' // is NOT reactive -vm.items.length = 2 // is NOT reactive -``` - -To overcome caveat 1, both of the following will accomplish the same as `vm.items[indexOfItem] = newValue`, but will also trigger state updates in the reactivity system: - -``` js -// Vue.set -Vue.set(vm.items, indexOfItem, newValue) -``` -``` js -// Array.prototype.splice -vm.items.splice(indexOfItem, 1, newValue) -``` - -You can also use the [`vm.$set`](https://vuejs.org/v2/api/#vm-set) instance method, which is an alias for the global `Vue.set`: - -``` js -vm.$set(vm.items, indexOfItem, newValue) -``` - -To deal with caveat 2, you can use `splice`: - -``` js -vm.items.splice(newLength) -``` - -## Object Change Detection Caveats - -Again due to limitations of modern JavaScript, **Vue cannot detect property addition or deletion**. For example: - -``` js -var vm = new Vue({ - data: { - a: 1 - } -}) -// `vm.a` is now reactive - -vm.b = 2 -// `vm.b` is NOT reactive -``` - -Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it's possible to add reactive properties to a nested object using the `Vue.set(object, propertyName, value)` method. For example, given: - -``` js -var vm = new Vue({ - data: { - userProfile: { - name: 'Anika' - } - } -}) -``` - -You could add a new `age` property to the nested `userProfile` object with: - -``` js -Vue.set(vm.userProfile, 'age', 27) -``` - -You can also use the `vm.$set` instance method, which is an alias for the global `Vue.set`: - -``` js -vm.$set(vm.userProfile, 'age', 27) -``` - -Sometimes you may want to assign a number of new properties to an existing object, for example using `Object.assign()` or `_.extend()`. In such cases, you should create a fresh object with properties from both objects. So instead of: - -``` js -Object.assign(vm.userProfile, { - age: 27, - favoriteColor: 'Vue Green' -}) -``` - -You would add new, reactive properties with: - -``` js -vm.userProfile = Object.assign({}, vm.userProfile, { - age: 27, - favoriteColor: 'Vue Green' -}) -``` +Due to limitations in JavaScript, there are types of changes that Vue **cannot detect** with arrays and objects. These are discussed in the [reactivity](reactivity.html#Change-Detection-Caveats) section. ## Displaying Filtered/Sorted Results diff --git a/src/v2/guide/reactivity.md b/src/v2/guide/reactivity.md index cbc8198e6c..6b67644d75 100644 --- a/src/v2/guide/reactivity.md +++ b/src/v2/guide/reactivity.md @@ -20,7 +20,11 @@ Every component instance has a corresponding **watcher** instance, which records ## Change Detection Caveats -Due to the limitations of modern JavaScript (and the abandonment of `Object.observe`), Vue **cannot detect property addition or deletion**. Since Vue performs the getter/setter conversion process during instance initialization, a property must be present in the `data` object in order for Vue to convert it and make it reactive. For example: +Due to limitations in JavaScript, there are types of changes that Vue **cannot detect**. However, there are ways to circumvent them to preserve reactivity. + +### For Objects + +Vue cannot detect property addition or deletion. Since Vue performs the getter/setter conversion process during instance initialization, a property must be present in the `data` object in order for Vue to convert it and make it reactive. For example: ``` js var vm = new Vue({ @@ -53,7 +57,47 @@ Sometimes you may want to assign a number of properties to an existing object, f this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 }) ``` -There are also a few array-related caveats, which were discussed earlier in the [list rendering section](list.html#Caveats). +### For Arrays + +Vue cannot detect the following changes to an array: + +1. When you directly set an item with the index, e.g. `vm.items[indexOfItem] = newValue` +2. When you modify the length of the array, e.g. `vm.items.length = newLength` + +For example: + +``` js +var vm = new Vue({ + data: { + items: ['a', 'b', 'c'] + } +}) +vm.items[1] = 'x' // is NOT reactive +vm.items.length = 2 // is NOT reactive +``` + +To overcome caveat 1, both of the following will accomplish the same as `vm.items[indexOfItem] = newValue`, but will also trigger state updates in the reactivity system: + +``` js +// Vue.set +Vue.set(vm.items, indexOfItem, newValue) +``` +``` js +// Array.prototype.splice +vm.items.splice(indexOfItem, 1, newValue) +``` + +You can also use the [`vm.$set`](https://vuejs.org/v2/api/#vm-set) instance method, which is an alias for the global `Vue.set`: + +``` js +vm.$set(vm.items, indexOfItem, newValue) +``` + +To deal with caveat 2, you can use `splice`: + +``` js +vm.items.splice(newLength) +``` ## Declaring Reactive Properties