Vue.js Quickset
This was part of my last note but then as time goes by I encountered more bottlenecks so I decided to put them in a different note to easily find the solutions.
Prevent request overhead
Never put a vuex store dispatch
or requests
in created
or mounted
method when a component is used inside a loop method. Why? of course it will always send a request to the server in every loop so for example if it will loop a 100x it will also send an equivalent request.
Vue component not rendering when used in laravel blade template
Example you have a blade view and lazy load a vue component like this.
resources/views/user/profile.blade.php
@section('content)
<vue-profile-component :user="{{ $user }} />
@section
resources/assets/js/app.js
Vue.component(
'vue-profile-component',
require('./components/UserProfile.vue)
);
But when you go to that endpoint it shows nothing. The workaround is so simple. Add default when instantiating the require method.
Vue.component(
'vue-profile-component',
require('./components/UserProfile.vue).default
);
[Vue warn]: Cannot find element: #app
Solution #1
Add an id=”app” in your div element.
app/resources/views/home.blade.php
@section('content')
<div class="card-body" id="app">
<vue-component :user="{{ auth()->user() }}" />
</div>
@section
Solution #2
Add defer keyword to the script tag to the compiled app.js in the main app layout view.
app/resources/views/layouts/app.blade.php
<script src="{{ asset('js/app.js') }}" defer></script>
CSS not working
You are sure that the style exists in your css or sass/less file. But then it is not applied in the element in your component. If this happens you needed to transfer or recreate the style inside of your component.
<style scoped>
/** Some styles here */
</style>
Modify child CSS property
Let say you have a parent component that has a child component then you want to modify the color of the h1
tag text in your child your component from the parent component.
Child Component
<template>
<div class="text-color">
<h1>Hello Vue!</h1>
</div>
</template>
<script></script>Parent Component
<template>
<div>
<child-component />
</div>
</template>
<script></script>
<style scoped>
/deep/ .text-color {
color: #000 !important
}
</style>
Passing an Array as prop to a Vue.js component inside in blade template.
When you try like below, the array will be converted as String
<vue-user-component users="{{ userArray }}" />
To Fix it you should use v-bind or like below to properly assign the value as prop.
<vue-user-component :users="{{ userArray }}" />
Passing an collection as prop to a Vue.js component inside in blade template.
When you try like below the collection data is udefined
in the component
<vue-user-component :users="{{ users }}" />
To Fix it you should encode your data into json object toproperly assign the value as prop.
<vue-user-component :users="{!! users !!}" />
[Vue warn]: You may have an infinite update loop in a component render function.
I encounter this error when I used a method
to display a title on a dropdown. This can be avoided if you are going to use computed
but I am also assigning a value to an object container to be use as prop on the child component, so to remove this warning, I put conditional statement to update only the value of role object when the user id is equal to the selected user value;
<template>
<select v-model="selectedUser">
<option v-for="user in users" :key="user.id" :value="user.id">
{{ optionTitle(user) }}
</option>
</select>
</template>----------------------------------------------data() {
return {
role: '',
selectedUser: '',
}
},methods: {
optionTitle: function(user) {
if (this.selectedUser != user.id) {
this.role = user.role;
} return `${user.role.name} - ${user.full_name}`
}
},
Vue Filters
Creating your custom filters
Example: Omitting post body
// app.js or main.js or your own filters fileVue.filter('ommit', value => {
if (!value || typeof(val) != 'string') {
return '';
}
return `value.slice(0,50) ${...}`;
});
Then you can use it like this post.body | ommit
Example: Simple Search
Assuming you have a list of users and want to only show the users that you want when you search.
//YourComponent
<template>
<input type="text" v-model="keyword" />
<ul>
<li v-for="user in filterUsers>user.name</li>
</ul>
</template>
<script>
props: ['users'],
data() {
return {
keyword: '',
}
}, computed: {
filterUsers() {
return this.users.filter(user => {
return user.title.match(this.keyword);
});
}
}
Having weird problems in the live server
In my machine it works fine, in the staging sometime it works some not, and in the live server it isn’t.
Error
Let say you have a user object and have a role child object and button to show specifically for the user role ex. admin and a guest user. And then when you deploy or update the live server the button for admin only is showing to the guest user.
Fix
Always validate the parent object first if it is not undefined
<button v-if="user && user.role === 'Admin'">Add</button><a href="/signup" v-else>Signup</a>
Error
I have multiple vue components inside on a blade template and only one of them are showing.
Fix
Instead of instantiating your vue components like this
<my-component-one />
<my-component-two />
<my-component-three />
Do it like this
<my-component-one></my-component-one>
<my-component-two></my-component-two />
<my-component-three></my-component-three />
Problem
When I want to get the real time value from an input with model binding, the update is delayed. e.g. When I press 1, it shows undefined
and when I press 2 which supposedly displays 12, that’s the time it shows the 1 value.
Fix
Instead of using @keydown
use @keyup
to get the value from the input.
<input v-model="myInput" @keyup="methodToProcessInputValue" />
More To Come…