-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: added composition API reference * fix: changed define component link * Update src/api/composition-api.md Co-authored-by: Rahul Kadyan <hi@znck.me> * Update src/api/composition-api.md Co-authored-by: Rahul Kadyan <hi@znck.me> * feat: added composition API reference * fix: changed define component link * fix: move arguments above usecases * feat: added example for attrs destructuring * fix: fixed `this` usage explanation * feat: added explanation about inline event handler * fix: added example to `isReactive` * fix: grammar * fix: grammar * fix: removed raw values mention * Addressed reviewers comments * feat: moved reactivity APIs * feat: moved reactivity utilities * feat: separated advanced reactivity apis * fix: fixed indentation * fix: refactored reactivity API structure * feat: added links to composition API * fix: renamed proxy APIs to basic * fix: fixed reactive typing * fix: addressed reviewers comments * fix: added async onInvalidate * feat: added example for generic with unknown type * fix: fixed cleanup example * fix: removed warning Co-authored-by: Rahul Kadyan <hi@znck.me>
- Loading branch information
1 parent
9efd692
commit 189453f
Showing
5 changed files
with
1,159 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
# Basic Reactivity APIs | ||
|
||
> This section uses [single-file component](TODO: SFC) syntax for code examples | ||
## `reactive` | ||
|
||
Returns a reactive copy of the object. | ||
|
||
```js | ||
const obj = reactive({ count: 0 }) | ||
``` | ||
|
||
The reactive conversion is "deep"—it affects all nested properties. In the [ES2015 Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) based implementation, the returned proxy is **not** equal to the original object. It is recommended to work exclusively with the reactive proxy and avoid relying on the original object. | ||
|
||
### Typing | ||
|
||
```ts | ||
function reactive<T extends object>(target: T): UnwrapNestedRefs<T> | ||
``` | ||
|
||
## `readonly` | ||
|
||
Takes an object (reactive or plain) or a [ref](./refs-api.html#ref) and returns a readonly proxy to the original. A readonly proxy is deep: any nested property accessed will be readonly as well. | ||
|
||
```js | ||
const original = reactive({ count: 0 }) | ||
const copy = readonly(original) | ||
watchEffect(() => { | ||
// works for reactivity tracking | ||
console.log(copy.count) | ||
}) | ||
// mutating original will trigger watchers relying on the copy | ||
original.count++ | ||
// mutating the copy will fail and result in a warning | ||
copy.count++ // warning! | ||
``` | ||
|
||
## `isProxy` | ||
|
||
Checks if an object is a proxy created by [`reactive`](#reactive) or [`readonly`](#readonly). | ||
|
||
## `isReactive` | ||
|
||
Checks if an object is a reactive proxy created by [`reactive`](#reactive). | ||
|
||
```js | ||
import { reactive, isReactive } from 'vue' | ||
export default { | ||
setup() { | ||
const state = reactive({ | ||
name: 'John' | ||
}) | ||
console.log(isReactive(state)) // -> true | ||
} | ||
} | ||
``` | ||
|
||
It also returns `true` if the proxy is created by [`readonly`](#readonly), but is wrapping another proxy created by [`reactive`](#reactive). | ||
|
||
```js{7-15} | ||
import { reactive, isReactive, readonly } from 'vue' | ||
export default { | ||
setup() { | ||
const state = reactive({ | ||
name: 'John' | ||
}) | ||
// readonly proxy created from plain object | ||
const plain = readonly({ | ||
name: 'Mary' | ||
}) | ||
console.log(isReactive(plain)) // -> false | ||
// readonly proxy created from reactive proxy | ||
const stateCopy = readonly(state) | ||
console.log(isReactive(stateCopy)) // -> true | ||
} | ||
} | ||
``` | ||
|
||
## `isReadonly` | ||
|
||
Checks if an object is a readonly proxy created by [`readonly`](#readonly). | ||
|
||
## `toRaw` | ||
|
||
Returns the raw, original object of a [`reactive`](#reactive) or [`readonly`](#readonly) proxy. This is an escape hatch that can be used to temporarily read without incurring proxy access/tracking overhead or write without triggering changes. It is **not** recommended to hold a persistent reference to the original object. Use with caution. | ||
|
||
```js | ||
const foo = {} | ||
const reactiveFoo = reactive(foo) | ||
console.log(toRaw(reactiveFoo) === foo) // true | ||
``` | ||
|
||
## `markRaw` | ||
|
||
Marks an object so that it will never be converted to a proxy. Returns the object itself. | ||
|
||
```js | ||
const foo = markRaw({}) | ||
console.log(isReactive(reactive(foo))) // false | ||
// also works when nested inside other reactive objects | ||
const bar = reactive({ foo }) | ||
console.log(isReactive(bar.foo)) // false | ||
``` | ||
|
||
::: warning | ||
`markRaw` and the shallowXXX APIs below allow you to selectively opt-out of the default deep reactive/readonly conversion and embed raw, non-proxied objects in your state graph. They can be used for various reasons: | ||
|
||
- Some values simply should not be made reactive, for example a complex 3rd party class instance, or a Vue component object. | ||
|
||
- Skipping proxy conversion can provide performance improvements when rendering large lists with immutable data sources. | ||
|
||
They are considered advanced because the raw opt-out is only at the root level, so if you set a nested, non-marked raw object into a reactive object and then access it again, you get the proxied version back. This can lead to **identity hazards** - i.e. performing an operation that relies on object identity but using both the raw and the proxied version of the same object: | ||
|
||
```js | ||
const foo = markRaw({ | ||
nested: {} | ||
}) | ||
|
||
const bar = reactive({ | ||
// although `foo` is marked as raw, foo.nested is not. | ||
nested: foo.nested | ||
}) | ||
|
||
console.log(foo.nested === bar.nested) // false | ||
``` | ||
|
||
Identity hazards are in general rare. However, to properly utilize these APIs while safely avoiding identity hazards requires a solid understanding of how the reactivity system works. | ||
::: | ||
|
||
## `shallowReactive` | ||
|
||
Creates a reactive proxy that tracks reactivity of its own properties but does not perform deep reactive conversion of nested objects (exposes raw values). | ||
|
||
```js | ||
const state = shallowReactive({ | ||
foo: 1, | ||
nested: { | ||
bar: 2 | ||
} | ||
}) | ||
|
||
// mutating state's own properties is reactive | ||
state.foo++ | ||
// ...but does not convert nested objects | ||
isReactive(state.nested) // false | ||
state.nested.bar++ // non-reactive | ||
``` | ||
|
||
## `shallowReadonly` | ||
|
||
Creates a proxy that makes its own properties readonly, but does not perform deep readonly conversion of nested objects (exposes raw values). | ||
|
||
```js | ||
const state = shallowReadonly({ | ||
foo: 1, | ||
nested: { | ||
bar: 2 | ||
} | ||
}) | ||
|
||
// mutating state's own properties will fail | ||
state.foo++ | ||
// ...but works on nested objects | ||
isReadonly(state.nested) // false | ||
state.nested.bar++ // works | ||
``` |
Oops, something went wrong.