From 866a65cd7e5b1512c9c08f0a00a8be5ed0d10df6 Mon Sep 17 00:00:00 2001 From: Sarah Dayan Date: Tue, 25 Feb 2020 22:47:25 +0100 Subject: [PATCH 1/2] fix: deduplicate change detection caveat sections --- src/v2/guide/list.md | 98 +------------------------------------- src/v2/guide/reactivity.md | 48 ++++++++++++++++++- 2 files changed, 47 insertions(+), 99 deletions(-) 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..e6917c3a4c 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. + +### With 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). +### With Arrays + +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) +``` ## Declaring Reactive Properties From a90c40b890aeab384242a8379d10352606c00b81 Mon Sep 17 00:00:00 2001 From: Sarah Dayan Date: Wed, 26 Feb 2020 12:42:21 +0100 Subject: [PATCH 2/2] fix: apply suggestions from review --- src/v2/guide/reactivity.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/v2/guide/reactivity.md b/src/v2/guide/reactivity.md index e6917c3a4c..6b67644d75 100644 --- a/src/v2/guide/reactivity.md +++ b/src/v2/guide/reactivity.md @@ -22,9 +22,9 @@ Every component instance has a corresponding **watcher** instance, which records Due to limitations in JavaScript, there are types of changes that Vue **cannot detect**. However, there are ways to circumvent them to preserve reactivity. -### With Objects +### 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: +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({ @@ -57,9 +57,9 @@ 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 }) ``` -### With Arrays +### For Arrays -Due to limitations in JavaScript, Vue **cannot** detect the following changes to an array: +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`