Categories
JavaScript Vue

Vue.js Basics — The Vue Instance

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look more closely at the Vue instance, including how to define it and some properties of it.

Characteristics of the Vue Instance

Each Vue.js app begins by defining a new Vue instance. The Vue constructor takes an options object that takes various properties.

We often use vm to refer to a Vue instance, where vm stands for ViewModel.

A Vue app roughly follows the Model-View-ViewModel pattern, where the ViewModel has the business logic of the app, View has the markup that users see, and Model has the data.

For example, we can define a Vue instance as follows:

const vm = new Vue({ });

Each Vue app consists of a root Vue instance and it’s created with new Vue . We can organize it in a tree for easier maintenance.

Data and Methods

The options object that pass into the Vue constructor can have data and methods.

For example, if we define a Vue instance as follows:

const vm = new Vue({  
  el: "#app",  
  data: { foo: "bar" }  
});

Then when we add:

console.log(vm.foo);

below our vm definition, we get 'bar' since data.foo has the value 'bar' .

In other words, if we have:

const data = { foo: "bar" };  
const vm = new Vue({  
  el: "#app",  
  data  
});  
console.log(vm.foo === data.foo);

Then the console.log will log true .

When the data changes, the app will re-render with the new data.

If we create a new property in vm and set it as follows:

let data = { foo: "bar" };  
const vm = new Vue({  
  el: "#app",  
  data  
});  
vm.a = 1;

The app won’t re-render. On the other hand, if we write:

let data = { foo: "bar", a: 1 };  
const vm = new Vue({  
  el: "#app",  
  data  
});

Then the app will re-render. This means that we have to put our data that we want to render in the data field.

If we freeze the object that we pass to data with Object.freeze() , then the Vue app won’t re-render since properties can’t be changed, so new changes can’t propagate since they aren’t set in the object.

So if we have:

let data = { foo: "bar", a: 1 };  
Object.freeze(data);  
const vm = new Vue({  
  el: "#app",  
  data  
});

No changes can be made after the initial render since we froze data with Object.freeze .

The Vue instance also exposes a number of instance properties and methods.

They’re prefixed with the $ so that we know they’re part of the Vue instance.

$el

We have the $el property to get the DOM element that the Vue instance resides in.

For example, if we have:

let data = { foo: "bar" };  
const vm = new Vue({  
  el: "#app",  
  data  
});

console.log(vm.$el === document.getElementById("app"));

Then the console.log will log true since our Vue instance resides in an element with ID app .

$data

The $data property will get us the value of the data property that we set in the options object that we passed into the Vue constructor.

So if we have:

let data = { foo: "bar" };  
const vm = new Vue({  
  el: "#app",  
  data  
});

console.log(vm.$data === data);

Then we get true from the console.log since data references the same object as vm.$data since we set it as the value of the data property of the options object that we passed into the Vue constructor.

$watch

$watch is an instance method that lets us watch for changes in the data object that we set as the value of the options object.

For example, if we have:

let data = { foo: "bar" };  
const vm = new Vue({  
  el: "#app",  
  data  
});

vm.$watch("foo", (newValue, oldValue) => {  
  console.log(newValue, oldValue);  
});

in src/index.js and:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>Hello</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <input type="text" v-model="foo" />  
    </div>  
    <script src="./src/index.js"></script>  
  </body>  
</html>

in index.html . Then when we type in something to the input box, we should get some console.log output from:

vm.$watch("foo", (newValue, oldValue) => {  
  console.log(newValue, oldValue);  
});

This is because changes are constantly being watched in the data.foo property. v-model automatically updates the value for foo as we type into the box.

So as we’re typing, the changes to foo are being watched and it’s logged by the handler function that we passed into the $watch method.

Conclusion

The Vue instance is created by passing in an options object with the data , el , and methods properties to the Vue constructor. It returns an instance of our Vue app.

The instance has the $el property to get the DOM element that our app resides in.

Also, there’s the $data property to get the value of the data property to get the data that we set when we pass it in as the value of the data property of the options object.

Finally, we have the $watch method to watch for changes in our data.

Categories
JavaScript Vue

List Rendering with Vue.js — Array Change Detection

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at Vue’s array change detection capabilities.

Array Change Detection

Vue wraps the following array mutation methods so that when these methods are called, a view update will be triggered. They’re the following:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

For example, if we have a button that triggers a push of a new item to an array, it’ll update:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    persons: [{ name: "Joe" }, { name: "Jane" }]  
  },  
  methods: {  
    addPerson() {  
      this.persons.push({ name: "Mary" });  
    }  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <button @click="addPerson">Add Person</button>  
      <div v-for="person in persons">  
        {{person.name}}  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then we get:

JoeJane

When the array is first rendered. Then when we click Add Button, we get:

JoeJaneMary

since we called the addPerson method with the button click, which called the push method to add a new entry.

Replacing an Array

Non-mutating array method are ones that always return a new array. We can replace the original array with the returned array to trigger a view update.

Vue doesn’t re-render the list from scratch when we update the array. Instead, it’ll try to maximum DOM element reuse.

For example, if we have the following:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    persons: [{ name: "Joe" }, { name: "Jane" }, { name: "Mary" }]  
  },  
  methods: {  
    filterPerson() {  
      this.persons = this.persons.filter(p => p.name !== "Joe");  
    }  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js)"></script>  
  </head> <body>  
    <div id="app">  
      <button @click="filterPerson">Filter Person</button>  
      <div v-for="person in persons">  
        {{person.name}}  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then when our page first loads, we get the following names:

JoeJaneMary

Once we click Filter Person, we get:

JaneMary

since we called the filterPerson method with the button click, which called the filter method to return an array with the filtered items.

Then the new array is assigned to this.persons and then the view is refreshed.

Catches

Vue can’t detect directly assign an item to an array by setting the index or when the length of the array is modified.

So:

vm.item[indexOfItem] = 'item';

and:

vm.items.length = 2;

won’t be picked up by Vue and update the view with updated data.

We can either call Vue.set or splice to set an entry to a given index.

Vue.set

For example, we can write the following code:

src/index.js

new Vue({  
  el: "#app",  
  data: {  
    persons: ["Joe", "Mary"]  
  },  
  methods: {  
    addPerson() {  
      Vue.set(this.persons, 5, "Jane");  
    }  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js)"></script>  
  </head> <body>  
    <div id="app">  
      <button @click="addPerson">Add Person</button>  
      <div v-for="(person, index) in persons">  
        {{index}} - {{person}}  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

When the page first loads, we get the following entries rendered:

0 - Joe1 - Mary

Then when we click Add Person, we get:

0 - Joe1 - Mary2 -3 -4 -5 - Jane

Splice

We can do the same with splice , but the length has to be set first:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    persons: ["Joe", "Mary"]  
  },  
  methods: {  
    addPerson() {  
      this.persons.length = 5;  
      this.persons.splice(5, 1, "Jane");  
    }  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <button @click="addPerson">Add Person</button>  
      <div v-for="(person, index) in persons">  
        {{index}} - {{person}}  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then we get the same results as before.

We can also use splice to set the length of the array and trigger view update. To do this, we can write:

this.persons.splice(5);

vm.$set

We can call vm.$set as follows, which is the same as Vue.set except that it’s available to the Vue instance instead of a global object.

For example, we can write:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    persons: ["Joe", "Mary"]  
  },  
  methods: {  
    addPerson() {  
      this.$set(this.persons, 5, "Jane");  
    }  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <button @click="addPerson">Add Person</button>  
      <div v-for="(person, index) in persons">  
        {{index}} - {{person}}  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Conclusion

Some array changes will trigger view updates automatically.

Array mutation method calls are watched to update the view.

Array methods that return new arrays have to treated differently from mutation methods. The returned value has to be assigned to the original variable to trigger a view update.

To trigger view update when we assign an entry to an array index, we can use splice , Vue.set , or this.$set / vm.$set.

To set the array’s length and trigger view updates, we can also call splice .

Categories
JavaScript Vue

Vue.js Transition Effects — Transitioning Between Elements

Transitioning Between Elements

With Vue, we can transition elements between v-if and v-else .

When toggling between elements that have the same tag name, we must tell Vue that they’re distinct elements giving them unique key attributes. Otherwise, the Vue compiler will only replace the content of the element for efficiency.

It’s always a good idea to key multiple items within a transition element.

For example, we can transition between 2 p elements as follows:

src/index.js :

new Vue({  
  el: "#app",  
  data: { show: false }  
});

src/style.css :

.fade-enter-active,  
.fade-leave-active {  
  transition: opacity 0.5s;  
}  
.fade-enter,  
.fade-leave-to {  
  opacity: 0;  
}

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
    <link  
      rel="stylesheet"  
      type="text/css"  
      href="./src/styles.css"  
      media="screen"  
    />  
  </head>  
  <body>  
    <div id="app">  
      <button v-on:click="show = !show">  
        Toggle  
      </button>  
      <transition name="fade">  
        <p v-if="show" key="hi">hi</p>  
        <p v-else key="bye">bye</p>  
      </transition>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then we should see fade effects when we transition between ‘hi’ and ‘bye’.

We added key attributes to each so they’ll always be rendered from scratch.

Also, we can use the key attribute to transition between different states of the same element.

We can do that as follows:

src/index.js :

new Vue({  
  el: "#app",  
  data: { show: false }  
});

src/styles.css :

.fade-enter-active,  
.fade-leave-active {  
  transition: opacity 0.5s;  
}  
.fade-enter,  
.fade-leave-to {  
  opacity: 0;  
}

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
    <link  
      rel="stylesheet"  
      type="text/css"  
      href="./src/styles.css"  
      media="screen"  
    />  
  </head>  
  <body>  
    <div id="app">  
      <button v-on:click="show = !show">  
        Toggle  
      </button>  
      <transition name="fade">  
        <p v-bind:key="show">  
          {{ show ? 'hi' : 'bye' }}  
        </p>  
      </transition>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, we replaced:

<transition name="fade">  
  <p v-if="show" key="hi">hi</p>  
  <p v-else key="bye">bye</p>  
</transition>

with:

<transition name="fade">  
  <p v-bind:key="show">  
    {{ show ? 'hi' : 'bye' }}  
  </p>  
</transition>

Everything else remained the same.

The transition can be done between any number of elements with v-if or binding a single element to a dynamic property.

For example, we can write:

src/index.js :

new Vue({  
  el: "#app",  
  data: { states: ["foo", "bar", "baz"], state: "", index: 0 },  
  methods: {  
    rotate() {  
      this.index = (this.index + 1) % this.states.length;  
      this.state = this.states[this.index];  
    }  
  }  
});

src/styles.css :

.fade-enter-active,  
.fade-leave-active {  
  transition: opacity 0.5s;  
}  
.fade-enter,  
.fade-leave-to {  
  opacity: 0;  
}

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
    <link  
      rel="stylesheet"  
      type="text/css"  
      href="./src/styles.css"  
      media="screen"  
    />  
  </head>  
  <body>  
    <div id="app">  
      <button v-on:click="rotate">  
        Rotate  
      </button>  
      <transition name="fade">  
        <p v-bind:key="state">  
          {{ state }}  
        </p>  
      </transition>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

We can rotate to different state value from the states array. Then we see transition each time the value of state changes.

Also, we can write out the v-if statements for each item as follows:

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
    <link  
      rel="stylesheet"  
      type="text/css"  
      href="./src/styles.css"  
      media="screen"  
    />  
  </head>  
  <body>  
    <div id="app">  
      <button v-on:click="rotate">  
        Rotate  
      </button>  
      <transition name="fade">  
        <p v-if="state === 'foo'" key="foo">  
          foo  
        </p>  
        <p v-if="state === 'bar'" key="bar">  
          bar  
        </p>  
        <p v-if="state === 'baz'" key="baz">  
          baz  
        </p>  
      </transition>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

The rest are unchanged.

Transition Modes

We can set the transition modes to control how old elements are transition to new elements.

There’re 2 transition modes:

  • in-out — new element transitions in first, then the current element transitions out
  • out-in — current element transitions our first and then the new element transitions in

For example, we can use it as follows:

src/index.js :

new Vue({  
  el: "#app",  
  data: { states: ["foo", "bar", "baz"], state: "", index: 0 },  
  methods: {  
    rotate() {  
      this.index = (this.index + 1) % this.states.length;  
      this.state = this.states[this.index];  
    }  
  } 
});

src/styles.css :

.fade-enter-active,  
.fade-leave-active {  
  transition: opacity 0.5s;  
}  
.fade-enter,  
.fade-leave-to {  
  opacity: 0;  
}

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
    <link  
      rel="stylesheet"  
      type="text/css"  
      href="./src/styles.css"  
      media="screen"  
    />  
  </head>  
  <body>  
    <div id="app">  
      <button v-on:click="rotate">  
        Rotate  
      </button>  
      <transition name="fade" mode="out-in">  
        <p v-bind:key="state">  
          {{ state }}  
        </p>  
      </transition>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

With the mode attribute added, we no longer have the jumpiness that the previous example has when transitioning between elements since old and new elements won’t exist on the same screen.

Conclusion

We can add the transition mode to prevent undesirable results from the old and new elements existing together.

Also, we should add a key attribute to each element that’s transitioned to that they’re rendered from scratch. It works for v-if and dynamic elements.

Categories
JavaScript Vue

Introduction to Vue.js Watchers

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at how to define and use Vue.js watchers.

When Should We Use Watchers?

We can use watchers when we want to watch for data changes in reactive properties and do some asynchronous or expensive options as the value changes.

For example, we can use it to watch for changes for an input and then get a joke from the Chuck Norris API when we type in something.

First, we put the following in src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    message: "",  
    joke: ""  
  },  
  created() {  
    this.debounceGetAllCapsMessage = _.debounce(this.getAllCapsMessage, 500);  
  },  
  methods: {  
    async getAllCapsMessage() {  
      const res = await fetch("https://api.icndb.com/jokes/random");  
      const result = await res.json();  
      this.joke = result.value.joke;  
    }  
  },  
  watch: {  
    message(newMessage, oldMessage) {  
      this.debounceGetAllCapsMessage();  
    }  
  }  
});

The code above watches for the change in the message property and then call the debounceGetAllCapsMessage method, which gets a jokes after a half a second delay.

The watch method both takes the new value as the first parameter and the old value as the second parameter.

Then we put the following in index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>Hello</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>  
  </head> <body>  
    <div id="app">  
      <input type="text" v-model="message" />  
      <p>{{joke}}</p>  
    </div>  
    <script src="./src/index.js"></script>  
  </body>  
</html>

As we can see, we can run an asynchronous operation, add a delay before we perform the operation, and then get the final result.

We can also use vm.$watch to watch for a value. It takes up to 3 arguments.

The first is a path to a property, which is a string. It can also be a function with one or multiple things combined to watch.

The second argument is a function that runs when the value changes.

The third argument for vm.$watch is an object with some properties. They include:

  • immediate — watches for the setting of the initial value

The method returns a function to stop watching for values. This is an optional argument.

We can use it as follows. In src/index.js , we have:

const vm = new Vue({  
  el: "#app",  
  data: {  
    message: "",  
    joke: ""  
  }  
});

vm.$watch(  
  "message",  
  _.debounce(async function() {  
    const res = await fetch("https://api.icndb.com/jokes/random");  
    const result = await res.json();  
    this.joke = result.value.joke;  
  }, 500)  
);

Then index.html , we have:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>Hello</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>  
  </head> <body>  
    <div id="app">  
      <input type="text" v-model="message" />  
      <p>{{joke}}</p>  
    </div>  
    <script src="./src/index.js"></script>  
  </body>  
</html>

which is the same as what we had before.

In both examples, we should get a new joke after half a second delay displayed.

Conclusion

We can use the watch method in the options and object and vm.$watch to watch for value changes.

The vm.$watch method watches a property given the path to it or a function that returns it or a combination of multiple properties.

vm.$watch takes a value changes handler and we can run code in it to handle when the value of a reactive property change.

The watch method runs code as the value changes.

Also, the watch method both takes the new value as the first parameter and the old value as the second parameter.

Categories
JavaScript Vue

How to Conditionally Render Elements in Vue

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at various ways to render items conditionally on the screen with Vue.js by using the v-show directive.

Also, we’ll look at the performance implications of combining v-if and v-for is various ways.

v-show

The v-show directive is used to show something when the expression we passed into it is truthy.

For example, we can use it as follows:

<h1 v-show="show">Hi</h1>

The difference between v-show and v-if are that v-show elements remain in the DOM even though is hidden.

On the other hand, v-if elements are hidden by removing them from the DOM.

Also, v-if removes event listeners and child components inside conditional blocks are destroyed if they’re hidden and recreated when v-if ‘s expression is truthy.

v-if elements are also different in that if the condition is falsy during conditional render, it won’t do anything. It won’t be rendered until the expression becomes truthy.

v-if has higher toggling than v-show since DOM manipulating and attaching event listeners have to be done when things are toggled.

Therefore, if things need to be toggled often, v-show is more efficient.

v-if with v-for

v-for has higher priority than v-if if they’re used together.

However, we shouldn’t use them together because of the higher precedence of v-for over v-if .

If we want to filter some elements out when we render items from an array, we should use a computed property.

If we only render a small fraction of array elements, it has to iterate over the entire list and then check if the expression we set it truthy.

For example, the following JavaScript and HTML code:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    persons: ["Joe", "Jane", "Mary"]  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  <body>  
    <div id="app">  
      <div v-for="person in persons" v-if='person !== "Joe"'>  
        {{person}}  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

is not very efficient since every time the loop is rendered, Vue has to iterate through every element and then check if person !== “Joe” is true .

Instead, we should use a computed property as follows:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    persons: ["Joe", "Jane", "Mary"]  
  },  
  computed: {  
    personsWithoutJoe() {  
      return this.persons.filter(p => p !== "Joe");  
    }  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  <body>  
    <div id="app">  
      <div v-for="person in personsWithoutJoe">  
        {{person}}  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

The code above is more efficient because personsWithoutJoe is only recomputed when persons change.

Also, only the items in personsWithoutJoe is iterated through during render, so v-for doesn’t have to loop through all the items.

There’s also less logic in the template, which keeps it clean. Maintenance is much easier.

We can also get performance benefits from moving v-if to the parent element that has the v-for , so whatever’s inside is only rendered when the condition is met.

For example, if we have:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    persons: ["Joe", "Jane", "Mary"],  
    show: false  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  <body>  
    <div id="app">  
      <div v-if="show">  
        <div v-for="person in persons">  
          {{person}}  
        </div>  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then nothing is rendered since show is false . Vue doesn’t have to do the work to look at whatever’s inside.

This is much better than:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  <body>  
    <div id="app">  
      <div v-for="person in persons" v-if="show">  
        {{person}}  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, Vue has to loop through each entry and check if the condition in the v-if returns a truthy value.

As we can see, even though the code is only slightly different, but the performance implications are big.

Conclusion

v-show is similar to v-if , except that items with v-show stays in the DOM no matter if it’s shown or not.

Also, we should be careful when we combine v-for and v-if .

First, v-for takes precedence over v-if if applied to the same element.

Also, we shouldn’t use them on the same element since Vue has to check each element for v-if ‘s condition in every iteration.

If we want to render a filtered list, we should use a computed property.

If we want to check if we should render the whole array, we should move v-if to the parent of the element with v-for , so that if v-if ‘s condition is falsy, then Vue won’t render the items in there.