exhtml
3/19/2020 - 2:30 PM

(raw) Vue Snippets - Basics

Basics

...

Class/style bindings

Always use a computed property when possible:

<div v-bind:class="classObject"></div>

data: {
  isActive: true,
  error: null
},
computed: {
  classObject: function () {
    return {
      active: this.isActive && !this.error,
      'text-danger': this.error && this.error.type === 'fatal'
    }
  }
}

Inline object:

<div class="static"
     v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>

Array syntax:

<div v-bind:class="[{ active: isActive }, errorClass]"></div>

Inline styles with computed property:

<div v-bind:style="styleObject"></div>
data: {
  styleObject: {
    color: 'red',
    fontSize: '13px'
  }
}

or inline object:

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

Conditional rendering

  • v-if if the condition is unlikely to change at runtime.
  • v-show if you need to toggle something very often or for a lot of elements.
  • Don't use v-if and v-for together

Example use with if/else:

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address">
</template>

Vue tries to render elements as efficiently as posible, so the <input> won't be replaced, just the placeholder. If you want to avoid this, add a key attribute with unique values:

<input placeholder="Enter your username" key="username-input">

List rendering

Iterating through an array

To give Vue a hint so that it can track each node’s identity when reusing and reordering existing elements, provide a unique key attribute for each item wherever possible:

<ul id="example-2">
  <li v-for="(item, index) in items" v-bind:key="item.id">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>
//...
  data: {
    parentMessage: 'Parent',
    items: [
      { message: 'Foo', id: 5 },
      { message: 'Bar', id: 6 }
    ]
  }

You can also use v-for="item of items, more closer to javascript syntax for iterators.

Array change detection:

  • Array’s mutation methods (push() / pop() / shift() / unshift() / splice() / sort() / reverse()) mutate the original array they are called on, so will also trigger view updates
  • For non-mutating methods (filter() / concat() / slice()) you can replace the old array with the new one returned: this.items = this.items.filter(...)
  • If you need no change a value of an item by index: this.items[2] = newValue (not detected by Vue) you can use Vue.set(this.items, 2, newValue)

Iterating through properties of an object

<div v-for="(value, key, index) in object">
  {{ index }}. {{ key }}: {{ value }}
</div>

//...
  data: {
    object: {
      firstName: 'John',
      lastName: 'Doe',
      age: 30
    }
  }

*When iterating over an object, the order is based on the key enumeration order of Object.keys(), which is not guaranteed to be consistent across JavaScript engine implementations.

Object change detection:

  • Vue cannot detect property addition or deletion: Vue does not allow dynamically adding new root-level reactive properties (data object) to an already created instance
var vm = new Vue({
  data: {
    a: 1
  }
})
vm.b = 2 //this new property won't be reactive
  • But you can add reactive properties to a nested object:
var vm = new Vue({
  data: {
    userProfile: {
      name: 'Anika'
    }
  }
})
Vue.set(vm.userProfile, 'age', 27)

If you want to assign several new properties to an existing object, you should create a fresh object with properties from both objects:

vm.userProfile = Object.assign({}, vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

Filtering/sorting

  • Create a computed property (ensure you don't mutate the original data)
<li v-for="n in evenNumbers">{{ n }}</li>
data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
  evenNumbers: function () {
    return this.numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}
  • In a situation where computed properties are not feasible, use a method:
<li v-for="n in even(numbers)">{{ n }}</li>
//...
methods: {
  even: function (numbers) {
    return numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

Other cases

  • v-for on a custom component (a key is required):
<my-component
  v-for="(item, index) in items"
  v-bind:item="item"
  v-bind:index="index"
  v-bind:key="item.id"
></my-component>
  • use the is attribute where you need valid HTML to avoid browser parsing error:
<ul>
    <li
        is="todo-item" <!-- same than <todo-item> -->
        v-for="(todo, index) in todos"
        v-bind:key="todo.id"
        v-bind:title="todo.title"
        v-on:remove="todos.splice(index, 1)"
    ></li>
</ul>
  • use v-for on a <template> to render a block of multiple elements.
<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>
  • v-for with a Range:
<span v-for="n in 10">{{ n }} </span> //will repeat the template that many times.
  • v-for has a higher priority than v-if:
<li v-for="todo in todos" v-if="!todo.isComplete"> //v-if will be run on each iteration of the loop separately
  {{ todo }}
</li>

Event handling

(...)