A Vue component without JavaScript consists of static HTML elements. The structure of the page and the data displayed on the page is not intended to change. When we add JavaScript to a component we encode actions that are performed when the user interacts with the visual component (the view). These actions can then alter the values of variables that have been declared, which in turn can alter the structure of the component (the HTML), the appearance of the component (e.g. CSS changes), and the information that is displayed. The variables that we declare in the JavaScript which determine how and what HTML is rendered are called state variables. The value of the set of state variables at any particular point in time is called the state of the component. The State Management guide in the Vue documentation has a great diagram showing the circular relationship between the state, the view, and the actions.
You may have heard that Vue is a reactive framework. What does this mean?
The Vue framework defines a particular syntax for specifying in a HTML template how a view should be rendered based on the values of the state variables. This special syntax removes the need for developer to write JavaScript functions that manually modify the DOM when the value in a state variable changes. Instead, Vue, behind the scenes, automatically and continuously, monitors the state of the component and if a state variable is modified, reacts by automatically modifying the part of the DOM that is dependent on the state variable.
Later in the course we’ll discuss how that state of one component can affect the state of another, but for now let’s investigate a single independent component. We’ll show how to define a component’s state variables and how we can annotate the template to make the view dependent on state variables.
Defining and Using State Variables
We can write the JavaScript code for a component using either the Options API or the newer Composition API. We’ll be using the Composition API.
To declare reactive state variables using Composition, since we are using a build process, we can specifying that we are using Composition by including the word setup in our opening script tag.
<script setup> ... </script>
When we do this, all top-level imports, functions, and variables declared in the <script setup> are accessible within the component’s template.
If we are not using a build process we would have to export a setup() function (see the Vue documentation for more information).
Now inside the script we can either declare state variables using ref() or reactive(). Each has its benefits and limitations. Let’s first look at ref().
Using ref() to Register State Variables
To use ref() we first need to import ref from ‘vue’. The function ref() takes a value of any type as an argument, creates a ref object with a property named value and returns the ref object. The ref object’s value property is reactive and monitored by Vue.
In the example below we create a constant named count that holds a ref object which hold the value 0. We can then use the value property to retrieve and modify its value.
<script setup> import { ref } from 'vue' const count = ref(1) console.log(count.value) // 1 function increment() { count.value++ } </script>
Below we show how an exposed function (increment) and the ref (count) can be used in a template. Note how easy it is to register a button handler in Vue and how we use mustache syntax to embed the value of a state variable.
<template> <button @click="increment"> {{ count }} </button> </template>
Notice that in order to display the value held in the ref we don’t specify count.value but rather just specify the name of the ref. This is because Vue automatically unwraps refs in templates if the top-level object referenced is a ref.
Just to go back to our original discussion. You see in this example that the action (button press) modifies a reactive state variable (count) which is monitored by Vue and since the variable is used in the DOM, when its value is changed Vue automatically updates the DOM. This is the power of a reactive framework.
As we noted earlier, we can use ref() on any type value including objects and arrays.
const address = ref({ street: "123 Main Street", city: "Bridgewater", state: "VA" })
When we use address in a template we can reference its properties individually.
<span> {{addr.street }} {{addr.city }}, {{addr.state }} </span>
function changeAll() { addr.value = { street: "456 Water Street", city: "Winthrop", state: "NY" } }
function changeState() { addr.value.state = "WI" }
const name = { first: ref("Jesse"), last: ref("Martinez") }
<span> {{ name.first.value }}, {{ name.last.value }} </span>
function toggleName() { name.first.value = (name.first.value === "Jesse") ? "Mary" : "Jesse" }
<buttonclass="btn btn-primary" @click="toggleName"> Toggle </button>
Using reactive() to Register State Variables
<script setup> import { reactive } from 'vue' ...
const song = reactive({ title: "Sunflower", artist: ["Post Malone", "Swae Lee"] })
song.producer = ["Carter Lang", "Louis Bell"]
function changeTitle(t) { t = "I Like You" } function updateTitle() { changeTitle(song.title) // does not change title in proxy }
Further Reading
© 2023, Eric.