--- outline: deep --- # Reactivity Fundamentals {#reactivity-fundamentals} :::tip API Preference This page and many other chapters later in the guide contain different content for the Options API and the Composition API. Your current preference is Options APIComposition API. You can toggle between the API styles using the "API Preference" switches at the top of the left sidebar. :::
## Declaring Reactive State \* {#declaring-reactive-state} With the Options API, we use the `data` option to declare reactive state of a component. The option value should be a function that returns an object. Vue will call the function when creating a new component instance, and wrap the returned object in its reactivity system. Any top-level properties of this object are proxied on the component instance (`this` in methods and lifecycle hooks): ```js{2-6} export default { data() { return { count: 1 } }, // `mounted` is a lifecycle hook which we will explain later mounted() { // `this` refers to the component instance. console.log(this.count) // => 1 // data can be mutated as well this.count = 2 } } ``` [Try it in the Playground](https://play.vuejs.org/#eNpFUNFqhDAQ/JXBpzsoHu2j3B2U/oYPpnGtoetGkrW2iP/eRFsPApthd2Zndilex7H8mqioimu0wY16r4W+Rx8ULXVmYsVSC9AaNafz/gcC6RTkHwHWT6IVnne85rI+1ZLr5YJmyG1qG7gIA3Yd2R/LhN77T8y9sz1mwuyYkXazcQI2SiHz/7iP3VlQexeb5KKjEKEe2lPyMIxeSBROohqxVO4E6yV6ppL9xykTy83tOQvd7tnzoZtDwhrBO2GYNFloYWLyxrzPPOi44WWLWUt618txvASUhhRCKSHgbZt2scKy7HfCujGOqWL9BVfOgyI=) These instance properties are only added when the instance is first created, so you need to ensure they are all present in the object returned by the `data` function. Where necessary, use `null`, `undefined` or some other placeholder value for properties where the desired value isn't yet available. It is possible to add a new property directly to `this` without including it in `data`. However, properties added this way will not be able to trigger reactive updates. Vue uses a `$` prefix when exposing its own built-in APIs via the component instance. It also reserves the prefix `_` for internal properties. You should avoid using names for top-level `data` properties that start with either of these characters. ### Reactive Proxy vs. Original \* {#reactive-proxy-vs-original} In Vue 3, data is made reactive by leveraging [JavaScript Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy). Users coming from Vue 2 should be aware of the following edge case: ```js export default { data() { return { someObject: {} } }, mounted() { const newObject = {} this.someObject = newObject console.log(newObject === this.someObject) // false } } ``` When you access `this.someObject` after assigning it, the value is a reactive proxy of the original `newObject`. **Unlike in Vue 2, the original `newObject` is left intact and will not be made reactive: make sure to always access reactive state as a property of `this`.**
## Declaring Reactive State \*\* {#declaring-reactive-state-1} ### `ref()` \*\* {#ref} In Composition API, the recommended way to declare reactive state is using the [`ref()`](/api/reactivity-core#ref) function: ```js import { ref } from 'vue' const count = ref(0) ``` `ref()` takes the argument and returns it wrapped within a ref object with a `.value` property: ```js const count = ref(0) console.log(count) // { value: 0 } console.log(count.value) // 0 count.value++ console.log(count.value) // 1 ``` > See also: [Typing Refs](/guide/typescript/composition-api#typing-ref) To access refs in a component's template, declare and return them from a component's `setup()` function: ```js{5,9-11} import { ref } from 'vue' export default { // `setup` is a special hook dedicated for the Composition API. setup() { const count = ref(0) // expose the ref to the template return { count } } } ``` ```vue-html
{{ count }}
``` Notice that we did **not** need to append `.value` when using the ref in the template. For convenience, refs are automatically unwrapped when used inside templates (with a few [caveats](#caveat-when-unwrapping-in-templates)). You can also mutate a ref directly in event handlers: ```vue-html{1} ``` For more complex logic, we can declare functions that mutate refs in the same scope and expose them as methods alongside the state: ```js{7-10,15} import { ref } from 'vue' export default { setup() { const count = ref(0) function increment() { // .value is needed in JavaScript count.value++ } // don't forget to expose the function as well. return { count, increment } } } ``` Exposed methods can then be used as event handlers: ```vue-html{1} ``` Here's the example live on [Codepen](https://codepen.io/vuejs-examples/pen/WNYbaqo), without using any build tools. ### ` ``` [Try it in the Playground](https://play.vuejs.org/#eNo9jUEKgzAQRa8yZKMiaNcllvYe2dgwQqiZhDhxE3L3jrW4/DPvv1/UK8Zhz6juSm82uciwIef4MOR8DImhQMIFKiwpeGgEbQwZsoE2BhsyMUwH0d66475ksuwCgSOb0CNx20ExBCc77POase8NVUN6PBdlSwKjj+vMKAlAvzOzWJ52dfYzGXXpjPoBAKX856uopDGeFfnq8XKp+gWq4FAi) Top-level imports, variables and functions declared in `