Vue Data Binding

Data binding is one of Vue's core features. It establishes a connection between component state (data) and the rendered DOM view. When data changes, the view updates automatically, and vice versa (when using v-model).

Vue provides multiple types of data binding:

1. Text Interpolation

This is the most basic form of data binding, using double curly braces {{ }} syntax. It inserts data as plain text into the content of an element.

<script setup>
import { ref } from 'vue'

const message = ref('Hello, Vue!')
</script>

<template>
  <span>{{ message }}</span>
</template>

2. Attribute Binding

Double curly braces cannot be used in HTML attributes. To dynamically bind one or more attributes, you need to use the v-bind directive, usually abbreviated as a colon :.

<script setup>
import { ref } from 'vue'

const imageId = ref('main-logo')
const isButtonDisabled = ref(true)
</script>

<template>
  <div :id="imageId"></div>
  <button :disabled="isButtonDisabled">Click me</button>
</template>

This also applies to binding boolean-type attributes. If isButtonDisabled's value is true, the disabled attribute will be included in the <button> element; if false, the attribute will be removed.

3. Class and Style Binding

Vue provides enhanced binding functionality for the class and style attributes because they are common scenarios for data-driven styling. v-bind can accept strings, objects, or arrays.

Binding Class

<script setup>
import { ref, reactive } from 'vue'

const isActive = ref(true)
const hasError = ref(false)

const classObject = reactive({
  active: true,
  'text-danger': false
})
</script>

<template>
  <!-- Object syntax -->
  <div :class="{ active: isActive, 'text-danger': hasError }"></div>
  <div :class="classObject"></div>

  <!-- Array syntax -->
  <div :class="[isActive ? 'active' : '', 'errorClass']"></div>
</template>

Binding Style

<script setup>
import { ref, reactive } from 'vue'

const activeColor = ref('red')
const fontSize = ref(30)

const styleObject = reactive({
  color: 'red',
  fontSize: '13px'
})
</script>

<template>
  <!-- Object syntax -->
  <div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
  <div :style="styleObject"></div>

  <!-- Array syntax (can apply multiple style objects to one element) -->
  <div :style="[baseStyles, overridingStyles]"></div>
</template>

4. Form Input Binding

For form elements, we can use the v-model directive to create two-way data binding. This means that when a user types content in an input box, the bound data updates synchronously; conversely, when the data changes, the input box's content also updates.

<script setup>
import { ref } from 'vue'

const text = ref('')
const checked = ref(false)
const selected = ref('')
</script>

<template>
  <!-- Text input -->
  <input v-model="text">
  <p>Text is: {{ text }}</p>

  <!-- Checkbox -->
  <input type="checkbox" v-model="checked">
  <label>Checked: {{ checked }}</label>

  <!-- Radio buttons -->
  <input type="radio" value="One" v-model="picked">
  <input type="radio" value="Two" v-model="picked">

  <!-- Dropdown -->
  <select v-model="selected">
    <option disabled value="">Please select one</option>
    <option>A</option>
    <option>B</option>
  </select>
  <span>Selected: {{ selected }}</span>
</template>

v-model intelligently uses different properties and events to work based on different input element types (for example, value and input events for text boxes, checked and change events for checkboxes).