Learn Depth
Learn Depth
Learn Depth
Learn Depth
learndepth.com/InterviewQa/"VueInt"
Virtual DOM: It uses virtual DOM similar to other existing frameworks such as
ReactJS, Ember etc. Virtual DOM is a light-weight in-memory tree representation of
the original HTML DOM and updated without affecting the original DOM.
Components: Used to create reusable custom elements in VueJS applications.
Templates: VueJS provides HTML based templates that bind the DOM with the Vue
instance data
Routing: Navigation between pages is achieved through vue-router
Light weight: VueJS is light weight library compared to other frameworks.
Lifecycle hooks are a window into how the library you’re using works behind-the-
scenes. By using these hooks, you will know when your component is created,
added to the DOM, updated, or destroyed. Let's look at lifecycle diagram before
going to each lifecycle hook in detail,
Creation(Initialization):
Creation Hooks allow you to perform actions before your component has even been
added to the DOM. You need to use these hooks if you need to set things up in your
component both during client rendering and server rendering. Unlike other hooks,
creation hooks are also run during server-side rendering.
beforeCreate: This hook runs at the very initialization of your component. hook
observes data and initialization events in your component. Here, data is still not
reactive and events that occur during the component’s lifecycle have not been set
up yet.
https://learndepth.com/InterviewQa/"VueInt" 1/100
7/24/24, 8:33 PM Learn Depth
new Vue({
data: {
count: 10
},
beforeCreate: function () {
console.log('Nothing gets called at this moment')
// 'this' points to the view model instance
console.log('count is ' + this.count);
}
})
// count is undefined
created: This hook is invoked when Vue has set up events and data observation.
Here, events are active and access to reactive data is enabled though templates
have not yet been mounted or rendered.
new Vue({
data: {
count: 10
},
created: function () {
// 'this' points to the view model instance
console.log('count is: ' + this.count)
}
})
// count is: 10
Note: Remember that, You will not have access to the DOM or the target mounting
element (this.$el) inside of creation hooks
Mounting(DOM Insertion):
Mounting hooks are often the most-used hooks and they allow you to access your
component immediately before and after the first render.
new Vue({
beforeMount: function () {
// 'this' points to the view model instance
console.log('this.$el is yet to be created');
}
})
https://learndepth.com/InterviewQa/"VueInt" 2/100
7/24/24, 8:33 PM Learn Depth
mounted: This is a most used hook and you will have full access to the reactive
component, templates, and rendered DOM (via. this.$el). The most frequently used
patterns are fetching data for your component.
<div id="app">
<p>I’m text inside the component.</p>
</div>
new Vue({
el: ‘#app’,
mounted: function() {
console.log(this.$el.textContent); // I'm text inside the component.
}
})
Updating (Diff & Re-render): Updating hooks are called whenever a reactive
property used by your component changes, or something else causes it to re-render
beforeUpdate: The beforeUpdate hook runs after data changes on your component
and the update cycle begins, right before the DOM is patched and re-rendered.
<div id="app">
<p>{{counter}}</p>
</div>
beforeUpdate: function() {
console.log(this.counter) // Logs the counter value every second, before the
DOM updates.
}
})
updated: This hook runs after data changes on your component and the DOM re-
renders.
https://learndepth.com/InterviewQa/"VueInt" 3/100
7/24/24, 8:33 PM Learn Depth
<div id="app">
<p ref="dom">{{counter}}</p>
</div>
...//
new Vue({
el: '#app',
data() {
return {
counter: 0
}
},
created: function() {
setInterval(() => {
this.counter++
}, 1000)
},
updated: function() {
console.log(+this.$refs['dom'].textContent === this.counter) // Logs true
every second
}
})
Destruction (Teardown):
Destruction hooks allow you to perform actions when your component is destroyed,
such as cleanup or analytics sending.
new Vue ({
data() {
return {
message: 'Welcome VueJS developers'
}
},
beforeDestroy: function() {
this.message = null
delete this.message
}
})
destroyed: This hooks is called after your component has been destroyed, its
directives have been unbound and its event listeners have been removed.
https://learndepth.com/InterviewQa/"VueInt" 4/100
7/24/24, 8:33 PM Learn Depth
new Vue ({
destroyed: function() {
console.log(this) // Nothing to show here
}
})
VueJS provides set of directives to show or hide elements based on conditions. The
available directives are: v-if, v-else, v-else-if and v-show
v-if:
The v-if directive adds or removes DOM elements based on the given expression.
For example, the below button will not show if isLoggedIn is set to false.
<button v-if="isLoggedIn">Logout</button>
You can also control multiple elements with a single v-if statement by wrapping all
the elements in a
<template v-if="isLoggedIn">
<label> Logout </button>
<button> Logout </button>
</template>
v-else:
This directive is used to display content only when the expression adjacent v-if
resolves to false. This is similar to else block in any programming language to
display alternative content and it is preceded by v-if or v-else-if block. You don't
need to pass any value to this. For example, v-else is used to display LogIn button if
isLoggedIn is set to false(not logged in).
v-else-if:
This directive is used when we need more than two options to be checked. For
example, we want to display some text instead of LogIn button when
ifLoginDisabled property is set to true. This can be achieved through v-else
statement.
https://learndepth.com/InterviewQa/"VueInt" 5/100
7/24/24, 8:33 PM Learn Depth
v-show:
This directive is similar to v-if but it renders all elements to the DOM and then uses
the CSS display property to show/hide elements. This directive is recommended if
the elements are switched on and off frequently.
Below are some of the main differences between v-show and v-if directives,
v-if only renders the element to the DOM if the expression passes whereas v-show
renders all elements to the DOM and then uses the CSS display property to
show/hide elements based on expression.
v-if supports v-else and v-else-if directives whereas v-show doesn't support else
directives.
v-if has higher toggle costs while v-show has higher initial render costs. i.e, v-show
has a performance advantage if the elements are switched on and off frequently,
while the v-if has the advantage when it comes to initial render time.
v-if supports
The built-in v-for directive allows us to loop through items in an array or object. You
can iterate on each element in the array or object.
Array usage:
https://learndepth.com/InterviewQa/"VueInt" 6/100
7/24/24, 8:33 PM Learn Depth
<ul id="list">
<li v-for="(item, index) in items">
{{ index }} - {{ item.message }}
</li>
</ul>
You can also use of as the delimiter instead of in, similar to javascript iterators.
Object usage:
<div id="object">
<div v-for="(value, key, index) of user">
{{ index }}. {{ key }}: {{ value }}
</div>
</div>
Every Vue application works by creating a new Vue instance with the Vue function.
Generally the variable vm (short for ViewModel) is used to refer Vue instance. You
can create vue instance as below,
https://learndepth.com/InterviewQa/"VueInt" 7/100
7/24/24, 8:33 PM Learn Depth
As mentioned in the above code snippets, you need to pass options object. You can
find the full list of options in the API reference.
Q8. How do you achieve conditional group of elements?
For example, you can conditionally group user details based on valid user condition.
<template v-if="condition">
<h1>Name</h1>
<p>Address</p>
<p>Contact Details</p>
</template>
Vue always tries to render elements as efficient as possible. So it tries to reuse the
elements instead of building them from scratch. But this behavior may cause
problems in few scenarios.
For example, if you try to render the same input element in both v-if and v-else
blocks then it holds the previous value as below,
In this case, it shouldn't reuse. We can make both input elements as separate by
applying key attribute as below,
https://learndepth.com/InterviewQa/"VueInt" 8/100
7/24/24, 8:33 PM Learn Depth
The above code make sure both inputs are independent and doesn't impact each
other.
Q10. Why should not use if and for directives together on the same element?
It is recommended not to use v-if on the same element as v-for. Because v-if
directive has a higher priority than v-for.
There are two cases where developers try to use this combination,
<ul>
<li
v-for="user in users"
v-if="user.isActive"
:key="user.id"
>
{{ user.name }}
<li>
</ul>
This can be avoided by preparing the filtered list using computed property on the
initial list
computed: {
activeUsers: function () {
return this.users.filter(function (user) {
return user.isActive
})
}
}
...... //
...... //
<ul>
<li
v-for="user in activeUsers"
:key="user.id">
{{ user.name }}
<li>
</ul>
https://learndepth.com/InterviewQa/"VueInt" 9/100
7/24/24, 8:33 PM Learn Depth
<ul>
<li
v-for="user in users"
v-if="shouldShowUsers"
:key="user.id"
>
{{ user.name }}
<li>
</ul>
This can be solved by moving the condition to a parent by avoiding this check for
each user
<ul v-if="shouldShowUsers">
<li
v-for="user in users"
:key="user.id"
>
{{ user.name }}
<li>
</ul>
In order to track each node’s identity, and thus reuse and reorder existing elements,
you need to provide a unique key attribute for each item with in v-for iteration. An
ideal value for key would be the unique id of each item.
Note: You shouldn’t use non-primitive values like objects and arrays as v-for keys.
Use string or numeric values instead.
Below are the list of array mutation methods which trigger view updates.
https://learndepth.com/InterviewQa/"VueInt" 10/100
7/24/24, 8:33 PM Learn Depth
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
If you perform any of the above mutation method on the list then it triggers view
update. For example, push method on array named 'items' trigger a view update,
The methods which do not mutate the original array but always return a new array
are called non-mutation methods.
filter()
concat()
slice()
For example, lets take a todo list where it replaces the old array with new one based
on status filter,
This approach won't re-render the entire list due to VueJS implementation.
Vue cannot detect changes for the array in the below two cases,
vm.todos[indexOfTodo] = newTodo
https://learndepth.com/InterviewQa/"VueInt" 11/100
7/24/24, 8:33 PM Learn Depth
vm.todos.length = todosLength
You can overcome both the caveats using set and splice methods, Let's see the
solutions with an examples,
// Vue.set
Vue.set(vm.todos, indexOfTodo, newTodoValue)
(or)
// Array.prototype.splice
vm.todos.splice(indexOfTodo, 1, newTodoValue)
vm.todos.splice(todosLength)
Vue cannot detect changes for the object in property addition or deletion
You can overcome this scenario using the Vue.set(object, key, value) method or
Object.assign(),
https://learndepth.com/InterviewQa/"VueInt" 12/100
7/24/24, 8:33 PM Learn Depth
You can also use integer type(say 'n') for v-for directive which repeats the element
many times.
<div>
<span v-for="n in 20">{{ n }} </span>
</div>
<ul>
<template v-for="todo in todos">
<li>{{ todo.title }}</li>
<li class="divider"></li>
</template>
</ul>
You can use event handlers in vue similar to plain javascript. The method calls also
support the special $event variable.
methods: {
show: function (message, event) {
// now we have access to the native event
if (event) event.preventDefault()
console.log(message);
}
}
https://learndepth.com/InterviewQa/"VueInt" 13/100
7/24/24, 8:33 PM Learn Depth
.stop
.prevent
.capture
.self
.once
.passive
Vue supports key modifiers on v-on for handling keyboard events. Let's take an
example of keyup event with enter keycode.
Remembering all the key codes is really difficult. It supports the full list of key codes
aliases
.enter
.tab
.delete (captures both “Delete” and “Backspace” keys)
.esc
.space
.up
.down
.left
.right
Now the above keyup code snippet can be written with aliases as follows,
https://learndepth.com/InterviewQa/"VueInt" 14/100
7/24/24, 8:33 PM Learn Depth
Note: The use of keyCode events is deprecated and may not be supported in new
browsers.
Q21. How do you define custom key modifier aliases?
You can define custom key modifier aliases via the global config.keyCodes. There
are few guidelines for the properties
You can't use camelCase. Instead you can use kebab-case with double quotation
marks
You can define multiple values in an array format
Vue.config.keyCodes = {
f1: 112,
"media-play-pause": 179,
down: [40, 87]
}
Vue supports below modifiers to trigger mouse or keyboard event listeners when the
corresponding key is pressed,
.ctrl
.alt
.shift
.meta
.left
.right
.middle
https://learndepth.com/InterviewQa/"VueInt" 15/100
7/24/24, 8:33 PM Learn Depth
<button
v-if="button === 'right'"
v-on:mousedown.right="increment"
v-on:mousedown.left="decrement"
/>
You can use the v-model directive to create two-way data bindings on form input,
textarea, and select elements.
Remember, v-model will ignore the initial value, checked or selected attributes
found on any form elements. So it always use the Vue instance data as the source
of truth.
1. lazy: By default, v-model syncs the input with the data after each input event. You
can add the lazy modifier to instead sync after change events.
2.number: If you want user input to be automatically typecast as a number, you can
add the number modifier to your v-model. Even with type='number', the value of
HTML input elements always returns a string. So, this typecast modifier is required.
3. trim: If you want whitespace from user input to be trimmed automatically, you can
add the trim modifier to your v-model.
<input v-model.trim="msg">
https://learndepth.com/InterviewQa/"VueInt" 16/100
7/24/24, 8:33 PM Learn Depth
Components are reusable Vue instances with a name. They accept the same
options as new Vue, such as data, computed, watch, methods, and lifecycle
hooks(except few root-specific options like el).
Let's use this component inside a root Vue instance created with new Vue
<div id="app">
<button-counter></button-counter>
</div>
Props are custom attributes you can register on a component. When a value is
passed to a prop attribute, it becomes a property on that component instance. You
can pass those list of values as props option and use them as similar to data
variables in template.
Vue.component('todo-item', {
props: ['title'],
template: '<h2>{{ title }}</h2>'
})
Once the props are registered, you can pass them as custom attributes.
https://learndepth.com/InterviewQa/"VueInt" 17/100
7/24/24, 8:33 PM Learn Depth
In VueJS 2.x, every component must have a single root element when template has
more than one element. In this case, you need to wrap the elements with a parent
element.
<template>
<div class="todo-item">
<h2>{{ title }}</h2>
<div v-html="content"></div>
</div>
</template>
Otherwise there will an error throwing, saying that 'Component template should
contain exactly one root element...'.
Whereas in 3.x, components now can have multiple root nodes. This way of adding
multiple root nodes is called as fragments.
<template>
<h2>{{ title }}</h2>
<div v-html="content"></div>
</template>
If you want child wants to communicate back up to the parent, then emit an event
from child using $emit object to parent,
Vue.component('todo-item', {
props: ['todo'],
template: '
<div class="todo-item">
<h3>{{ todo.title }}</h3>
<button v-on:click="$emit('increment-count', 1)">
Add
</button>
<div v-html="todo.description"></div>
</div>
'
})
Now you can use this todo-item in parent component to access the count value.
https://learndepth.com/InterviewQa/"VueInt" 18/100
7/24/24, 8:33 PM Learn Depth
The custom events can also be used to create custom inputs that work with v-
model. The input inside the component must follow below rules,
Vue.component('custom-input', {
props: ['value'],
template: '
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
/>
'
})
<custom-input v-model="searchInput"></custom-input>
Vue implements a content distribution API using the element to serve as distribution
outlets for content created after the current Web Components spec draft.
https://learndepth.com/InterviewQa/"VueInt" 19/100
7/24/24, 8:33 PM Learn Depth
Vue.component('alert', {
template: '
<div class="alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
'
})
<alert>
There is an issue with in application.
</alert>
The components which are globally registered can be used in the template of any
root Vue instance (new Vue) created after registration.
Vue.component('my-component-name', {
// ... options ...
})
Let's take multiple components which are globally registered in the vue instance,
Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>
https://learndepth.com/InterviewQa/"VueInt" 20/100
7/24/24, 8:33 PM Learn Depth
Due to global registration, even if you don't use the component it could still be
included in your final build. So it will create unnecessary javascript in the
application. This can be avoided using local registration with the below steps,
Locally registered components will not be available in sub components. In this case,
you need to add them in components section
var ComponentB = {
components: {
'component-a': ComponentA
},
// ...
}
You can use the components in the components section of the vue instance,
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
Q34. What is the difference between local and global registration in module system?
Let's say you want to register component A and B in component C, the configuration
seems as below,
https://learndepth.com/InterviewQa/"VueInt" 21/100
7/24/24, 8:33 PM Learn Depth
export default {
components: {
ComponentA,
ComponentB
},
// ...
}
https://learndepth.com/InterviewQa/"VueInt" 22/100
7/24/24, 8:33 PM Learn Depth
requireComponent.keys().forEach(fileName => {
// Get component config
const componentConfig = requireComponent(fileName)
You can declare props with type or without type. But it is recommended to have
prop types because it provides the documentation for the component and warns the
developer for any incorrect data type being assigned.
props: {
name: String,
age: Number,
isAuthenticated: Boolean,
phoneNumbers: Array,
address: Object
}
As mentioned in the above code snippet, you can list props as an object, where the
properties’ names and values contain the prop names and types, respectively.
https://learndepth.com/InterviewQa/"VueInt" 23/100
7/24/24, 8:33 PM Learn Depth
All props follows a one-way-down binding between the child property and the parent
one. i.e, When the parent property is updated then that latest prop value will be
passed down to the child, but not the otherway(child to parent) around. The child
component should not mutate the prop otherwise it throws a warning in the console.
The possible mutation cases can be solved as below,
When you try to use parent prop as initial value for child property:
In this case you can define a local property in child component and assign parent
value as initial value
props: ['defaultUser'],
data: function () {
return {
username: this.defaultUser
}
}
props: ['environment'],
computed: {
localEnvironment: function () {
return this.environment.trim().toUpperCase()
}
}
A non-prop attribute is an attribute that is passed to a component, but does not have
a corresponding prop defined.
For example, If you are using a 3rd-party custom-input component that requires a
data-tooltip attribute on the input then you can add this attribute to component
instance,
If you try to pass the props from parent component the child props with the same
names will be overridden. But props like class and style are exception to this, these
values will be merged in the child component.
https://learndepth.com/InterviewQa/"VueInt" 24/100
7/24/24, 8:33 PM Learn Depth
Vue provides validations such as types, required fields, default values along with
customized validations. You can provide an object with validation requirements to
the value of props as below,
Let's take an example of user profile Vue component with possible validations,
Vue.component('user-profile', {
props: {
// Basic type check ('null' matches any type)
age: Number,
// Multiple possible types
identityNumber: [String, Number],
// Required string
email: {
type: String,
required: true
},
// Number with a default value
minBalance: {
type: Number,
default: 10000
},
// Object with a default value
message: {
type: Object,
// Object or array defaults must be returned from
// a factory function
default: function () {
return { message: 'Welcome to Vue' }
}
},
// Custom validator function
location: {
validator: function (value) {
// The value must match one of these strings
return ['India', 'Singapore', 'Australia'].indexOf(value) !== -1
}
}
}
})
https://learndepth.com/InterviewQa/"VueInt" 25/100
7/24/24, 8:33 PM Learn Depth
The v-model directive on a component uses value as the prop and input as the
event, but some input types such as checkboxes and radio buttons may need to use
the value attribute for a server side value. In this case, it is preferred to customize
model directive.
Vue.component('custom-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: '
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
'
})
<custom-checkbox v-model="selectFramework"></custom-checkbox>
The selectFramework property will be passed to the checked prop and same
property will be updated when custom checkbox component emits a change event
with a new value.
Q40. What are the possible ways to provide transitions?
There are many ways Vue provides transition effects when items are inserted,
updated, or removed from the DOM.
Vue Router is a official routing library for single-page applications designed for use
with the Vue.js framework.
https://learndepth.com/InterviewQa/"VueInt" 26/100
7/24/24, 8:33 PM Learn Depth
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<h1>Welcome to Vue routing app!</h1>
<p>
<!-- use router-link component for navigation using 'to' prop. It rendered as
an '<a>' tag -->
<router-link to="/home">Home</router-link>
<router-link to="/services">Services</router-link>
</p>
<!-- route outlet in which component matched by the route will render here -->
<router-view></router-view>
</div>
Step 2: Import Vue and VueRouter packages and then apply router
Vue.use(VueRouter)
https://learndepth.com/InterviewQa/"VueInt" 27/100
7/24/24, 8:33 PM Learn Depth
const routes = [
{ path: '/home', component: Home },
{ path: '/services', component: Services }
]
Step 5: Create the router instance and pass the routes option
Now you are able to navigate different pages(Home, Services) with in Vue
application.
Q43. What is dynamic route matching?
Let's take a user component with the mapped URLs like /user/john/post/123 and
/user/jack/post/235 using dynamic segments,
const User = {
template: '<div>User {{ $route.params.name }}, PostId: {{ route.params.postid }}
</div>'
}
When you navigate from one URL to other(mapped with a single component) using
routes with params then the same component instance will be reused. Even though
it is more efficient than destroying the old instance and then creating a new one, the
https://learndepth.com/InterviewQa/"VueInt" 28/100
7/24/24, 8:33 PM Learn Depth
const User = {
template: '<div>User {{ $route.params.name }} </div>',
watch: {
'$route' (to, from) {
// react to route changes...
}
}
}
Use beforeRouteUpdate navigation guard: This is only available since 2.2 version
const User = {
template: '<div>User {{ $route.params.name }} </div>',
beforeRouteUpdate (to, from, next) {
// react to route changes and then call next()
}
}
Note that the beforeRouteEnter guard does NOT have access to this. Instead you
can pass a callback to next to access the vm instance.
Q45. What is route matching priority?
Sometimes the URL might be matched by multiple routes and the confusion of
which route need to be mapped is resolved by route matching priority. The priority is
based on order of routes configuration. i.e, The route which declared first has higher
priority.
https://learndepth.com/InterviewQa/"VueInt" 29/100
7/24/24, 8:33 PM Learn Depth
Generally, the app is composed of nested components which are nested multiple
levels deep. The segments of a URL corresponds to a certain structure of these
nested components. To render components into the nested outlet, you need to use
the children option in VueRouter constructor config.
Let's take a user app composed of profile and posts nested components with
respective routes. You can also define a default route configuration when there is no
matching nested route.
Single File Components are an easy concept to understand. Earlier you might heard
about all three parts(HTML, JavaScript and CSS) of your application kept in
different components. But Single File Components encapsulate the structure, styling
and behaviour into one file. In the beginning, it seems strange to have all three parts
in one file, but it actually makes a lot more sense.
https://learndepth.com/InterviewQa/"VueInt" 30/100
7/24/24, 8:33 PM Learn Depth
<template>
<div>
<h1>Welcome {{ name }}!</h1>
</div>
</template>
<script>
module.exports = {
data: function() {
return {
name: 'John'
}
}
}
</script>
<style scoped>
h1 {
color: #34c779;
padding: 3px;
}
</style>
For example,
<template>
<div>This section will be pre-compiled and hot reloaded</div>
</template>
<script src="./my-component.js"></script>
<style src="./my-component.css"></style>
The Single File Components solve the common problems occurred in a javascript
driven application with a .vue extension. The list of issues are,
https://learndepth.com/InterviewQa/"VueInt" 31/100
7/24/24, 8:33 PM Learn Depth
No CSS support means that while HTML and JavaScript are modularized into
components, CSS is conspicuously left out
No build step restricts us to HTML and ES5 JavaScript, rather than preprocessors
like Pug (formerly Jade) and Babel.
Q50. What are filters?
Filters can be used to apply common text formatting. These Filters should be
appended to the end of the JavaScript expression, denoted by the “pipe” symbol.
You can use them in two specific cases:
mustache interpolations
v-bind expressions
For example, Let's define a local filter named capitalize in a component’s options
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
Now you can use the filter in either mustache interpolation or v-bind expression,
Local filters: You can define local filters in a component’s options. In this case, filter
is applicable to that specific component.
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
https://learndepth.com/InterviewQa/"VueInt" 32/100
7/24/24, 8:33 PM Learn Depth
Global filters: You can also define a filter globally before creating the Vue instance.
In this case, filter is applicable to all the components with in the vue instance,
new Vue({
// ...
})
You can chain filters one after the other to perform multiple manipulations on the
expression. The generic structure of filter chain would be as below,
In the above chain stack, you can observe that message expression applied with
three filters, each separated by a pipe(|) symbol. The first filter(filterA) takes the
expression as a single argument and the result of the expression becomes an
argument for second filter(filterB) and the chain continue for remaining filters.
For example, if you want to transform date expression with a full date format and
uppercase then you can apply dateFormat and uppercase filters as below,
Yes, you can pass arguments for a filter similar to a javascript function. The generic
structure of filter parameters would be as follows,
In this case, filterA takes message expression as first argument and the explicit
parameters mentioned in the filter as second and third arguments.
For example, you can find the exponential strength of a particular value
https://learndepth.com/InterviewQa/"VueInt" 33/100
7/24/24, 8:33 PM Learn Depth
The Plugin is created by exposing an install method which takes Vue constructor as
a first argument along with options. The structure of VueJS plugin with possible
functionality would be as follows,
https://learndepth.com/InterviewQa/"VueInt" 34/100
7/24/24, 8:33 PM Learn Depth
You can use plugin by passing your plugin to Vue's use global method. You need to
apply this method before start your app by calling new Vue().
new Vue({
//... options
})
const myMixin = {
created(){
console.log("Welcome to Mixins!")
}
}
var app = new Vue({
el: '#root',
mixins: [myMixin]
})
Note: Multiple mixins can be specified in the mixin array of the component
Vue.mixin({
created(){
console.log("Write global mixins")
}
})
new Vue({
el: '#app'
})
https://learndepth.com/InterviewQa/"VueInt" 35/100
7/24/24, 8:33 PM Learn Depth
In the above global mixin, the mixin options spread across all components with the
console running during the instance creation. These are useful during test, and
debugging or third party libraries. At the same time, You need to use these global
mixins sparsely and carefully, because it affects every single Vue instance created,
including third party components.
Q59. How do you use mixins in CLI?
Using Vue CLI, mixins can be specified anywhere in the project folder but preferably
within /src/mixins for ease of access. Once these mixins are created in a .js file and
exposed with the export keyword, they can be imported in any component with the
import keyword and their file paths.
When a mixin and the component itself contain overlapping options, the options will
be merged based on some strategies.
The data objects undergo a recursive merge, with the component’s data taking
priority over mixins in cases of overlapping or conflicts.
var mixin = {
data: function () {
return {
message: 'Hello, this is a Mixin'
}
}
}
new Vue({
mixins: [mixin],
data: function () {
return {
message: 'Hello, this is a Component'
}
},
created: function () {
console.log(this.$data); // => { message: "Hello, this is a Component'" }
}
})
The Hook functions which are overlapping merged into an array so that all of them
will be called. Mixin hooks will be called before the component’s own hooks.
https://learndepth.com/InterviewQa/"VueInt" 36/100
7/24/24, 8:33 PM Learn Depth
const myMixin = {
created(){
console.log("Called from Mixin")
}
}
new Vue({
el: '#root',
mixins: [myMixin],
created(){
console.log("Called from Component")
}
})
The options that expect object values(such as methods, components and directives)
will be merged into the same object. In this case, the component’s options will take
priority when there are conflicting keys in these objects.
var mixin = {
methods: {
firstName: function () {
console.log('John')
},
contact: function () {
console.log('+65 99898987')
}
}
}
vm.firstName() // "John"
vm.lastName() // "Murray"
vm.contact() // "+91 893839389"
https://learndepth.com/InterviewQa/"VueInt" 37/100
7/24/24, 8:33 PM Learn Depth
Vue uses the default strategy which overwrites the existing value while custom
options are merged. But if you want a custom option merged using custom login
then you need to attach a function to Vue.config.optionMergeStrategies
For the example, the structure of myOptions custom option would be as below,
Custom Directives are tiny commands that you can attach to DOM elements. They
are prefixed with v- to let the library know you're using a special bit of markup and to
keep syntax consistent. They are typically useful if you need low-level access to an
HTML element to control a bit of behavior.
Let's create a custom focus directive to provide focus on specific form element
during page load time,
<input v-focus>
https://learndepth.com/InterviewQa/"VueInt" 38/100
7/24/24, 8:33 PM Learn Depth
You can also register directives locally(apart from globally) using directives option in
component as below,
directives: {
focus: {
// directive definition
inserted: function (el) {
el.focus()
}
}
}
<input v-focus>
A directive can take any valid javascript expression. So if you want to pass multiple
values then you can pass in a JavaScript object literal.
<div v-avatar="{ width: 500, height: 400, url: 'path/logo', text: 'Iron Man' }">
</div>
https://learndepth.com/InterviewQa/"VueInt" 39/100
7/24/24, 8:33 PM Learn Depth
In few cases, you may want the same behavior on bind and update hooks
irrespective of other hooks. In this situation you can use function shorthand,
In VueJS, the templates are very powerful and recommended to build HTML as part
of your application. However, some of the special cases like dynamic component
creation based on input or slot value can be achieved through render functions.
Also, these functions gives the full programmatic power of javascript eco system.
Let's take an example of simple Div markup and corresponding render function. The
HTML markup can be written in template tag as below,
<template>
<div :class="{'is-rounded': isRounded}">
<p>Welcome to Vue render functions</p>
</div>
</template>
and the compiled down or explicit render function would appear as below,
https://learndepth.com/InterviewQa/"VueInt" 40/100
7/24/24, 8:33 PM Learn Depth
Note: The react components are built with render functions in JSX.
Q69. Explain the structure of createElement with arguments?
The createElement accepts few arguments to use all the template features.
https://learndepth.com/InterviewQa/"VueInt" 41/100
7/24/24, 8:33 PM Learn Depth
// @returns {VNode}
createElement(
// An HTML tag name, component options, or async function resolving to one of
these.
// Type is {String | Object | Function}
// Required.
'div',
https://learndepth.com/InterviewQa/"VueInt" 42/100
7/24/24, 8:33 PM Learn Depth
})
]
)
All virtual nodes(VNodes) in the component tree must be unique.i.e, You can't write
duplicated nodes in a straightforward way. If you want to duplicate the same
element/component many times then you should use factory function.
The below render function is invalid where you are trying to duplicate h1 element 3
times,
The functional components are just simple functions to create simple components
just by passing a context. Every functional component follows two rules,
https://learndepth.com/InterviewQa/"VueInt" 43/100
7/24/24, 8:33 PM Learn Depth
Vue.component('my-component', {
functional: true,
// Props are optional
props: {
// ...
},
// To compensate for the lack of an instance,
// we are now provided a 2nd context argument.
render: function (createElement, context) {
// ...
}
})
Note: The functional components are quite popular in React community too.
Q72. What are the similarities between VueJS and ReactJS?
Even though ReactJS and VueJS are two different frameworks there are few
similarities(apart from the common goal of utilized in interface design) between
them.
The dynamic component will allow you to dynamically switch beetween multiple
components without updating the route of the application and even retaining the
state of the component when switching back to the initial component. It works by
using tag with v-bind:is attribute which accept dynamic component.
https://learndepth.com/InterviewQa/"VueInt" 44/100
7/24/24, 8:33 PM Learn Depth
Let's create a dynamic component vue instance to switch between different pages
of a website,
new Vue({
el: '#app',
data: {
currentPage: 'home'
},
components: {
home: {
template: "<p>Home</p>"
},
about: {
template: "<p>About</p>"
},
contact: {
template: "<p>Contact</p>"
}
}
})
Now you can use the dynamic component which holds the current page,
<div id="app">
<component v-bind:is="currentPage">
<!-- component changes when currentPage changes! -->
<!-- output: Home -->
</component>
</div>
Note: The value of :is attribute can be either name of the registered component or
the actual imported object itself.
Q76. What is the purpose of keep alive tag?
https://learndepth.com/InterviewQa/"VueInt" 45/100
7/24/24, 8:33 PM Learn Depth
When there are multiple conditional children, it requires that only one child is
rendered at a time.
Note: Remember that keep-alive tag doesn’t render a DOM element itself, and
doesn’t show up in the component parent chain.
Q77. What are async components?
In large applications, we may need to divide the app into smaller chunks and only
load a component from the server when it’s needed. To make this happen, Vue
allows you to define your component as a factory function that asynchronously
resolves your component definition. These components are known as async
component.
Vue will only trigger the factory function when the component needs to be rendered
and will cache the result for future re-renders.
https://learndepth.com/InterviewQa/"VueInt" 46/100
7/24/24, 8:33 PM Learn Depth
If you keep an inline-template on a child component then it will use its inner content
as a template instead of treating as reusable independent content.
<my-component inline-template>
<div>
<h1>Inline templates</h1>
<p>Treated as component component owne content</p>
</div>
</my-component>
Note: Even though this inline-templates gives more flexibility for template authoring,
it is recommended to define template using template property or tag inside .vue
component.
Apart from regular templates and inline templates, you can also define templates
using a script element with the type text/x-template and then referencing the
template by an id.
https://learndepth.com/InterviewQa/"VueInt" 47/100
7/24/24, 8:33 PM Learn Depth
Vue.component('x-template-example', {
template: '#script-template'
})
The Components that can recursively invoke themselves in their own template are
known as recursive components.
Vue.component('recursive-component', {
template: '<!--Invoking myself!-->
<recursive-component></recursive-component>'
});
Note: Remember that recursive component can lead infinite loops with max stack
size exceeded error, so make sure recursive invocation is conditional(for example,
v-if directive).
Let's say componentA and componentB included in their respective templates which
makes circular dependency,
//ComponentA
<div>
<component-b >
</div>
//ComponentB
<div>
<component-a >
</div>
This can be solved by either registering(or wait until) the child component in
beforeCreate hook or using webpack's asynchronous import while registering the
component,
Solution1:
https://learndepth.com/InterviewQa/"VueInt" 48/100
7/24/24, 8:33 PM Learn Depth
beforeCreate: function () {
this.$options.components.componentB = require('./component-b.vue').default
}
Solution2:
components: {
componentB: () => import('./component-b.vue')
}
In this case you can use runtime-only builds with Webpack + vue-loader or
Browserify + vueify technology stack through which templates will be precompiled
into render functions. This way you can make sure VueJS applications are 100%
CSP complaint.
Q84. What is the difference between full and runtime only builds?
1. Full: These are the builds that contain both the compiler and the runtime.
2. Runtime Only: These builds doesn't include compiler but the code is responsible
for creating Vue instances, rendering and patching virtual DOM. These are about
6KB lighter min+gzip.
module.exports = {
// ...
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1
}
}
}
https://learndepth.com/InterviewQa/"VueInt" 49/100
7/24/24, 8:33 PM Learn Depth
The compiler is is responsible for compiling template strings into JavaScript render
functions.
For example, the below code snippet shows the difference of templates which need
compiler and not,
VueJS is available in jsdelivr, unpkg and cdnjs etc CDNs. Normally you can use
them for prototyping or learning purposes.
For example, you can use them using jsdelivr with latest versions as below,
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script type="module">
import Vue from 'https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.esm.browser.js'
</script>
It is extremely rare situation of having to manually force an update despite the fact
that no reactive data has changed. i.e, To force the Vue instance to re-render
manually. You can do it force update using vm.$forceUpdate() API method.
https://learndepth.com/InterviewQa/"VueInt" 50/100
7/24/24, 8:33 PM Learn Depth
Note: It does not affect all child components but only the instance itself and child
components with inserted slot content.
Q90. What is the purpose of vuejs once directive?
If you want to render a lot of static content then you need to make sure it only
evaluated once and then cached thereafter. In this case, you can use v-once
directive by wrapping at the root level.
Vue.component('legal-terms', {
template: '
<div v-once>
<h1>Legal Terms</h1>
... a lot of static content goes here...
</div>
'
})
Note: It is recommended not to overuse unless there is slow rendering due to lot of
static content.
The root instance(new Vue()) can be accessed with the $root property.
First let's create a root instance with properties and methods as below,
Now you can access root instance data and it's methods with in subcomponents as
below,
https://learndepth.com/InterviewQa/"VueInt" 51/100
7/24/24, 8:33 PM Learn Depth
Below are the top 10 organizations using VueJS for their applications or products,
When the default render function encounters an error then you can use
rennderError as an alternative render output. The error will be passed to
renderError as the second argument.
new Vue({
render (h) {
throw new Error('An error')
},
renderError (h, err) {
return h('div', { style: { color: 'red' }}, err.stack)
}
}).$mount('#app')
https://learndepth.com/InterviewQa/"VueInt" 52/100
7/24/24, 8:33 PM Learn Depth
The $parent object refers to the immediate outer scope. The parent will be
accessible as this.$parent for the child, and the child will be pushed into the parent’s
$children array. It establishes a parent-child relationship between the two
instances(parent and child). You can access parent data and properties similar to
$root.
The state management has state, view and actions as major components. The
pattern followed by these components in a application is known as State
Management Pattern. Below are the components in a detail,
The state, which is the source of truth that drives our app
The view, which is just a declarative mapping of the state
The actions, which are the possible ways the state could change in reaction to user
inputs from the view.
Let us take a counter example which follows state management pattern with the
above 3 components,
new Vue({
// state
data () {
return {
count: 0
}
},
// view
template: '
<div>{{ count }}</div>
',
// actions
methods: {
increment () {
this.count++
}
}
})
https://learndepth.com/InterviewQa/"VueInt" 53/100
7/24/24, 8:33 PM Learn Depth
Vue loader is a loader for webpack that allows you to author Vue components in a
format called Single-File Components (SFCs).
<template>
<div class="greeting">{{ message }}</div>
</template>
<script>
export default {
data () {
return {
message: 'Hello world for vueloader!'
}
}
}
</script>
<style>
.greeting {
color: blue;
}
</style>
Vue Loader's configuration is a bit different from other loaders by adding Vue
Loader's plugin to your webpack config. The vue loader plugin is required for
cloning any other rules(js and css rules) defined and applying them to the
corresponding language blocks(
For example, the simple demonistration of webpack configuration for vue loader
would be as below,
https://learndepth.com/InterviewQa/"VueInt" 54/100
7/24/24, 8:33 PM Learn Depth
// webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /.vue$/,
loader: 'vue-loader'
},
// this will apply to both plain '.js' files and '<script>' blocks in '.vue'
files
{
test: /.js$/,
loader: 'babel-loader'
},
// this will apply to both plain '.css' files and '<style>' blocks in '.vue'
files
{
test: /.css$/,
use: [
'vue-style-loader',
'css-loader'
]
}
]
},
plugins: [
// make sure to include the plugin for cloning and mapping them to respective
language blocks
new VueLoaderPlugin()
]
}
https://learndepth.com/InterviewQa/"VueInt" 55/100
7/24/24, 8:33 PM Learn Depth
Vue-loader will automatically infer the proper loaders to use based on the lang
attribute of a language block and the rules defined in webpack config. You can use
pre-processors such as SASS,LESS, Stylus and PostCSS using vuejs loader.
<style scoped>
.greeting {
color: green;
}
</style>
<template>
<div class="greeting">Let's start Scoped CSS</div>
</template>
<style scoped>
.greeting[data-v-f3f3eg9] {
color: green;
}
</style>
<template>
<div class="greeting" data-v-f3f3eg9>Let's start Scoped CSS</div>
</template>
Yes, you can include both scoped and non-scoped styles in the same component. If
you don't mention scoped attribute then it will become global style.
https://learndepth.com/InterviewQa/"VueInt" 56/100
7/24/24, 8:33 PM Learn Depth
<style>
/* global styles */
</style>
<style scoped>
/* local styles */
</style>
In scoped css, if you need to modify the styles of a child component using deep
selectors(i,e from parent scoped css) then you need to use >>> combinator.
For example, the scoped deep selector on parent scoped css would be as below,
<style scoped>
.class1 >>> .class2 { /* ... */ }
</style>
Note: If you preprocessors such as SASS then it may not be able to processs >>>
properly. In such cases use the /deep/ or ::v-deep combinator instead >>>
combinator.
The parent component's styles will not leak into child components. But a child
component's root node will be affected by both the parent's scoped CSS and the
child's scoped CSS. i.e, your child component's root element has a class that also
exists in the parent component, the parent component's styles will leak to the child.
Anyway this is by design so that the parent can style the child root element for
layout purposes.
For example, the background color property of parent component leaked into child
component as below,
//parent.vue
https://learndepth.com/InterviewQa/"VueInt" 57/100
7/24/24, 8:33 PM Learn Depth
<template>
<div class="wrapper">
<p>parent</p>
<ChildMessageComponent/>
</div>
</template>
<script>
import ChildMessageComponent from "./components/child";
export default {
name: "App",
components: {
ChildMessageComponent
}
};
</script>
<style scoped>
.wrapper {
background: blue;
}
</style>
//child.vue
<template>
<div class="wrapper">
<p>child</p>
</div>
</template>
<script>
export default {
name: "Hello, Scoped CSS",
};
</script>
<style scoped>
.wrapper {
background: red;
}
</style>
Q105. How do you style dynamic generated content using scoped css?
The scoped css style doesn't impact v-html directive's dynamically generated
content. In this case, you can use deep selectors to solve this styling issue.
https://learndepth.com/InterviewQa/"VueInt" 58/100
7/24/24, 8:33 PM Learn Depth
No, templates (or any Vue-specific HTML) are ONLY allowed in .vue files and
render functions are required in other cases.
Enable CSS modules: CSS Modules must be enabled by passing modules: true
option to css-loader
// webpack.config.js
{
module: {
rules: [
// ... other rules omitted
{
test: /.css$/,
use: [
'vue-style-loader',
{
loader: 'css-loader',
options: {
// enable CSS Modules
modules: true,
// customize generated class names
localIdentName: '[local]_[hash:base64:8]'
}
}
]
}
]
}
}
<style module>
.customStyle {
background: blue;
}
</style>
Inject CSS modules: You can inject CSS modules object with computed property
$style
https://learndepth.com/InterviewQa/"VueInt" 59/100
7/24/24, 8:33 PM Learn Depth
<template>
<div :class="$style.blue">
Background color should be in blue
</p>
</template>
For example, sass-loader can configured in webpack file for sass preprocessor.
You can customize the name of the injected computed property by giving the
module attribute a value. This will be helpful to avoid overwriting injected styled if
you have more than one
<style module="a">
/* identifiers injected as a */
</style>
<style module="b">
/* identifiers injected as b */
</style>
Hot reloading is not about reloading the page when you edit any .vue file. Instead,
when you edit a *.vue file, all instances of that component will be swapped in
without reloading the page. It improves the development experience when you are
tweaking the templates or styling of your components.
https://learndepth.com/InterviewQa/"VueInt" 60/100
7/24/24, 8:33 PM Learn Depth
You can use hotReload: false option to disable the Hot Reload explicitly.
module: {
rules: [
{
test: /.vue$/,
loader: 'vue-loader',
options: {
hotReload: false // disables Hot Reload
}
}
]
}
The vue loader plugin internally uses hot reloading. If you are scaffolding project
with vue-cli, hot reloading comes out of the box but if you are manually setting up
the project then hot reloading is enabled by default with webpack-dev-server --hot
command.
https://learndepth.com/InterviewQa/"VueInt" 61/100
7/24/24, 8:33 PM Learn Depth
<template functional>
<div>{{ props.msg }}</div>
</template>
If you need to access properties defined globally on Vue.prototype then you can
access them on parent,
<template functional>
<div>{{ parent.$someProperty }}</div>
</template>
Using vue-cli: It offers pre-configured unit testing and e2e testing setups
Manual setup: You can manually setting up unit tests for *.vue files using either
mocha-webpack or jest
The stylelint linter supports linting style parts of Vue single file components. You can
run linter on particular vue file as below,
stylelint MyComponent.vue
// webpack.config.js
const StyleLintPlugin = require('stylelint-webpack-plugin');
module.exports = {
// ... other options
plugins: [
new StyleLintPlugin({
files: ['**/*.{vue,htm,html,css,sss,less,scss,sass}'],
})
]
}
https://learndepth.com/InterviewQa/"VueInt" 62/100
7/24/24, 8:33 PM Learn Depth
The official eslint-plugin-vue supports linting both the template and script parts of
Vue single file components. You can configure plugin in your ESLint config,
// .eslintrc.js
module.exports = {
extends: [
"plugin:vue/essential"
]
}
You can use eslint-loader for *.vue files in order to automatically linted on save
during development. It can be installed as npm module,
// webpack.config.js
module.exports = {
// ... other options
module: {
rules: [
{
enforce: 'pre',
test: /.(js|vue)$/,
loader: 'eslint-loader',
exclude: /node_modules/
}
]
}
}
CSS Extraction is used to extract all the processed CSS in all Vue components into
a single CSS file. For webpack4, you need to install below npm command,
https://learndepth.com/InterviewQa/"VueInt" 63/100
7/24/24, 8:33 PM Learn Depth
// webpack.config.js
var MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
// other options...
module: {
rules: [
// ... other rules omitted
{
test: /.css$/,
use: [
process.env.NODE_ENV !== 'production'
? 'vue-style-loader'
: MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
plugins: [
// ... Vue Loader plugin omitted
new MiniCssExtractPlugin({
filename: 'style.css'
})
]
}
You can define custom language blocks inside *.vue files based on the lang
attribute of the block, the block's tag name, and the rules in your webpack config.
You can also use resourceQuery to match a rule against a custom block with no
lang.
{
module: {
rules: [
{
resourceQuery: /blockType=message/,
loader: 'loader-to-use'
}
]
}
}
https://learndepth.com/InterviewQa/"VueInt" 64/100
7/24/24, 8:33 PM Learn Depth
It has more than 160 built-in rules to catch errors, apply limits and enforce stylistic
conventions
Understands latest CSS syntax including custom properties and level 4 selectors
It extracts embedded styles from HTML, markdown and CSS-in-JS object &
template literals
Parses CSS-like syntaxes like SCSS, Sass, Less and SugarSS
Supports Plugins for reusing community plugins and creating own plugins
Q125. Does Vuex support hot reloading?
Yes, vuex supports hot-reloading for mutations, modules, actions and getters during
development. You need to use either webpack's hot module replacement API or
browserify's hot module replacement plugin.
https://learndepth.com/InterviewQa/"VueInt" 65/100
7/24/24, 8:33 PM Learn Depth
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutations'
import myModule from './modules/myModule'
Vue.use(Vuex)
if (module.hot) {
// accept actions and mutations as hot modules
module.hot.accept(['./mutations', './modules/newMyModule'], () => {
// Get the updated modules
const newMutations = require('./mutations').default
const newMyModule = require('./modules/myModule').default
//swap in the new modules and mutations
store.hotUpdate({
mutations: newMutations,
modules: {
moduleA: newMyModule
}
})
})
}
Since mutations are just functions that completely rely on their arguments it will be
easier to test. You need to keep mutations inside your store.js file and should also
export the mutations as a named export apart from default export.
// mutations.js
export const mutations = {
increment: state => state.counter++
}
https://learndepth.com/InterviewQa/"VueInt" 66/100
7/24/24, 8:33 PM Learn Depth
// mutations.spec.js
import { expect } from 'chai'
import { mutations } from './store'
describe('mutations', () => {
it('INCREMENT', () => {
// mock state
const state = { counter: 10 }
// apply mutation
increment(state)
// assert result
expect(state.counter).to.equal(11)
})
})
// getters.js
export const getters = {
filterTodos (state, status) {
return state.todos.filter(todo => {
return todo.status === status
})
}
}
https://learndepth.com/InterviewQa/"VueInt" 67/100
7/24/24, 8:33 PM Learn Depth
// getters.spec.js
import { expect } from 'chai'
import { getters } from './getters'
describe('getters', () => {
it('filteredTodos', () => {
// mock state
const state = {
todos: [
{ id: 1, title: 'design', status: 'Completed' },
{ id: 2, title: 'testing', status: 'InProgress' },
{ id: 3, title: 'development', status: 'Completed' }
]
}
// mock getter
const filterStatus = 'Completed'
By proper mocking, you can bundle tests with webpack and run them on node
without having depenceny on Browser API. It involves 2 steps,
https://learndepth.com/InterviewQa/"VueInt" 68/100
7/24/24, 8:33 PM Learn Depth
// webpack.config.js
module.exports = {
entry: './test.js',
output: {
path: __dirname,
filename: 'test-bundle.js'
},
module: {
loaders: [
{
test: /.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
}
}
Run testcases: First you need to bundle and then run them using mocha as below
webpack
mocha test-bundle.js
Install mocha-loader.
Configure webpack config entry point to 'mocha-loader!babel-loader!./test.js'.
Start webpack-dev-server using the config.
Go to localhost:8080/webpack-dev-server/test-bundle to see the test result
https://learndepth.com/InterviewQa/"VueInt" 69/100
7/24/24, 8:33 PM Learn Depth
The vuex plugin is an option hat exposes hooks for each mutation. It is a normal
function that receives the store as the only argument. You can create your own
plugin or use built-in plugins. The plugin skeleton would be as below,
Similar to components you can't mutate state directly but they can trigger changes
by by committing mutations. This way a plugin can be used to sync a data source to
the store.
https://learndepth.com/InterviewQa/"VueInt" 70/100
7/24/24, 8:33 PM Learn Depth
A Vuex 'store' is basically a container that holds your application state. The store
creation is pretty straightforward.
https://learndepth.com/InterviewQa/"VueInt" 71/100
7/24/24, 8:33 PM Learn Depth
store.commit('increment')
console.log(store.state.count) // -> 1
Q136. What are the differences of vuex store and plain global object?
Below are the two major differences between vuex store and plain global object,
Vuex stores are reactive: If the store's state changes then vue components will
reactively and efficiently get updated
Cannot directly mutate the store's state: The store's state is changed by explicitly
committing mutations to ensure that every state change leaves a track-able record
for tooling purpose
We want to explicitly track application state in order to implement tools that can log
every mutation, take state snapshots, or even perform time travel debugging. So we
need to commit a mutation instead of changing store's state directly.
Vuex's single state tree is single object contains all your application level state and
serves as the 'single source of truth'. It does not conflict with modularity when you
split state and mutations into sub modules.
https://learndepth.com/InterviewQa/"VueInt" 72/100
7/24/24, 8:33 PM Learn Depth
Vue.use(Vuex)
Yes, vuex requires Promise. If your supporting browsers do not implement Promise
(e.g. IE), you can use a polyfill library, such as es6-promise using npm or yarn.
import 'es6-promise/auto'
Since Vuex stores are reactive, you can retrieve' state from store by simply
returning store's state from within a computed property. i.e, Whenever store state
changes, it will cause the computed property to re-evaluate, and trigger associated
DOM updates.
Let's take a hello word component which display store's state in the template,
https://learndepth.com/InterviewQa/"VueInt" 73/100
7/24/24, 8:33 PM Learn Depth
Vuex provides a mechanism to 'inject' the store into all child components from the
root component with the store option. It will be enabled by vue.use(vuex).
Now the store will be injected into all child components of the root and will be
available on them as this.$store
https://learndepth.com/InterviewQa/"VueInt" 74/100
7/24/24, 8:33 PM Learn Depth
export default {
// ...
computed: mapState({
// arrow functions can make the code very succinct!
username: state => state.username,
We can also pass a string array to mapState when the name of a mapped
computed property is the same as a state sub tree name
computed: mapState([
// map this.username to store.state.username
'username'
])
Q144. How do you combine local computed properties with mapState helper?
You can use object spread operator syntax in order to combine mapState
helper(which returns an object) with other local computed properties. This way it
simplify merging techniques using utilities.
computed: {
localComputed () { /* ... */ },
// mix this into the outer object with the object spread operator
...mapState({
// ...
})
}
No, if a piece of state strictly belongs to a single component, it could be just fine
leaving it as local state. i.e, Even though vuex used in the application, it doesn't
mean that you need to keep all the local state in vuex store. Other than that the
https://learndepth.com/InterviewQa/"VueInt" 75/100
7/24/24, 8:33 PM Learn Depth
code becomes more verbose and indirect although it makes your state mutations
more explicit and debuggable.
Q146. What are vuex getters??
Vuex getters acts as computed properties for stores to compute derived state based
on store state. Similar to computed properties, a getter's result is cached based on
its dependencies, and will only re-evaluate when some of its dependencies have
changed.
Let's take a todo example which as completedTodos getter to find all completed
todos,
store.getters.todosStatus
The getters can be passed as 2nd argument for other getters. For example, you can
derive completed todo's count based on their status as below,
getters: {
completedTodosCount: (state, getters) => {
return getters.todosStatus === 'completed'
}
}
https://learndepth.com/InterviewQa/"VueInt" 76/100
7/24/24, 8:33 PM Learn Depth
For example, you can pass user id to find user profile information as below,
getters: {
getUserProfileById: (state) => (id) => {
return state.users.find(user => user.id === id)
}
}
The mapGetters is a helper that simply maps store getters to local computed
properties.
For example, the usage of getters for todo app would be as below,
export default {
computed: {
// mix the getters into computed with object spread operator
...mapGetters([
'completedTodos',
'todosCount',
// ...
])
}
}
Vuex mutations are similar to any events with a string type and a handler. The
handler function is where we perform actual state modifications, and it will receive
the state as the first argument.
For example, the counter example with increment mutation would be as below,
https://learndepth.com/InterviewQa/"VueInt" 77/100
7/24/24, 8:33 PM Learn Depth
You can't directly invoke mutation instead you need to call store.commit with its
type. The above mutation would be triggered as folows
store.commit('increment')
You can also pass payload for the mutation as an additional argument to
store.commit.
For example, the counter mutation with payload object would be as below,
mutations: {
increment (state, payload) {
state.count += payload.increment
}
}
store.commit('increment', {
increment: 20
})
You can also commit a mutation is by directly using an object that has a type
property.
https://learndepth.com/InterviewQa/"VueInt" 78/100
7/24/24, 8:33 PM Learn Depth
store.commit({
type: 'increment',
value: 20
})
Now the entire object will be passed as the payload to mutation handlers(i.e, without
any changes to handler signature).
mutations: {
increment (state, payload) {
state.count += payload.value
}
}
Since a Vuex store's state is made reactive by Vue, the same reactivity caveats of
vue will apply to vuex mutations. These are the rules should be followed for vuex
mutations,
It is recommended to initialize store's initial state with all desired fields upfront
Add new properties to state Object either by set method or object spread syntax
You need to remember that mutation handler functions must be synchronous. This
is why because any state mutation performed in the callback is essentially un-
trackable. It is going to be problematic when the devtool will need to capture a
'before' and 'after' snapshots of the state during the mutations.
mutations: {
someMutation (state) {
api.callAsyncMethod(() => {
state.count++
})
}
}
https://learndepth.com/InterviewQa/"VueInt" 79/100
7/24/24, 8:33 PM Learn Depth
export default {
methods: {
...mapMutations([
'increment', // map 'this.increment()' to 'this.$store.commit('increment')
No, it is not mandatory. But you might observed that State management
implementations such Flux and Redux use constants for mutation types. This
convention is just a preference and useful to take advantage of tooling like linters,
and putting all constants in a single file allows your collaborators to get an at-a-
glance view of what mutations are possible in the entire application.
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
https://learndepth.com/InterviewQa/"VueInt" 80/100
7/24/24, 8:33 PM Learn Depth
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'
Actions are similar to mutations, but there are two main differences,
Vuex provides actions property similar mutations property in order to define action
handlers. These action handlers receive context object as an argument which has
same properties and methods of store instance.
https://learndepth.com/InterviewQa/"VueInt" 81/100
7/24/24, 8:33 PM Learn Depth
store.dispatch('increment')
Yes, actions support both payload and object style format similar to mutations
https://learndepth.com/InterviewQa/"VueInt" 82/100
7/24/24, 8:33 PM Learn Depth
For example, you can dispatch increment actions in counter component as below,
export default {
// ...
methods: {
...mapActions([
'increment', // map 'this.increment()' to
'this.$store.dispatch('increment')'
You can write multiple actions together to handle more complex async flows either
by chaining promises or async/await. i.e, store.dispatch can handle Promise
returned by the triggered action handler and it also returns Promise.
Let's take two actions to see how they are combined and handled async flows,
actions: {
actionOne ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('first mutation')
resolve()
}, 1000)
})
},
actionTwo ({ dispatch, commit }) {
return dispatch('actionA').then(() => {
commit('second mutation')
})
}
}
As per the above example, When you try to dispatch actionTwo it dispatchs
actionOne first and then commits respective mutation. You can still simplify with
async/await as below,
https://learndepth.com/InterviewQa/"VueInt" 83/100
7/24/24, 8:33 PM Learn Depth
actions: {
async actionOne ({ commit }) {
commit('first mutation', await getDataAsPromise())
},
async actionTwo ({ dispatch, commit }) {
await dispatch('actionOne') // wait for 'actionA' to finish
commit('second mutation', await getSomeDataAsPromise())
}
}
If you keep all state of our application in a single big state, the store can get really
bloated. To solve this problem, Vuex allows us to divide our store into modules.
Here, each module can contain its own state, mutations, actions, getters, and even
nested modules.
Let's take an example with multiple modules, configuring them in vuex and
accessing different modules,
const moduleOne = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleTwo = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
When you use modules the local state will be available to mutations, getters and
actions in different ways.
Both mutations and getters will receive module local state as first argument
https://learndepth.com/InterviewQa/"VueInt" 84/100
7/24/24, 8:33 PM Learn Depth
const moduleOne = {
state: { count: 0 },
mutations: {
increment (state) {
state.count++; // Here state refers local module state
}
},
getters: {
average (state) {
return state.count / 2
}
}
}
const moduleOne = {
actions: {
incrementConditional ({ state, commit, rootState }) {
if (state.count < rootState.count) {
commit('increment')
}
}
}
}
By default, actions, mutations and getters inside modules are still registered under
the global namespace. Because of that multiple modules react to the same
mutation/action type.
https://learndepth.com/InterviewQa/"VueInt" 85/100
7/24/24, 8:33 PM Learn Depth
In strict mode, you can't mutate state directly using v-model attribute. If you use v-
model it throws an error because mutation is not performed inside an explicit Vuex
mutation handler.
For example, the below input throws an error due to v-model usage
<input v-model="stateObject.message">
In this case, you need to bind the 's value. It can be resolved using value attribute
as below,
computed: {
...mapState({
username: state => state.user.username
})
},
methods: {
updateProfile (e) {
this.$store.commit('updateProfile', e.target.value)
}
},
mutations: {
updateProfile (state, username) {
state.user.username = username
}
}
Q171. How to use model directive with two way computed property?
You can still use model directive using two-way computed property with a setter.
https://learndepth.com/InterviewQa/"VueInt" 86/100
7/24/24, 8:33 PM Learn Depth
<input v-model="username">
computed: {
username: {
get () {
return this.$store.state.user.username
},
set (value) {
this.$store.commit('updateProfile', value)
}
}
}
mutations: {
updateProfile (state, username) {
state.user.username = username
}
}
Vue CLI is a simple command line interface for scaffolding Vue.js projects. It will be
helpful for rapid Vue.js development. You can install the npm package globally as
below,
You can find the install version using vue --version command. Note: Vue CLI
requires Node.js version 8.9 or above (8.11.0+ recommended).
In Vue CLI, Instant prototyping is known as rapid prototyping with just a single *.vue
file with the vue serve(similar to vue create) and vue build commands. But you need
to install below global addon for this.
https://learndepth.com/InterviewQa/"VueInt" 87/100
7/24/24, 8:33 PM Learn Depth
You can also provide entry component for vue serve and target file for vue build
using below commands
Vue CLI uses a plugin-based architecture where each plugin can modify the internal
webpack configuration and inject commands to vue-cli-service. i.e, Each feature is
implemented as a plugin. This architecture makes Vue CLI flexible and extensible.
You can install a plugin into an already created project with the vue add command.
If a plugin is already installed, you can skip the installation and only invoke its
generator with the vue invoke command.
If you need access to the plugin API in your project without creating a full plugin,
you can use the vuePlugins.service option in your package.json file
{
"vuePlugins": {
"service": ["my-service.js"]
}
}
https://learndepth.com/InterviewQa/"VueInt" 88/100
7/24/24, 8:33 PM Learn Depth
You can also add files that will behave like UI plugins with the vuePlugins.ui option
{
"vuePlugins": {
"ui": ["my-ui.js"]
}
}
A Vue CLI preset is a JSON object that contains pre-defined options and plugins for
creating a new project without interactive prompts to select them. During project
creation(using vue create), the presets will be saved in a ~/.vuerc which can
modified at any time.
{
"useConfigFiles": true,
"router": true,
"vuex": true,
"cssPreprocessor": "sass",
"plugins": {
"@vue/cli-plugin-babel": {},
"@vue/cli-plugin-eslint": {
"config": "airbnb",
"lintOn": ["save", "commit"]
}
}
}
{
"plugins": {
"@vue/cli-plugin-eslint": {
"version": "^3.0.0",
// ... other options for this plugin
}
}
}
For official plugins, the CLI will automatically use the latest version available in the
registry
https://learndepth.com/InterviewQa/"VueInt" 89/100
7/24/24, 8:33 PM Learn Depth
Each plugin can inject its own prompts during the project creation process
irrespective of preset declarations using prompts: true setting
For example, user can pick their own ESLint config using the below configuration
{
"plugins": {
"@vue/cli-plugin-eslint": {
// let the users pick their own ESLint config
"prompts": true
}
}
}
You can share a preset with other developers by publishing it in a git repo. The repo
can be published in either github, GitLab or BitBucket. The repo will contain below
files,
preset.json: The main file containing the preset data and it is required.
generator.js: A generator that can inject or modify files in the project.
prompts.js: A prompts file that can collect options for the generator. You can apply --
preset option to use remote presets while creating the project
Yes, Vue CLI will load local presets if the value for the --preset option is a relative or
absolute file path, or ends with .json. i.e, You can work with local presets directly.
These local presets avoids repeatedly pushing the preset to a remote repo to test.
https://learndepth.com/InterviewQa/"VueInt" 90/100
7/24/24, 8:33 PM Learn Depth
"browserslist": [
"last 1 version",
"> 1%",
"IE 10"
]
The community plugins and components might need different strategies for different
versions. In this case, you can use Vue.version which provides installed version of
Vue as a string.
For example, you can implement different logic based on different versions
if (version === 2) {
// Vue v2.x.x
} else if (version === 1) {
// Vue v1.x.x
} else {
// Unsupported versions of Vue
}
In version 3.0 you can create a reactive object with the reactive() API.
In version 2.6, you can create reactive objects with Vue.observable() global API.
These observable objects can be used directly in computed properties and render
functions.
https://learndepth.com/InterviewQa/"VueInt" 91/100
7/24/24, 8:33 PM Learn Depth
const Demo = {
render(h) {
return h('button', {
on: { click: () => { reactiveState.count++ }}
}, 'count is: $ {state.count}')
}
}
In Vue 2.6 version, the new slot syntax is provided using v-slot directive which
aligns syntax with Vue 3.0. This is going to be replacement for old slot syntax.
VueJS provides compile method which is used to compile a template string into a
render function. This method is only available in the full build.
new Vue({
data: {
msg: 'Welcome to Vue world'
},
render: result.render,
staticRenderFns: result.staticRenderFns
})
https://learndepth.com/InterviewQa/"VueInt" 92/100
7/24/24, 8:33 PM Learn Depth
The nextTick method is just a comfortable way to execute a function after the data
has been set, and the DOM has been updated. As an example, the usage is going
to be similar to setTimeout:
// modify data
vm.msg = 'Welcome to Vue'
// DOM not updated yet
Vue.nextTick(function () {
// DOM updated
})
From 2.6 version onwards, Vue's built-in error handling mechanism can capture
errors inside v-on handlers. Also,if any of your lifecycle hooks or event handlers
performs asynchronous operations, you can now return a Promise from the function
so that any uncaught errors from that Promise chain are also sent to your error
handlers.
export default {
async mounted() {
// if an async error is thrown here, it now will get
// caught by errorCaptured and Vue.config.errorHandler
this.todos = await api.getTodos()
}
}
In Vue 2.6 release onwards, Directive arguments can now accept dynamic
JavaScript expressions. i.e, the specific argument that we want to use is only known
at runtime.
Let's assign dynamic key and event directives for a div element,
<div v-bind:[key]="value"></div>
<div v-on:[event]="handler"></div>
https://learndepth.com/InterviewQa/"VueInt" 93/100
7/24/24, 8:33 PM Learn Depth
Apart from the benefits of dynamic directives arguments, it brings two drawbacks or
considerations on the usage
Dynamic argument values are expected to be strings but it allows null as a special
value that explicitly indicates that the binding should be removed. Other types will
be treated as mistakes and will trigger a warning. So null value can be applied for v-
bind and v-on.
No. It can be applied only for v-bind and v-on but not v-slot. This is because v-slot is
not a binding and cannot be removed.
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-i18n/dist/vue-i18n.js"></script>
<div id="app">
<p>{{ $t("user.message") }}</p>
</div>
https://learndepth.com/InterviewQa/"VueInt" 94/100
7/24/24, 8:33 PM Learn Depth
You can use custom formatting for some of the formatting cases such as ICU
formatting syntax (message 'pattern' strings with variable-element placeholders
enclosed in {curly braces}). It implement Formatter Interface.
https://learndepth.com/InterviewQa/"VueInt" 95/100
7/24/24, 8:33 PM Learn Depth
// Run!
new Vue({ i18n }).$mount('#app')
You can translate with pluralization by defining the locale that have a pipe |
separator, and define plurals in pipe separator. Remember that template should use
$tc() instead of $t().
const messages = {
en: {
user: 'user | users',
friend: 'no friend | one friend | {count} friends'
}
}
https://learndepth.com/InterviewQa/"VueInt" 96/100
7/24/24, 8:33 PM Learn Depth
<p>user</p>
<p>users</p>
<p>no friend</p>
<p>one friend</p>
<p>10 friends</p>
You can localize the datetime with definition formats(e.g. short, long, etc).
For example, you can add definition formats for English and Jappan locale as below
const dateTimeFormats = {
'en-US': {
short: {
year: 'numeric', month: 'short', day: 'numeric'
},
long: {
year: 'numeric', month: 'short', day: 'numeric',
weekday: 'short', hour: 'numeric', minute: 'numeric'
}
},
'ja-JP': {
short: {
year: 'numeric', month: 'short', day: 'numeric'
},
long: {
year: 'numeric', month: 'short', day: 'numeric',
weekday: 'short', hour: 'numeric', minute: 'numeric', hour12: true
}
}
}
After that You need to specify the dateTimeFormats option of VueI18n constructor
new Vue({
i18n
}).$mount('#app')
https://learndepth.com/InterviewQa/"VueInt" 97/100
7/24/24, 8:33 PM Learn Depth
<div id="app">
<p>{{ $d(new Date(), 'short') }}</p>
<p>{{ $d(new Date(), 'long', 'ja-JP') }}</p>
</div>
<div id="app">
<p>May 20, 2019</p>
<p>2019年5月20日</p>
</div>
You can localize the number with definition formats(e.g. currency, etc)
You need to add definition formats. For example, lets add it for English and
Japanese locales
const numberFormats = {
'en-US': {
currency: {
style: 'currency', currency: 'USD'
}
},
'ja-JP': {
currency: {
style: 'currency', currency: 'JPY', currencyDisplay: 'symbol'
}
}
}
new Vue({
i18n
}).$mount('#app')
https://learndepth.com/InterviewQa/"VueInt" 98/100
7/24/24, 8:33 PM Learn Depth
<div id="app">
<p>{{ $n(10, 'currency') }}</p>
<p>{{ $n(50, 'currency', 'ja-JP') }}</p>
</div>
<div id="app">
<p>$10.00</p>
<p>¥50</p>
</div>
All child components of a root instance are localized using the locale property of the
VueI18n class. You can change the value of the locale property of the VueI18n
instance as below.
You can also use component's VueI18n instance referenced as the $i18n property
which will be used to change the locale.
https://learndepth.com/InterviewQa/"VueInt" 99/100
7/24/24, 8:33 PM Learn Depth
<template>
<div class="locale-changer">
<select v-model="$i18n.locale">
<option v-for="(lang, i) in langs" :key='Lang$ {i}' :value="lang">{{ lang }}
</option>
</select>
</div>
</template>
<script>
export default {
name: 'locale-changer',
data () {
return { langs: ['de', 'en'] }
}
}
</script>
https://learndepth.com/InterviewQa/"VueInt" 100/100