151. What is mapState helper?
In Vuex application, creating a computed property every time whenever we want to access the store's state property or getter is going to be repetitive and verbose, especially if a component needs more than one state property. In this case, we can make use of the mapState helper of vuex which generates computed getter functions for us.
Let's take an increment example to demonstrate mapState helper,
```javascript
// in full builds helpers are exposed as Vuex.mapState
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// arrow functions can make the code very succinct!
username: state => state.username,
// passing the string value 'username' is same as `state => state.username`
usernameAlias: 'username',
// to access local state with `this`, a normal function must be used
greeting (state) {
return this.localTitle + 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
```javascript
computed: mapState([
// map this.username to store.state.username
'username'
])
```
152. 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.
```javascript
computed: {
localComputed () { /* ... */ },
// mix this into the outer object with the object spread operator
...mapState({
// ...
})
}
```
153. Do you need to replace entire local state with vuex?
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 the code becomes more verbose and indirect although it makes your state mutations more explicit and debuggable.
154. 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,
```javascript
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: 'Vue course', completed: true },
{ id: 2, text: 'Vuex course', completed: false },
{ id: 2, text: 'Vue Router course', completed: true }
]
},
getters: {
completedTodos: state => {
return state.todos.filter(todo => todo.completed)
}
}
})
```
**Note:**Getters receive state as first argument.
155. What is a property style access?
You can access values of store's getter object(store.getters) as properties. This is known as property style access.
For example, you can access todo's status as a property,
```javascript
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,
```javascript
getters: {
completedTodosCount: (state, getters) => {
return getters.todosStatus === 'completed'
}
}
```
**Note:** The getters accessed as properties are cached as part of Vue's reactivity system.
156. What is a method style access?
You can access store's state in a method style by passing arguments. For example, you can pass user id to find user profile information as below,
```javascript
getters: {
getUserProfileById: (state) => (id) => {
return state.users.find(user => user.id === id)
}
}
```
After that you can access it as a method call,
```javascript
store.getters.getUserProfileById(111); {id: '111', name: 'John', age: 33}
```
157. What is mapGetter helper??
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,
```javascript
import { mapGetters } from 'vuex'
export default {
computed: {
// mix the getters into computed with object spread operator
...mapGetters([
'completedTodos',
'todosCount',
// ...
])
}
}
```
158. What are mutations?
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,
```javascript
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
// mutate state
state.count++
}
}
})
```
You can't directly invoke mutation instead you need to call `store.commit` with its type. The above mutation would be triggered as folows
```javascript
store.commit('increment')
```
159. How do you commit with payload?
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,
```javascript
mutations: {
increment (state, payload) {
state.count += payload.increment
}
}
```
And then you can trigger increment commit
```javascript
store.commit('increment', {
increment: 20
})
```
**Note:** You can also pass primitives as payload.
160. What is object style commit?
You can also commit a mutation is by directly using an object that has a **type** property.
```javascript
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).
```javascript
mutations: {
increment (state, payload) {
state.count += payload.value
}
}
```
161. What are the caveats with vuex mutations?
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,
1. It is recommended to initialize store's initial state with all desired fields upfront
2. Add new properties to state Object either by set method or object spread syntax
```javascript
Vue.set(stateObject, 'newProperty', 'John')
```
(OR)
```javascript
state.stateObject = { ...state.stateObject, newProperty: 'John' }
```
162. Why mutations should be synchronous?
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.
```javascript
mutations: {
someMutation (state) {
api.callAsyncMethod(() => {
state.count++
})
}
}
```
163. How do you perform mutations in components?
You can commit mutations in components with either **this.$store.commit('mutation name')** or mapMutations helper to map component methods to **store.commit** calls.
For example, the usage of mapMutations helper on counter example would be as below,
```javascript
import { mapMutations } from 'vuex'
export default {
methods: {
...mapMutations([
'increment', // map `this.increment()` to `this.$store.commit('increment')`
// `mapMutations` also supports payloads:
'incrementBy' // map `this.incrementBy(amount)` to `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // map `this.add()` to `this.$store.commit('increment')`
})
}
}
```
164. Is it mandatory to use constants for mutation types?
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.
For example, the mutations can be declared as below,
```javascript
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
```
And you can configure them in store as follows,
```javascript
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'
const store = new Vuex.Store({
state: { ... },
mutations: {
// ES2015 computed property name feature to use a constant as the function name
[SOME_MUTATION] (state) {
// mutate state
}
}
})
```
165. How do you perform asynchronous operations?
In Vuex, mutations are synchronous transactions. But if you want to handle asynchronous operations then you should use **actions**.
166. What are differences between mutations and actions?
Actions are similar to mutations, but there are two main differences,
1. Mutations perform mutations on the state, actions commit mutations.
2. Actions can contain arbitrary asynchronous operations unlike mutations.
167. Give an example usage of actions?
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.
Let's see counter example to demonstrate increment action which commits respective mutation,
```javascript
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
```
168. How do you dispatch actions?
Actions are simply triggered with the store.dispatch method as below,
```javascript
store.dispatch('increment')
```
169. Can you dispatch an action using payload or object style?
Yes, actions support both payload and object style format similar to mutations.
```javascript
// dispatch with a payload
store.dispatch('incrementAsync', {
amount: 10
})
// dispatch with an object
store.dispatch({
type: 'incrementAsync',
amount: 10
})
```
170. Can I use styled components in vuejs?
Styled components is basically used for ReactJS applications. If you want to use for VueJS applications, there is vuejs styled components library available under styled component library. VueJS Styled component is a javascript library for stying vuejs applications.
171. How do you dispatch actions in components?
You can dispatch actions in components with **this.$store.dispatch('action name')**, or use the **mapActions** helper which maps component methods to store.dispatch calls.
For example, you can dispatch increment actions in counter component as below,
```javascript
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // map `this.increment()` to `this.$store.dispatch('increment')`
// `mapActions` also supports payloads:
'incrementBy' // map `this.incrementBy(amount)` to `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // map `this.add()` to `this.$store.dispatch('increment')`
})
}
}
```
172. How do you compose actions?
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,
```javascript
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,
```javascript
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())
}
}
```
173. What are modules in vuex?
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,
```javascript
const moduleOne = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleTwo = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const store = new Vuex.Store({
modules: {
one: moduleOne,
two: moduleTwo
}
})
store.state.one // -> `moduleOne's state
store.state.one // -> `moduleTwo's state
```
174. What is module local state?
When you use modules the local state will be available to mutations, getters and actions in different ways.
1. Both mutations and getters will receive module local state as first argument.
```javascript
const moduleOne = {
state: { count: 0 },
mutations: {
increment (state) {
state.count++; // Here state refers local module state
}
},
getters: {
average (state) {
return state.count / 2
}
}
}
```
2. In actions, local state will be available as first argument.
```javascript
const moduleOne = {
actions: {
incrementConditional ({ state, commit, rootState }) {
if (state.count < rootState.count) {
commit('increment')
}
}
}
}
```
175. What is namespacing in vuex?
176. What is the default namespace behavior in vuex?
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.
177. When do you reuse modules?
Sometime you may need to create multiple instances of a module. For example, it is needed in the below cases,
1. If multiple stores that use the same module
2. Register the same module multiple times in the same store.
In those cases, you need to assign to a variable and export it for reusability,
```javascript
const MyReusableModule = {
// state
// mutations, actions, getters...
}
```
178. What are the principles enforced by vuex?
Vuex enforces below high-level principles,
1. The Application-level state need to be centralized in the store
2. The state should be mutated by committing mutations only(i.e, for synchronous transactions)
3. The actions should be used for asynchronous transactions.
179. Can I perform mutations directly in strict mode?
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
```javascript
<input v-model="stateObject.message">
```
In this case, you need to bind the <input>'s value. It can be resolved using value attribute as below,
```javascript
<input :value="username" @input="updateProfile">
computed: {
...mapState({
message: state => state.user.username
})
},
methods: {
updateProfile (e) {
this.$store.commit('updateProfile', e.target.value)
}
},
mutations: {
updateProfile (state, username) {
state.user.username = username
}
}
```
180. How to use model directive with two way computed property?
You can still use model directive using two-way computed property with a setter.
```javascript
<input v-model="username">
computed: {
message: {
get () {
return this.$store.state.user.username
},
set (value) {
this.$store.commit('updateProfile', value)
}
}
}
mutations: {
updateProfile (state, username) {
state.user.username = username
}
}
```
181. What is Vue CLI?
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,
```javascript
npm install -g @vue/cli
# OR
yarn global add @vue/cli
```
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).
182. What are the features provided by Vue CLI?
VueCLI provides below major features,
1. Interactive project scaffolding via @vue/cli
2. A rich collection of official plugins integrating the best tools in the frontend ecosystem.
3. A full graphical user interface to create and manage Vue.js projects.
4. Zero config rapid prototyping via combination of @vue/cli and @vue/cli-service-global
5. A runtime dependency (@vue/cli-service) built on top of webpack and extensible via plugins
183. What is instant prototyping?
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.
```javascript
npm install -g @vue/cli-service-global
# or
yarn global add @vue/cli-service-global
```
You can also provide entry component for `vue serve` and target file for `vue build` using below commands
```javascript
vue serve MyComponent.vue
vue build MyComponent.vue
```
184. How do you create project using vue CLI?
You can create project using `vue create` command
```javascript
vue create my-app
```
You can either choose the default preset or select "Manually select features" to pick the features you need.
The default preset prompt would be as below,
<img src="https://github.com/sudheerj/vuejs-interview-questions/blob/master/images/cli-default-presets.png" width="400" height="500">
and the manual select features would be as below,
<img src="https://github.com/sudheerj/vuejs-interview-questions/blob/master/images/cli-manual-features.png" width="400" height="500">
185. How do you create project using GUI?
You can also create and manage projects using a graphical interface with the `vue ui` command. Once you apply this command, it opens a browser window with a GUI that guides you through the project creation process.
<img src="https://github.com/sudheerj/vuejs-interview-questions/blob/master/images/cli-gui.png" width="400" height="500">
186. What are plugins in vue CLI?
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.
187. How do you install plugins in an existing Vue CLI project?
You can install a plugin into an already created project with the `vue add` command.
```javascript
vue add @vue/eslint
(OR)
vue add @vue/cli-plugin-eslint
```
You can also add options for plugin
```javascript
vue add @vue/eslint --config airbnb --lintOn save
```
If a plugin is already installed, you can skip the installation and only invoke its generator with the `vue invoke` command.
188. How to access local plugins in a project?
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
```javascript
{
"vuePlugins": {
"service": ["my-service.js"]
}
}
```
189. How do you create UI plugins kind of behavior?
You can also add files that will behave like UI plugins with the `vuePlugins.ui` option
```javascript
{
"vuePlugins": {
"ui": ["my-ui.js"]
}
}
```
190. What are presets?
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.
For example, the generated JSON object(or preset) would be as below
```javascript
{
"useConfigFiles": true,
"router": true,
"vuex": true,
"cssPreprocessor": "sass",
"plugins": {
"@vue/cli-plugin-babel": {},
"@vue/cli-plugin-eslint": {
"config": "airbnb",
"lintOn": ["save", "commit"]
}
}
}
```
Comments
Post a Comment
please do not enter any spam link in the comment box