Introduction

I was working in a multi-tenanted app where I was generating a HTML select element with a list of all of the application's customers, then using v-show to conditionally hide this content.

In diagnosing a separate rendering issue, I discovered that VueJS will still render the HTML, then set it's the display property to none for the element, if the v-show test returned a false-y value.

I dug into the controller code to make sure that only customers the authenticated user had access to view were returned, but did some further investigation to determine how to appropriately handle this in Vue, after Matt suggested that v-if might address my concerns.

v-if

Conditionally render the element based on the truthy-ness of the expression value. The element and its contained data bindings / components are destroyed and re-constructed during toggles.

Essentially, if the expression in the v-if attribute results in a false-y value, the element will not be rendered on the page at all.

<select name="customer_id" v-if="can_edit_customers">
    <option value="1">ACME Corporation</option>
    <option value="2">Laracasts</option>
    <option value="3">Tighten Co.</option>
</select>

In the above example, the select element will be rendered to the DOM only if the can_edit_customers property returns true. This can be passed into your component as a property, for example, and resolved directly from your controller.

<customers can_edit_customers="{{ auth()->user()->can('manage_customers') }}"></customers>

v-show

Toggle’s the element’s display CSS property based on the truthy-ness of the expression value.

The element will always be rendered in the DOM, and its display property will be set to block if the expression results in a truth-y value and none if the expression results in a false-y value.

An example where you might do this is when you're showing or hiding a loader/spinner.

<button class="btn btn-primary">
    <i class="fa fa-btn fa-spinner fa-spin" v-show="request.loading"></i>
    <i class="fa fa-btn fa-tick" v-show="! request.loading"></i>
</button>

In the above example, the spinner element will only be displayed if the request object's loading property returns true and the tick element only when the same value returns false.

Conclusion

It is up to you to determine whether it's ok for some element to be rendered and merely have it's display property toggled, or if you need it to be removed from the DOM entirely.

In this example, if you don't want to reveal details of your application to unauthorised users (customers, users, etc.) you probably want to use v-if. If you just want to toggle the state of some element, v-show will do just fine.

Update Feb 24, 2015

Jacob raises an excellent point here. For most people, JavaScript will be enabled, but in situations where it is not available or has been intentionally disabled, you still need to factor in the security of your application data.

The simplest way of doing this is to ensure that you're only sending to the client data that you're happy to be rendered for the visitor. That means, if you mean to use v-if to conditionally render some content to the browser, you should also only send it the data that you want to be rendered.

Further Reading