3-2 Vue application basics

A minimal Vue application

The example p301.html is a ‘bare-bones’ example of a Vue application.

<div id="app">
  <div>1+2*3 = {{ 1+2*3 }}</div>
  <div>It is now {{ (new Date).toLocaleTimeString() }}</div>
</div>

<script>
// define an empty Vue options object
const options = { };

// create a Vue component, mounted to the HTML template
const vm = Vue.createApp(options).mount('#app');
</script>

A Vue application is created using Vue.createApp(). The application contains a root component, which is mounted to a certain element in the document tree. (In this example, the mount point is #app). The data properties of the component is defined in an options object, and the component is rendered according to an HTML template. In this example, the HTML template is embedded inside the mount point. (We’ll show other ways to write the template later in this section.)

In the template, you can use the moustache {{ }} notation to run JavaScript expressions. The result of the expression will be inserted into the template, and shown in the browser display.

Data properties and reactivity

In the next example p302.html, we add some data properties to the view model. This is done by adding a method data() to the options object. Vue calls this method to create reactive proxy of the data properties.

Inside the template, we can display a data property with {{ property_name }} or {{ this.property_name }}. The mustache notation can be used in the content of HTML elements, but not as attribute value. To bind an HTML attribute to a data property, use v-bind:attr or the shorthand notation :attr.

Both {{ }} and v-bind respond to changes in data property. This is an important feature of Vue called reactivity. We only need to write the template once. When some data properties are updated, Vue will update the document tree efficiently to reflect the changes.

<div id="app">
  <img :src='conditionURL' style='float: left; padding-right: 1em'>
  <div>Temperature: {{ temperature }}°C</div>
  <div>Rain: {{ rain }}%</div>
</div>

<script>
// define a Vue options object
const weather = {
  data() {
    return {
      temperature: 28, rain: 20, conditionURL: 'image/sunny.png'
    }
  }
};

// create a Vue component, mounted to the HTML template
const vm = Vue.createApp(weather).mount('#app');
</script>

This example also shows two other ways to write templates of Vue. Example p302-a.html provides the template as the string value of the template property of the options object. Example p302-b.html embeds the template in the HTML document using the <script type="text/x-template"> tags, and uses the template property to refer to the template text in the <script> tag.

Binding to expression and style binding

Sometimes, it is not enough to bind a HTML attribute to a data property alone. You can implement simple logic with an expression in the binding to an attribute. In addition, the style and class attributes of HTML can bind to JavaScript objects. (For more detail about style and class bindings, please refer to the online reference.) The first excerpt from example p303.html below demonstrates this.

<div id="app">
  <div>
    Temperature: 
    <span :style="styleTemperature">{{ temperature }}°C</span>
    <img :src="temperature>=14 ? 'image/high-temp.png' : 'image/low-temp.png'">
  </div>
  <!-- some content omitted -->
</div>

<script>
const weather = {
  data() {
    return {
      temperature: 28, 
      styleTemperature: { fontWeight: 'bold', color: 'orange' },
      rain: 10, 
    }
  }
  // the computed properties are omitted
};

const vm = Vue.createApp(weather).mount('#app');
</script>

When the bound values involve more complicated logic, you can define computed properties by writing methods in the computed property. (online reference Computed properties work as read-only properties of the view model / component. When you define a computed property, you can refer to data property through this.

<div id="app">
  <!-- some content omitted -->
  <div>Rain: 
    <span :style="styleRain">{{ rain }}%</span>
    <img :src="rainImageURL">
  </div>
</div>

<script>
// define a Vue options object
const weather = {
  data() {
    return {
      temperature: 28, 
      styleTemperature: { fontWeight: 'bold', color: 'orange' },
      rain: 10, 
    }
  },
  computed: {
    styleRain() {
      const r = parseFloat(this.rain);
      let color;
      if (r < 30) {
        color = { color: 'yellow', backgroundColor: 'lightblue' }
      } else if (r < 70) {
        color = { color: 'red', backgroundColor: 'lightgreen' }
      } else {
        color = { color: 'black', backgroundColor: 'lightgray' }
      }
      return {
        ...color, padding: '0em 1em'
      };
    },
    rainImageURL() {
      const r = parseFloat(this.rain);
      if (r < 30) return 'image/rainy-1.png';
      if (r < 70) return 'image/rainy-2.png';
      return 'image/rainy-3.png';
    }
  }
};

// create a Vue component, mounted to the HTML template
const vm = Vue.createApp(weather).mount('#app');
</script>