Frequently asked - Vue JS Interview Questions and Answers - Part 02
21. Explain watchers in Vue.js?
Vue provides a more generic way to react to data changes through the watch
option. This is most useful when we want to perform asynchronous or expensive operations in response to changing data, like fetching asynchronous data when user inputs something.
<input v-model="question">
In Vue instance, we could watch the model data and react to changes.
var watchExampleVM = new Vue({
el: '#watch-example',
watch: {
// whenever question changes, this function will run
question: function (newQuestion, oldQuestion) {
// do asynchronous task
}
},
})
22. What are components in Vue.js?
Components are reusable Vue instances with a name. Vue.js allows us to create custom HTML elements that can be used within our views. To define and register a custom HTML element, we must create a Vue component using the component
method of the Vue
class.
// Define a new component called button-counter
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
Now we can use the component as below:
<div id="components-demo">
<button-counter></button-counter>
</div>
Since components are reusable Vue
instances, they accept the same options as new Vue, such as data
, computed
, watch
, methods
, and lifecycle hooks. The only exceptions are a few root-specific options like el
. Also, a component’s data option must be a function, so that each instance can maintain an independent copy of the returned data object.
23. How do you pass data to the component?
We can pass any value to a component as props. 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.
For example, to pass a message
property to the greeting
, we have included it in the list of properties that the component accepts, using the props
option.
Vue.component('greeting', {
props: ['message'],
template: '<h3>Hello, {{ message }}</h3>'
})
Once a prop is registered, you can pass data to it as a custom attribute, like this:
<greeting message="Welcome"></greeting>
24. How to communicate with the parent component from child?
Vue instances provide a custom events system to communicate with parent component. To emit an event to the parent, we can call the built-in $emit
method, passing the name of the event.
For example, the button
below is in the child component and emit a function when clicked.
<button v-on:click="$emit('enlarge-text', 0.1)">
Enlarge text
</button>
Then when we listen to the event in the parent, we can access the emitted event’s value with $event
:
<greeting
v-on:enlarge-text="postFontSize += $event">
</greeting>
25. What is slots in Vue.js?
Sometimes we will need to allow our parent Vue components to embed arbitrary content inside of child components. (In Angular, it is known as transclusion) Vue provides an easy way to do this via slots.
<div>
<p>I'm the child component!</p>
<!-- Content from the parent gets rendered here. -->
<slot></slot>
</div>
If there is no <slot></slot>
element in the child’s template, any content from the parent will be silently discarded. If the parent does not inject any content into the child’s slot, the child will render any elements inside its <slot></slot>
tag which is a fallback or default content.
26. How do you handle multiple slots? What is named slot?
When we want to handle multiple slots, Vue allows us to do this by way of named slots. Named slots are simply slots with a name attribute <slot name="slotName"></slot>
to allow for namespaced content injection.
<div class="child-component">
<!-- Elements injected with the `slot="top-slot"`
attribute will end up in here. -->
<slot name="top-slot">
</slot>
<!-- A slot tag without a name is a catch-all,
it will contain any content that doesn't have
a `slot=""` attribute. -->
<slot>
</slot>
<!-- Elements injected with the `slot="bottom-slot"`
attribute will end up in here. -->
<slot name="bottom-slot">
</slot>
</div>
The below markup is for the parent component:
<child-component>
<div slot="top-slot">
this is the content for the top slot
</div>
<div slot="bottom-slot">
this is the content for the bottom slot
</burger-bun>
<!-- Everything else gets injected into the middle slot (as it's not named.) -->
<div>
this is the content for middle slot.
</div><br/></child-component>
27. Can you access the root instance of the Vue instance? If so, how can you do that?
In every subcomponent of a new Vue
instance, the root instance can be accessed with the $root
property. For example, in this root instance:
// The root Vue instance
new Vue({
data: {
foo: 1
},
computed: {
bar: function () { /* ... */ }
},
methods: {
baz: function () { /* ... */ }
}
})
All subcomponents will now be able to access this instance and use it as a global store:
// Get root data
this.$root.foo
// Set root data
this.$root.foo = 2
// Access root computed properties
this.$root.bar
// Call root methods
this.$root.baz()
28. What is $parent
in Vue?
Similar to $root
, the $parent
property can be used to access the parent instance from a child.
Although it provides direct access, it makes the application hard to test and debug. And we can not easily find out the where the mutation come from.
Vue also provides $child
just like $parent
, but it can be used to access the child instance.
29. What is the role of ref
in Vue.js?
Despite the existence of props and events, sometimes if we still need to directly access a child component, we can assign a reference ID to the child component using the ref attribute. For example:
<base-input ref="usernameInput"></base-input>
Now in the component where we have defined this ref
, we can use:
this.$refs.usernameInput
$refs
are only populated after the component has been rendered, and they are not reactive. Hence we should avoid accessing $refs
from within templates or computed properties.
30. What are the caveats of object changes detection?
Vue cannot detect changes for the object in property addition or deletion. Lets take an example of user data changes,
var vm = new Vue({
data: {
user: {
name: 'John'
}
}
})
// `vm.name` is now reactive
vm.email = john@email.com // `vm.email` is NOT reactive
You can overcome this scenario using the Vue.set(object, key, value)
method or Object.assign()
,
Vue.set(vm.user, 'email', john@email.com);
// or
vm.user = Object.assign({}, vm.user, {
email: john@email.com
})
31. What are the event modifiers provided by Vue.js?
Normally, javascript provides event.preventDefault()
or event.stopPropagation()
inside event handlers. Although we can do this easily inside methods, it would be better if the methods can be purely about data logic rather than having to deal with DOM event details. For this, Vue.js provides event modifiers for v-on
and these are directive postfixes denoted by a dot.
.stop
- the click event’s propagation will be stopped..prevent
- thepreventDefault()
will be called..capture
- use capture mode when adding the event listener i.e. an event targeting an inner element is handled here before being handled by that element..self
- only trigger handler if event.target is the element itself i.e. not from a child element..once
- the click event will be triggered at most once.passive
- indicates that the function specified by listener will never callpreventDefault()
. If a passive listener does callpreventDefault()
, the user agent will do nothing other than generate a console warning.
These modifiers can be chained but the order of the chain matters because the relevant code is generated in the same order.
<!-- the click event's propagation will be stopped -->
<a v-on:click.stop="doThis"></a>
<!-- the submit event will no longer reload the page -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- modifiers can be chained -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- just the modifier -->
<form v-on:submit.prevent></form>
<!-- use capture mode when adding the event listener -->
<!-- i.e. an event targeting an inner element is handled here before being handled by that element -->
<div v-on:click.capture="doThis">...</div>
<!-- only trigger handler if event.target is the element itself -->
<!-- i.e. not from a child element -->
<div v-on:click.self="doThat">...</div>
32. What are key modifiers?
When listening for keyboard events, we often need to check for common key codes. Vue.js also allows adding key modifiers for v-on
when listening for key events:
<!-- only call `vm.submit()` when the `keyCode` is 13 -->
<input v-on:keyup.13="submit">
Remembering all the keyCodes is a hassle, so Vue.js provides aliases for the most commonly used keys:
<!-- same as above -->
<input v-on:keyup.enter="submit">
There are some list of important keyCode aliases in Vue.js such as: .tab
, .delete
, .esc
, .space
, .up
, .down
, .left
and .right
. Apart from these, we can also create our own aliases:
// enable `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
33. What are the supported System Modifier Keys?
We can use the following modifiers to trigger mouse or keyboard event listeners only when the corresponding modifier key is pressed.
.ctrl
, .alt
, .shift
and .meta
For example:
<!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
In addition, we can use the .exact
modifier which allows control of the exact combination of system modifiers needed to trigger an event.
<!-- this will only fire when Ctrl and no other keys are pressed -->
<input @click.ctrl.exact="onCtrlClick">
34. What are the supported modifiers on model?
There are three modifiers supported for v-model
directive.
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.
<!-- synced after "change" instead of "input" -->
<input v-model.lazy="msg" >
number
: If we want user input to be automatically typecast as a number, we can add the number modifier to our v-model
. Even with type="number"
, the value of HTML input elements always returns a string. So, this typecast modifier is required.
<input v-model.number="age" type="number">
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">
35. How do you implement model on custom input components?
The custom events can also be used to create custom inputs that work with v-model
. The inside the component must follow below rules,
- Bind the value attribute to a value prop
- On input, emit its own custom input event with the new value. Lets take a custom-input component as an example,,
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
Now we can use v-model
with this component,
<custom-input v-model="searchInput"></custom-input>
36. What is global registration in components?
The components which are globally registered can be used in the template of any root Vue instance (new Vue) created after registration. In the global registration, the components created using Vue.component as below,
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', { /* ... */ })
new Vue({ el: '#app' })
Remember that the components can be used in subcomponents as well. The above components can be used in the vue instance,
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c><br/></div>
37. Why do we need local registration?
Global registration often isn’t ideal. For example, if we are using a build system like Webpack, globally registering all components means that even if we stop using a component, it could still be included in our final build. This unnecessarily increases the amount of JavaScript your users have to download. In these cases, you can define your components as plain JavaScript objects:
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }
Then define the components you’d like to use in a components
option:
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
Note that locally registered components are not also available in subcomponents.
38. What is Mixins?
Mixins are a flexible way to distribute reusable functionalities for Vue components. A mixin object can contain any component options. When a component uses a mixin, all options in the mixin will be “mixed” into the component’s own options. Example:
// define a mixin object
var myMixin = {
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('hello from mixin!')
}
}
}
// define a component that uses this mixin
var Component = Vue.extend({
mixins: [myMixin]
})
var component = new Component() // => "hello from mixin!"
39. What is Option Merging?
When a mixin and the component itself contain overlapping options, they will be “merged” using appropriate strategies.
For example, data objects undergo a recursive merge, with the component’s data taking priority in cases of conflicts.
var mixin = {
data: function () {
return {
message: 'hello',
foo: 'abc'
}
}
}
new Vue({
mixins: [mixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log(this.$data)
// => { message: "goodbye", foo: "abc", bar: "def" }
}
})
40. Explain the Global Mixin?
We can also apply a mixin globally. Once we apply a mixin globally, it will affect every Vue instance created afterwards. When used properly, this can be used to inject processing logic for custom options:
// inject a handler for `myOption` custom option
Vue.mixin({
created: function () {
var myOption = this.$options.myOption
if (myOption) {
console.log(myOption)
}
}
})
new Vue({
myOption: 'hello!'
})
// => "hello!"