From 7ec6c806e27fb193ec379fda3b0decd7aeb8359a Mon Sep 17 00:00:00 2001 From: Alex Riviere Date: Sat, 5 Dec 2020 15:46:42 -0500 Subject: [PATCH 1/9] Adding documentation for watch and proxied objects --- src/guide/reactivity-computed-watchers.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/guide/reactivity-computed-watchers.md b/src/guide/reactivity-computed-watchers.md index 8481f97054..c0167ddee7 100644 --- a/src/guide/reactivity-computed-watchers.md +++ b/src/guide/reactivity-computed-watchers.md @@ -211,6 +211,24 @@ firstName.value = "John"; // logs: ["John",""] ["", ""] lastName.value = "Smith"; // logs: ["John", "Smith"] ["John", ""] ``` +### Watching Reactive Objects + +Using a watcher to compare values of an Array or Object that are reactive requires that it has a copy made of just the values. + +```js +const numbers = reactive([1,2,3,4]) + +watch( + () => [...numbers], + (numbers, prevNumbers) =>{ + console.log(numbers, prevNumbers); +}) + +numbers.push(5) // logs: [1,2,3,4,5] [1,2,3,4] +``` + +For deeply nested object and arrays, a deep copy of values may be required. This can be achieved with a utility such as `lodash.cloneDeep` + ### Shared Behavior with `watchEffect` `watch` shares behavior with [`watchEffect`](#watcheffect) in terms of [manual stoppage](#stopping-the-watcher), [side effect invalidation](#side-effect-invalidation) (with `onInvalidate` passed to the callback as the 3rd argument instead), [flush timing](#effect-flush-timing) and [debugging](#watcher-debugging). From 6abcf91b1ff25ae8c7f15c0fa5ba709d0622e936 Mon Sep 17 00:00:00 2001 From: Alex Riviere Date: Sun, 6 Dec 2020 08:40:32 -0500 Subject: [PATCH 2/9] Update src/guide/reactivity-computed-watchers.md Co-authored-by: Natalia Tepluhina --- src/guide/reactivity-computed-watchers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guide/reactivity-computed-watchers.md b/src/guide/reactivity-computed-watchers.md index c0167ddee7..e9d286be56 100644 --- a/src/guide/reactivity-computed-watchers.md +++ b/src/guide/reactivity-computed-watchers.md @@ -227,7 +227,7 @@ watch( numbers.push(5) // logs: [1,2,3,4,5] [1,2,3,4] ``` -For deeply nested object and arrays, a deep copy of values may be required. This can be achieved with a utility such as `lodash.cloneDeep` +For deeply nested object and arrays, a deep copy of values may be required. This can be achieved with a utility such as [lodash.cloneDeep](https://lodash.com/docs/4.17.15#cloneDeep) ### Shared Behavior with `watchEffect` From f0f034fc3acf4aabf4902eea80f025c949e6993f Mon Sep 17 00:00:00 2001 From: fimion Date: Mon, 21 Dec 2020 01:24:00 -0500 Subject: [PATCH 3/9] Added more documentation around using `deep` and deeply nested objects. --- src/guide/reactivity-computed-watchers.md | 126 ++++++++++++++++++---- 1 file changed, 106 insertions(+), 20 deletions(-) diff --git a/src/guide/reactivity-computed-watchers.md b/src/guide/reactivity-computed-watchers.md index e9d286be56..c56e452932 100644 --- a/src/guide/reactivity-computed-watchers.md +++ b/src/guide/reactivity-computed-watchers.md @@ -4,7 +4,11 @@ ## Computed values -Sometimes we need state that depends on other state - in Vue this is handled with component [computed properties](computed.html#computed-properties). To directly create a computed value, we can use the `computed` method: it takes a getter function and returns an immutable reactive [ref](reactivity-fundamentals.html#creating-standalone-reactive-values-as-refs) object for the returned value from the getter. +Sometimes we need state that depends on other state - in Vue this is handled with +component [computed properties](computed.html#computed-properties). To directly create a computed value, we can use +the `computed` method: it takes a getter function and returns an immutable +reactive [ref](reactivity-fundamentals.html#creating-standalone-reactive-values-as-refs) object for the returned value +from the getter. ```js const count = ref(1) @@ -32,7 +36,9 @@ console.log(count.value) // 0 ## `watchEffect` -To apply and _automatically re-apply_ a side effect based on reactive state, we can use the `watchEffect` method. It runs a function immediately while reactively tracking its dependencies and re-runs it whenever the dependencies are changed. +To apply and _automatically re-apply_ a side effect based on reactive state, we can use the `watchEffect` method. It +runs a function immediately while reactively tracking its dependencies and re-runs it whenever the dependencies are +changed. ```js const count = ref(0) @@ -48,7 +54,9 @@ setTimeout(() => { ### Stopping the Watcher -When `watchEffect` is called during a component's [setup()](composition-api-setup.html) function or [lifecycle hooks](composition-api-lifecycle-hooks.html), the watcher is linked to the component's lifecycle and will be automatically stopped when the component is unmounted. +When `watchEffect` is called during a component's [setup()](composition-api-setup.html) function +or [lifecycle hooks](composition-api-lifecycle-hooks.html), the watcher is linked to the component's lifecycle and will +be automatically stopped when the component is unmounted. In other cases, it returns a stop handle which can be called to explicitly stop the watcher: @@ -63,10 +71,13 @@ stop() ### Side Effect Invalidation -Sometimes the watched effect function will perform asynchronous side effects that need to be cleaned up when it is invalidated (i.e. state changed before the effects can be completed). The effect function receives an `onInvalidate` function that can be used to register an invalidation callback. This invalidation callback is called when: +Sometimes the watched effect function will perform asynchronous side effects that need to be cleaned up when it is +invalidated (i.e. state changed before the effects can be completed). The effect function receives an `onInvalidate` +function that can be used to register an invalidation callback. This invalidation callback is called when: - the effect is about to re-run -- the watcher is stopped (i.e. when the component is unmounted if `watchEffect` is used inside `setup()` or lifecycle hooks) +- the watcher is stopped (i.e. when the component is unmounted if `watchEffect` is used inside `setup()` or lifecycle + hooks) ```js watchEffect(onInvalidate => { @@ -79,23 +90,32 @@ watchEffect(onInvalidate => { }) ``` -We are registering the invalidation callback via a passed-in function instead of returning it from the callback because the return value is important for async error handling. It is very common for the effect function to be an async function when performing data fetching: +We are registering the invalidation callback via a passed-in function instead of returning it from the callback because +the return value is important for async error handling. It is very common for the effect function to be an async +function when performing data fetching: ```js const data = ref(null) watchEffect(async (onInvalidate) => { - onInvalidate(() => { /* ... */ }) // we register cleanup function before Promise resolves + onInvalidate(() => { /* ... */ + }) // we register cleanup function before Promise resolves data.value = await fetchData(props.id) }) ``` -An async function implicitly returns a Promise, but the cleanup function needs to be registered immediately before the Promise resolves. In addition, Vue relies on the returned Promise to automatically handle potential errors in the Promise chain. +An async function implicitly returns a Promise, but the cleanup function needs to be registered immediately before the +Promise resolves. In addition, Vue relies on the returned Promise to automatically handle potential errors in the +Promise chain. ### Effect Flush Timing -Vue's reactivity system buffers invalidated effects and flushes them asynchronously to avoid unnecessary duplicate invocation when there are many state mutations happening in the same "tick". Internally, a component's `update` function is also a watched effect. When a user effect is queued, it is by default invoked **before** all component `update` effects: +Vue's reactivity system buffers invalidated effects and flushes them asynchronously to avoid unnecessary duplicate +invocation when there are many state mutations happening in the same "tick". Internally, a component's `update` function +is also a watched effect. When a user effect is queued, it is by default invoked **before** all component `update` +effects: ```html + @@ -122,7 +142,8 @@ In this example: - The count will be logged synchronously on initial run. - When `count` is mutated, the callback will be called **before** the component has updated. -In cases where a watcher effect needs to be re-run **after** component updates, we can pass an additional `options` object with the `flush` option (default is `'pre'`): +In cases where a watcher effect needs to be re-run **after** component updates, we can pass an additional `options` +object with the `flush` option (default is `'pre'`): ```js // fire after component updates so you can access the updated DOM @@ -138,7 +159,8 @@ watchEffect( ) ``` -The `flush` option also accepts `'sync'`, which forces the effect to always trigger synchronously. This is however inefficient and should be rarely needed. +The `flush` option also accepts `'sync'`, which forces the effect to always trigger synchronously. This is however +inefficient and should be rarely needed. ### Watcher Debugging @@ -147,7 +169,8 @@ The `onTrack` and `onTrigger` options can be used to debug a watcher's behavior. - `onTrack` will be called when a reactive property or ref is tracked as a dependency. - `onTrigger` will be called when the watcher callback is triggered by the mutation of a dependency. -Both callbacks will receive a debugger event which contains information on the dependency in question. It is recommended to place a `debugger` statement in these callbacks to interactively inspect the dependency: +Both callbacks will receive a debugger event which contains information on the dependency in question. It is recommended +to place a `debugger` statement in these callbacks to interactively inspect the dependency: ```js watchEffect( @@ -166,7 +189,9 @@ watchEffect( ## `watch` -The `watch` API is the exact equivalent of the component [watch](computed.html#watchers) property. `watch` requires watching a specific data source and applies side effects in a separate callback function. It also is lazy by default - i.e. the callback is only called when the watched source has changed. +The `watch` API is the exact equivalent of the component [watch](computed.html#watchers) property. `watch` requires +watching a specific data source and applies side effects in a separate callback function. It also is lazy by default - +i.e. the callback is only called when the watched source has changed. - Compared to [watchEffect](#watcheffect), `watch` allows us to: @@ -201,7 +226,7 @@ A watcher can also watch multiple sources at the same time using an array: ```js const firstName = ref(''); -const lastName= ref(''); +const lastName = ref(''); watch([firstName, lastName], (newValues, prevValues) => { console.log(newValues, prevValues); @@ -213,22 +238,83 @@ lastName.value = "Smith"; // logs: ["John", "Smith"] ["John", ""] ### Watching Reactive Objects -Using a watcher to compare values of an Array or Object that are reactive requires that it has a copy made of just the values. +Using a watcher to compare values of an Array or Object that are reactive requires that it has a copy made of just the +values. ```js -const numbers = reactive([1,2,3,4]) +const numbers = reactive([1, 2, 3, 4]) watch( () => [...numbers], - (numbers, prevNumbers) =>{ + (numbers, prevNumbers) => { console.log(numbers, prevNumbers); -}) + }) numbers.push(5) // logs: [1,2,3,4,5] [1,2,3,4] ``` -For deeply nested object and arrays, a deep copy of values may be required. This can be achieved with a utility such as [lodash.cloneDeep](https://lodash.com/docs/4.17.15#cloneDeep) +Attempting to check for changes of properties in a deeply nested Object or Array will +still require the `deep` option to be true, if watching an Object or Array. + +```js +const state = reactive([ + { attributes: { name: "" }, id: 1 }, + { attributes: { name: "" }, id: 2 }, +]); + +watch( + () => state.map((e) => e.attributes), + (attrs, prevAttrs) => { + console.log( + 'not deep ', + attrs.map((e) => e.name), + prevAttrs.map((e) => e.name) + ); + } +); + +watch( + () => state.map((e) => e.attributes), + (attrs, prevAttrs) => { + console.log( + 'deep ', + attrs.map((e) => e.name), + prevAttrs.map((e) => e.name) + ); + }, + { deep: true } +) + +state[0].attributes.name = "Alex"; // Logs: "deep " ["Alex", ""] ["Alex", ""] +``` + +However, watching a reactive Object or Array will always return a reference to the current value of that Object. +To fully watch deeply nested Objects and Arrays, a deep copy of values may be required. This can be achieved with a utility such +as [lodash.cloneDeep](https://lodash.com/docs/4.17.15#cloneDeep) + +```js +import _ from 'lodash'; + +const state = reactive([ + { attributes: { name: "" }, id: 1 }, + { attributes: { name: "" }, id: 2 }, +]); + +watch( + () => state.map((e) => (_.cloneDeep(e.attributes))), + (attrs, prevAttrs) => { + console.log( + attrs.map((e) => e.name), + prevAttrs.map((e) => e.name) + ); + } +); + +state[0].attributes.name = "Alex"; // Logs: ["Alex", ""] ["", ""] +``` ### Shared Behavior with `watchEffect` -`watch` shares behavior with [`watchEffect`](#watcheffect) in terms of [manual stoppage](#stopping-the-watcher), [side effect invalidation](#side-effect-invalidation) (with `onInvalidate` passed to the callback as the 3rd argument instead), [flush timing](#effect-flush-timing) and [debugging](#watcher-debugging). +`watch` shares behavior with [`watchEffect`](#watcheffect) in terms of [manual stoppage](#stopping-the-watcher) +, [side effect invalidation](#side-effect-invalidation) (with `onInvalidate` passed to the callback as the 3rd argument +instead), [flush timing](#effect-flush-timing) and [debugging](#watcher-debugging). From 66613e61f9c22ab6378e7bd7c9487a0e044014d0 Mon Sep 17 00:00:00 2001 From: fimion Date: Mon, 21 Dec 2020 01:29:21 -0500 Subject: [PATCH 4/9] Whitespace --- src/guide/reactivity-computed-watchers.md | 58 ++++++----------------- 1 file changed, 15 insertions(+), 43 deletions(-) diff --git a/src/guide/reactivity-computed-watchers.md b/src/guide/reactivity-computed-watchers.md index c56e452932..0e8248d344 100644 --- a/src/guide/reactivity-computed-watchers.md +++ b/src/guide/reactivity-computed-watchers.md @@ -4,11 +4,7 @@ ## Computed values -Sometimes we need state that depends on other state - in Vue this is handled with -component [computed properties](computed.html#computed-properties). To directly create a computed value, we can use -the `computed` method: it takes a getter function and returns an immutable -reactive [ref](reactivity-fundamentals.html#creating-standalone-reactive-values-as-refs) object for the returned value -from the getter. +Sometimes we need state that depends on other state - in Vue this is handled with component [computed properties](computed.html#computed-properties). To directly create a computed value, we can use the `computed` method: it takes a getter function and returns an immutable reactive [ref](reactivity-fundamentals.html#creating-standalone-reactive-values-as-refs) object for the returned value from the getter. ```js const count = ref(1) @@ -36,9 +32,7 @@ console.log(count.value) // 0 ## `watchEffect` -To apply and _automatically re-apply_ a side effect based on reactive state, we can use the `watchEffect` method. It -runs a function immediately while reactively tracking its dependencies and re-runs it whenever the dependencies are -changed. +To apply and _automatically re-apply_ a side effect based on reactive state, we can use the `watchEffect` method. It runs a function immediately while reactively tracking its dependencies and re-runs it whenever the dependencies are changed. ```js const count = ref(0) @@ -54,9 +48,7 @@ setTimeout(() => { ### Stopping the Watcher -When `watchEffect` is called during a component's [setup()](composition-api-setup.html) function -or [lifecycle hooks](composition-api-lifecycle-hooks.html), the watcher is linked to the component's lifecycle and will -be automatically stopped when the component is unmounted. +When `watchEffect` is called during a component's [setup()](composition-api-setup.html) function or [lifecycle hooks](composition-api-lifecycle-hooks.html), the watcher is linked to the component's lifecycle and will be automatically stopped when the component is unmounted. In other cases, it returns a stop handle which can be called to explicitly stop the watcher: @@ -71,9 +63,7 @@ stop() ### Side Effect Invalidation -Sometimes the watched effect function will perform asynchronous side effects that need to be cleaned up when it is -invalidated (i.e. state changed before the effects can be completed). The effect function receives an `onInvalidate` -function that can be used to register an invalidation callback. This invalidation callback is called when: +Sometimes the watched effect function will perform asynchronous side effects that need to be cleaned up when it is invalidated (i.e. state changed before the effects can be completed). The effect function receives an `onInvalidate`function that can be used to register an invalidation callback. This invalidation callback is called when: - the effect is about to re-run - the watcher is stopped (i.e. when the component is unmounted if `watchEffect` is used inside `setup()` or lifecycle @@ -90,9 +80,7 @@ watchEffect(onInvalidate => { }) ``` -We are registering the invalidation callback via a passed-in function instead of returning it from the callback because -the return value is important for async error handling. It is very common for the effect function to be an async -function when performing data fetching: +We are registering the invalidation callback via a passed-in function instead of returning it from the callback because the return value is important for async error handling. It is very common for the effect function to be an async function when performing data fetching: ```js const data = ref(null) @@ -103,16 +91,11 @@ watchEffect(async (onInvalidate) => { }) ``` -An async function implicitly returns a Promise, but the cleanup function needs to be registered immediately before the -Promise resolves. In addition, Vue relies on the returned Promise to automatically handle potential errors in the -Promise chain. +An async function implicitly returns a Promise, but the cleanup function needs to be registered immediately before the Promise resolves. In addition, Vue relies on the returned Promise to automatically handle potential errors in the Promise chain. ### Effect Flush Timing -Vue's reactivity system buffers invalidated effects and flushes them asynchronously to avoid unnecessary duplicate -invocation when there are many state mutations happening in the same "tick". Internally, a component's `update` function -is also a watched effect. When a user effect is queued, it is by default invoked **before** all component `update` -effects: +Vue's reactivity system buffers invalidated effects and flushes them asynchronously to avoid unnecessary duplicate invocation when there are many state mutations happening in the same "tick". Internally, a component's `update` function is also a watched effect. When a user effect is queued, it is by default invoked **before** all component `update`effects: ```html @@ -142,8 +125,7 @@ In this example: - The count will be logged synchronously on initial run. - When `count` is mutated, the callback will be called **before** the component has updated. -In cases where a watcher effect needs to be re-run **after** component updates, we can pass an additional `options` -object with the `flush` option (default is `'pre'`): +In cases where a watcher effect needs to be re-run **after** component updates, we can pass an additional `options` object with the `flush` option (default is `'pre'`): ```js // fire after component updates so you can access the updated DOM @@ -159,8 +141,7 @@ watchEffect( ) ``` -The `flush` option also accepts `'sync'`, which forces the effect to always trigger synchronously. This is however -inefficient and should be rarely needed. +The `flush` option also accepts `'sync'`, which forces the effect to always trigger synchronously. This is however inefficient and should be rarely needed. ### Watcher Debugging @@ -169,8 +150,7 @@ The `onTrack` and `onTrigger` options can be used to debug a watcher's behavior. - `onTrack` will be called when a reactive property or ref is tracked as a dependency. - `onTrigger` will be called when the watcher callback is triggered by the mutation of a dependency. -Both callbacks will receive a debugger event which contains information on the dependency in question. It is recommended -to place a `debugger` statement in these callbacks to interactively inspect the dependency: +Both callbacks will receive a debugger event which contains information on the dependency in question. It is recommended to place a `debugger` statement in these callbacks to interactively inspect the dependency: ```js watchEffect( @@ -189,9 +169,7 @@ watchEffect( ## `watch` -The `watch` API is the exact equivalent of the component [watch](computed.html#watchers) property. `watch` requires -watching a specific data source and applies side effects in a separate callback function. It also is lazy by default - -i.e. the callback is only called when the watched source has changed. +The `watch` API is the exact equivalent of the component [watch](computed.html#watchers) property. `watch` requires watching a specific data source and applies side effects in a separate callback function. It also is lazy by default - i.e. the callback is only called when the watched source has changed. - Compared to [watchEffect](#watcheffect), `watch` allows us to: @@ -238,8 +216,7 @@ lastName.value = "Smith"; // logs: ["John", "Smith"] ["John", ""] ### Watching Reactive Objects -Using a watcher to compare values of an Array or Object that are reactive requires that it has a copy made of just the -values. +Using a watcher to compare values of an Array or Object that are reactive requires that it has a copy made of just the values. ```js const numbers = reactive([1, 2, 3, 4]) @@ -253,8 +230,7 @@ watch( numbers.push(5) // logs: [1,2,3,4,5] [1,2,3,4] ``` -Attempting to check for changes of properties in a deeply nested Object or Array will -still require the `deep` option to be true, if watching an Object or Array. +Attempting to check for changes of properties in a deeply nested Object or Array will still require the `deep` option to be true, if watching an Object or Array. ```js const state = reactive([ @@ -288,9 +264,7 @@ watch( state[0].attributes.name = "Alex"; // Logs: "deep " ["Alex", ""] ["Alex", ""] ``` -However, watching a reactive Object or Array will always return a reference to the current value of that Object. -To fully watch deeply nested Objects and Arrays, a deep copy of values may be required. This can be achieved with a utility such -as [lodash.cloneDeep](https://lodash.com/docs/4.17.15#cloneDeep) +However, watching a reactive Object or Array will always return a reference to the current value of that Object. To fully watch deeply nested Objects and Arrays, a deep copy of values may be required. This can be achieved with a utility such as [lodash.cloneDeep](https://lodash.com/docs/4.17.15#cloneDeep) ```js import _ from 'lodash'; @@ -315,6 +289,4 @@ state[0].attributes.name = "Alex"; // Logs: ["Alex", ""] ["", ""] ### Shared Behavior with `watchEffect` -`watch` shares behavior with [`watchEffect`](#watcheffect) in terms of [manual stoppage](#stopping-the-watcher) -, [side effect invalidation](#side-effect-invalidation) (with `onInvalidate` passed to the callback as the 3rd argument -instead), [flush timing](#effect-flush-timing) and [debugging](#watcher-debugging). +`watch` shares behavior with [`watchEffect`](#watcheffect) in terms of [manual stoppage](#stopping-the-watcher), [side effect invalidation](#side-effect-invalidation) (with `onInvalidate` passed to the callback as the 3rd argument instead), [flush timing](#effect-flush-timing) and [debugging](#watcher-debugging). From 4f93ae24821c36e4bc2c4c6153f7632edba1cc50 Mon Sep 17 00:00:00 2001 From: fimion Date: Mon, 21 Dec 2020 01:31:31 -0500 Subject: [PATCH 5/9] Whitespace --- src/guide/reactivity-computed-watchers.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/guide/reactivity-computed-watchers.md b/src/guide/reactivity-computed-watchers.md index 0e8248d344..a7e9acbb28 100644 --- a/src/guide/reactivity-computed-watchers.md +++ b/src/guide/reactivity-computed-watchers.md @@ -63,11 +63,10 @@ stop() ### Side Effect Invalidation -Sometimes the watched effect function will perform asynchronous side effects that need to be cleaned up when it is invalidated (i.e. state changed before the effects can be completed). The effect function receives an `onInvalidate`function that can be used to register an invalidation callback. This invalidation callback is called when: +Sometimes the watched effect function will perform asynchronous side effects that need to be cleaned up when it is invalidated (i.e. state changed before the effects can be completed). The effect function receives an `onInvalidate` function that can be used to register an invalidation callback. This invalidation callback is called when: - the effect is about to re-run -- the watcher is stopped (i.e. when the component is unmounted if `watchEffect` is used inside `setup()` or lifecycle - hooks) +- the watcher is stopped (i.e. when the component is unmounted if `watchEffect` is used inside `setup()` or lifecycle hooks) ```js watchEffect(onInvalidate => { @@ -85,8 +84,7 @@ We are registering the invalidation callback via a passed-in function instead of ```js const data = ref(null) watchEffect(async (onInvalidate) => { - onInvalidate(() => { /* ... */ - }) // we register cleanup function before Promise resolves + onInvalidate(() => { /* ... */ }) // we register cleanup function before Promise resolves data.value = await fetchData(props.id) }) ``` @@ -95,7 +93,7 @@ An async function implicitly returns a Promise, but the cleanup function needs t ### Effect Flush Timing -Vue's reactivity system buffers invalidated effects and flushes them asynchronously to avoid unnecessary duplicate invocation when there are many state mutations happening in the same "tick". Internally, a component's `update` function is also a watched effect. When a user effect is queued, it is by default invoked **before** all component `update`effects: +Vue's reactivity system buffers invalidated effects and flushes them asynchronously to avoid unnecessary duplicate invocation when there are many state mutations happening in the same "tick". Internally, a component's `update` function is also a watched effect. When a user effect is queued, it is by default invoked **before** all component `update` effects: ```html From 16dd03da319334969169819049331209027fc3b1 Mon Sep 17 00:00:00 2001 From: Alex Riviere Date: Fri, 25 Dec 2020 04:56:11 -0500 Subject: [PATCH 6/9] Update src/guide/reactivity-computed-watchers.md Co-authored-by: Natalia Tepluhina --- src/guide/reactivity-computed-watchers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guide/reactivity-computed-watchers.md b/src/guide/reactivity-computed-watchers.md index a7e9acbb28..de953f053a 100644 --- a/src/guide/reactivity-computed-watchers.md +++ b/src/guide/reactivity-computed-watchers.md @@ -214,7 +214,7 @@ lastName.value = "Smith"; // logs: ["John", "Smith"] ["John", ""] ### Watching Reactive Objects -Using a watcher to compare values of an Array or Object that are reactive requires that it has a copy made of just the values. +Using a watcher to compare values of an array or object that are reactive requires that it has a copy made of just the values. ```js const numbers = reactive([1, 2, 3, 4]) From a0c8ca813c508009fccda10670e2ee8e0d8999a5 Mon Sep 17 00:00:00 2001 From: Alex Riviere Date: Fri, 25 Dec 2020 04:57:09 -0500 Subject: [PATCH 7/9] Update src/guide/reactivity-computed-watchers.md Co-authored-by: Natalia Tepluhina --- src/guide/reactivity-computed-watchers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guide/reactivity-computed-watchers.md b/src/guide/reactivity-computed-watchers.md index de953f053a..3833805cb9 100644 --- a/src/guide/reactivity-computed-watchers.md +++ b/src/guide/reactivity-computed-watchers.md @@ -262,7 +262,7 @@ watch( state[0].attributes.name = "Alex"; // Logs: "deep " ["Alex", ""] ["Alex", ""] ``` -However, watching a reactive Object or Array will always return a reference to the current value of that Object. To fully watch deeply nested Objects and Arrays, a deep copy of values may be required. This can be achieved with a utility such as [lodash.cloneDeep](https://lodash.com/docs/4.17.15#cloneDeep) +However, watching a reactive object or array will always return a reference to the current value of that object. To fully watch deeply nested objects and arrays, a deep copy of values may be required. This can be achieved with a utility such as [lodash.cloneDeep](https://lodash.com/docs/4.17.15#cloneDeep) ```js import _ from 'lodash'; From 594a0700d068be4d8c3c3bb4430fb53f7b6c3f14 Mon Sep 17 00:00:00 2001 From: Alex Riviere Date: Fri, 25 Dec 2020 04:57:34 -0500 Subject: [PATCH 8/9] Update src/guide/reactivity-computed-watchers.md Co-authored-by: Natalia Tepluhina --- src/guide/reactivity-computed-watchers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guide/reactivity-computed-watchers.md b/src/guide/reactivity-computed-watchers.md index 3833805cb9..f284ff8ac8 100644 --- a/src/guide/reactivity-computed-watchers.md +++ b/src/guide/reactivity-computed-watchers.md @@ -228,7 +228,7 @@ watch( numbers.push(5) // logs: [1,2,3,4,5] [1,2,3,4] ``` -Attempting to check for changes of properties in a deeply nested Object or Array will still require the `deep` option to be true, if watching an Object or Array. +Attempting to check for changes of properties in a deeply nested object or array will still require the `deep` option to be true: ```js const state = reactive([ From d3469796c7c47cfa623e233ce9f2bfa01b899a33 Mon Sep 17 00:00:00 2001 From: fimion Date: Fri, 25 Dec 2020 05:28:30 -0500 Subject: [PATCH 9/9] Simplify examples and update language --- src/guide/reactivity-computed-watchers.md | 56 ++++++++++++----------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/guide/reactivity-computed-watchers.md b/src/guide/reactivity-computed-watchers.md index f284ff8ac8..20c75b62fc 100644 --- a/src/guide/reactivity-computed-watchers.md +++ b/src/guide/reactivity-computed-watchers.md @@ -231,58 +231,62 @@ numbers.push(5) // logs: [1,2,3,4,5] [1,2,3,4] Attempting to check for changes of properties in a deeply nested object or array will still require the `deep` option to be true: ```js -const state = reactive([ - { attributes: { name: "" }, id: 1 }, - { attributes: { name: "" }, id: 2 }, -]); +const state = reactive({ + id: 1, + attributes: { + name: "", + }, +}); watch( - () => state.map((e) => e.attributes), - (attrs, prevAttrs) => { + () => state, + (state, prevState) => { console.log( - 'not deep ', - attrs.map((e) => e.name), - prevAttrs.map((e) => e.name) + "not deep ", + state.attributes.name, + prevState.attributes.name ); } ); watch( - () => state.map((e) => e.attributes), - (attrs, prevAttrs) => { + () => state, + (state, prevState) => { console.log( - 'deep ', - attrs.map((e) => e.name), - prevAttrs.map((e) => e.name) + "deep ", + state.attributes.name, + prevState.attributes.name ); }, { deep: true } -) +); -state[0].attributes.name = "Alex"; // Logs: "deep " ["Alex", ""] ["Alex", ""] +state.attributes.name = "Alex"; // Logs: "deep " "Alex" "Alex" ``` -However, watching a reactive object or array will always return a reference to the current value of that object. To fully watch deeply nested objects and arrays, a deep copy of values may be required. This can be achieved with a utility such as [lodash.cloneDeep](https://lodash.com/docs/4.17.15#cloneDeep) +However, watching a reactive object or array will always return a reference to the current value of that object for both the current and previous value of the state. To fully watch deeply nested objects and arrays, a deep copy of values may be required. This can be achieved with a utility such as [lodash.cloneDeep](https://lodash.com/docs/4.17.15#cloneDeep) ```js import _ from 'lodash'; -const state = reactive([ - { attributes: { name: "" }, id: 1 }, - { attributes: { name: "" }, id: 2 }, -]); +const state = reactive({ + id: 1, + attributes: { + name: "", + }, +}); watch( - () => state.map((e) => (_.cloneDeep(e.attributes))), - (attrs, prevAttrs) => { + () => _.cloneDeep(state), + (state, prevState) => { console.log( - attrs.map((e) => e.name), - prevAttrs.map((e) => e.name) + state.attributes.name, + prevState.attributes.name ); } ); -state[0].attributes.name = "Alex"; // Logs: ["Alex", ""] ["", ""] +state.attributes.name = "Alex"; // Logs: "Alex" "" ``` ### Shared Behavior with `watchEffect`