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.
1<select name="customer_id" v-if="can_edit_customers">2 <option value="1">ACME Corporation</option>3 <option value="2">Laracasts</option>4 <option value="3">Tighten Co.</option>5</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.
1<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.
1<button class="btn btn-primary">2 <i class="fa fa-btn fa-spinner fa-spin" v-show="request.loading"></i>3 <i class="fa fa-btn fa-tick" v-show="! request.loading"></i>4</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
@stauffermatt @michaeldyrynda occurs to me that anyone with JS disabled would be able to poke around in that insecure content hidden by v-if
— Jacob Bennett (@JacobBennett) February 23, 2016
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.