Frequently asked - Vue JS Interview Questions and Answers - Part 03
41. Explain Simple State Management in Vue.js
Like Redux, Vue offers vuex: its own Elm-inspired state management library. It even integrates into vue-devtools, providing zero-setup access to time travel debugging.
The below example depicts a simple store:
var store = {
debug: true,
state: {
message: 'Hello!'
},
setMessageAction (newValue) {
if (this.debug) console.log('setMessageAction triggered with', newValue)
this.state.message = newValue
},
clearMessageAction () {
if (this.debug) console.log('clearMessageAction triggered')
this.state.message = ''
}
}
Now all actions that mutate the store’s state are put inside the store itself. This type of centralized state management makes it easier to understand what type of mutations could happen and how they are triggered. Now when something goes wrong, we’ll also have a log of what happened leading up to the bug.
In addition, each instance/component can still own and manage its own private state:
var vmA = new Vue({
data: {
privateState: {},
sharedState: store.state
}
})
var vmB = new Vue({
data: {
privateState: {},
sharedState: store.state
}
})
As we continue developing the convention where components are never allowed to directly mutate state that belongs to a store, but should instead dispatch events that notify the store to perform actions, we eventually arrive at the Flux architecture.
42. How Vue.js track changes?
When you pass a plain JavaScript object to a Vue instance as its data option, Vue will walk through all of its properties and convert them to getter/setters using Object.defineProperty
.
The getter/setters are invisible to the user, but under the hood they enable Vue to perform dependency-tracking and change-notification when properties are accessed or modified.
Every component instance has a corresponding watcher instance, which records any properties “touched” during the component’s render as dependencies. Later on when a dependency’s setter is triggered, it notifies the watcher, which in turn causes the component to re-render.
43. What are the caveats in Vue.js change detection?
Due to the limitations of modern JavaScript, Vue cannot detect property addition or deletion. Since Vue performs the getter/setter conversion process during instance initialization, a property must be present in the data object in order for Vue to convert it and make it reactive. For example:
var vm = new Vue({
data: {
a: 1
}
})
// `vm.a` is now reactive
vm.b = 2
// `vm.b` is NOT reactive
Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object using the Vue.set(object, key, value)
method:
Vue.set(vm.someObject, 'b', 2)
We can also use the vm.$set
instance method, which is an alias to the global Vue.set:
this.$set(this.someObject, 'b', 2)
New properties added to the object will not trigger changes. In such cases, create a fresh object with properties from both the original object and the mixin object like below:
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
44. What are the caveats in array change detection?
Due to limitations in JavaScript, Vue cannot detect the following changes to an array:
- When we directly set an item with the index, e.g.
vm.items[indexOfItem = newValue]
To overcome this caveat we can modify the array as shown below:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
- When we modify the length of the array, e.g.
vm.items.length = newLength
. For example:
var vm = new Vue({
data: {
items: ['a', 'b', 'c'
}
})
vm.items[1 = 'x' // is NOT reactive
vm.items.length = 2 // is NOT reactive
To deal with this, we can use splice:
vm.items.splice(newLength)
45. 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 that easier, Vue allows you to define our component as a factory function that asynchronously resolves your component definition. Vue will only trigger the factory function when the component needs to be rendered and will cache the result for future re-renders. For example:
Vue.component('async-example', function (resolve, reject) {
setTimeout(function () {
// Pass the component definition to the resolve callback
resolve({
template: '<div>I am async!</div>'
})
}, 1000)
})
As we can see, the factory function receives a resolve callback, which should be called when we have retrieved your component definition from the server. We can also call reject(reason)
to indicate the load has failed.
46. What are filters in Vue.js?
Vue.js allows us to define filters that can be used to apply common text formatting. Filters are usable in two places: mustache interpolations and v-bind
expressions. Filters should be appended to the end of the JavaScript expression, denoted by the “pipe” symbol:
<!-- in mustaches --><br/>{{ message | capitalize }}<br/><br/><!-- in v-bind --><br/><div v-bind:id="rawId | formatId"></div>
47. How do we create our own filters?
We can define our local filters in a component’s options like below:
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
or define a filter globally before creating the Vue instance:
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
The filter’s function always receives the expression’s value (the result of the former chain) as its first argument. In the above example, the capitalize
filter function will receive the value of message as its argument.
Filters can also be chained:
{{ message | filterA | filterB }}
48. How do you pass arguments to filters?
Filters are JavaScript functions, therefore they can take arguments:
{{ message | filterA('arg1', arg2) }}
Here filterA
is defined as a function taking three arguments. The value of message will be passed into the first argument. The plain string ‘arg1
’ will be passed into the filterA
as its second argument, and the value of expression arg2
will be evaluated and passed in as the third argument.
49. What is Vue Router?
Vue Router is the official router for Vue.js. It deeply integrates with Vue.js core to make building Single Page Applications with Vue.js easy to implement. Its features include:
- Nested route/view mapping
- Modular, component-based router configuration
- Route params, query, wildcards
- View transition effects powered by Vue.js’ transition system
- Fine-grained navigation control
- Links with automatic active CSS classes
- Customizable Scroll Behavior
- HTML5 history mode or hash mode, with auto-fallback in IE9
50. How do you define routes in Vue Router?
With Vue.js, we are already composing our application with components. When adding Vue Router to the mix, all we need to do is map our components to the routes and let Vue Router know where to render them. Here’s a basic example:
<p>
<!-- use router-link component for navigation. -->
<!-- specify the link by passing the `to` prop. -->
<!-- `<router-link>` will be rendered as an `<a>` tag by default -->
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
<!-- route outlet -->
<!-- component matched by the route will render here -->
<router-view></router-view>
</p>
In Javascript, define the routes as below:
const Foo = {
template: '<div>foo</div>'
}
const Bar = {
template: '<div>bar</div>'
}
// Each route should map to a component. The "component" can
// either be an actual component constructor created via
// `Vue.extend()`, or just a component options object.
// We'll talk about nested routes later.
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
// You can pass in additional options here, but let's
// keep it simple for now.
const router = new VueRouter({
routes // short for `routes: routes`
})
Finally, create and mount the root instance.
// Make sure to inject the router with the router option to make the
// whole app router-aware.
const app = new Vue({
router
}).$mount('#app')
51. What is Vue-cli?
The Vue CLI ( @vue/cli ) is a npm package and provides the vue command in our terminal. It provides the ability to quickly scaffold a new project via vue create, or instantly prototype new ideas via vue serve. We can also manage your projects using a graphical user interface via vue ui.
Vue CLI aims to be the standard tooling baseline for the Vue ecosystem. It ensures the various build tools work smoothly together with sensible defaults so you can focus on writing your app instead of spending days wrangling with configurations. At the same time, it still offers the flexibility to tweak the config of each tool without the need for ejecting.
To install the package, use one of those commands:
npm install -g @vue/cli
# OR
yarn global add @vue/cli
To create a new project, run:
vue create hello-world