Interpolation means putting or rendering your data which is possible very easily using Vue’s double-mustache syntax.
By using double-mustache syntax you can render your data:
<span>My name is: {{ myName }}</span>
Interpolations can contain simple expressions in Vue.
You can also use JavaScript expressions inside double-mustaches:
<span>I'm {{ myAge + 5 }} years old!</span>
You can also use methods to manipulate your data and return an string or integer to be rendered:
<span>My pets' names are {{ myPets.join(", ") }}</span>
You can also use ternary operator to have a simple conditional rendering:
<span>I'm a {{ myAge > 50 ? 'kinda old' : 'young' }}!</span>
Note:
<!--THIS IS WRONG-->
{{ let msg = 'Hello World!'; }}
<!--THIS IS WRONG-->
{{ if(true) { return 'Yes!' } }}
If you don’t want to escape your data and render it as real HTML use the v-html
directive:
<span v-html="myHTMLData"></span>
Warning: Rendering HTML can be risky since it can cause into XSS attacks on your website.
Binding means using your data inside your tag’s attributes.
Something wrong that new Vue developers try to do is putting a data into a attribute like this:
<span class="{{ myClass }}"></span>
But this is wrong and you actually have to bind it:
<span v-bind:class="myClass"></span>
There is a shorter way of binding which is by omitting v-bind
directive, like below:
<span :class="myClass"></span>
So what if you want to combine some string with your data when binding? Well use put your string inside of quotes and concat it as usual:
<span :class="myClass + 'test'"></span>
This can really be useful by using it inside hyperlinks:
<a :href="baseURL + '/post/' + postId">Read more</a>
The example above is a good example of a link to the post including the base URL and the post
suffix and then the post id.
You can use bindings to conditionally do something.
For the attributes which don’t have a value like disabled
or required
if your bound data return true the attribute will be added and if returns false the attribute won’t be added to the element.
<button :disabled="true"></button>
You can also use expressions which return boolean:
<button :disabled="password.length < 6"></button>
You can use an object inside the class attribute in order to bind the specified class if the condition is met:
<div :class="{green: true, red: false}"></div>
In the example above green
class will be added to our div
but not red.
You can use comparison and logical operators as well:
<div :class="{green: 5 > 1, red: false && 9 < 16}"></div>
By using the v-model
directive you can create a two-way data binding. Which means the user can change the data using an input and see the result simultaneously if needed.
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
let app = new Vue({
el: '#app',
data: {
message: ''
}
});
The v-model
directive can work on almost every input type.
Events are called when a specific action is performed on an element.
Events are declared with v-on
directive.
<div id="app">
<button v-on:click="callMyfunction"></button>
</div>
let app = new Vue({
el: '#app',
methods: {
callMyfunction() {
alert('This is it!');
}
}
});
When a click is performed on this button it will call the callMyFunction
method.
You can use anonymous functions as well:
<button v-on:click="() => alert('Hello my friend')"></button>
There is shorthand for events as well:
<button @click="() => alert('Hello my friend')"></button>
Imagine when you want to have an attributes name evaluated. Well this is possible by doing like below:
<div v-bind:[myAttribute]="myData"></div>
You can also have an events name dynamically attached:
<div v-on:[myEvent]="doSomething"></div>
There is also a way of binding dynamic arguments by using an object and JavaScript’s native dynamic key syntax, like below:
<button v-on="{[myAttr]: true}">Click on me if you can</button>
let app = new Vue({
el: '#app',
data: {
myAttr: 'disabled'
}
});
This can be used on events as well:
<button v-on="{[myEvent]: function() { alert("Hello world!") }}">Hi</button>
let app = new Vue({
el: '#app',
data: {
myEvent: 'click'
}
});
Computed properties are a way of cleaning your code and use them instead of expressions inside of your double-mustaches or other places.
Imagine you have the code below:
<p>
The best programming languages are: {{ programmingLanguages }}<br>
But the worst are: {{ programmingLanguages.split(', ').reverse().join(', ') }}
</p>
Instead you can define a computed property like below and use it instead of worst programming languages:
<p>
The best programming languages are: {{ programmingLanguages }}<br>
But the worst are: {{ worstProgrammingLanguages }}
</p>
let app = new Vue({
el: '#app',
data: {
programmingLangauges: 'JavaScript, C#, PHP, Python, LALALA, HOHOHO'
}
computed: {
worstProgrammingLanguages() {
return this.programmingLangauges.split(', ').reverse().join(', ');
}
}
});
The order is not real and I’m not judging any programming language. It is just for demonstration.
Computed properties are getters which means they only return something and have no role in setting the data.
You can change this behaviour and set both set
and get
methods for a data, like below:
let app = new Vue({
el: '#app',
data: {
myFirstName: 'Adnan',
myLastName: 'Babakan'
}
computed: {
myFullName: {
get(): {
return this.myFirstName + ' ' + this.myLastName;
},
set(v): {
let parts = v.split(' ');
this.myFirstName = parts[0];
this.myLastName = parts[1];
}
}
}
});
The code above will split the string by space and set the first part as first name and the second part as the last name when you are trying to set a data to myFullName
but when getting the data it will concat first name and last name.
A more generic way of knowing when a data changes is by using watchers.
let app = new Vue({
el: '#app',
data: {
myAge: 19
}
watch: {
myAge(v) {
console.log('I\'m now ' + v);
}
}
});
Note: Watchers don’t manipulate data unless you want.
A conditional rendering is used when you want to display parts of your UI according to some condition(s).
<span v-if="isUserLoggedIn">Hello user</span>
<span v-else>Hi guest!</span>
Your conditions can have an ‘else-if’ as well:
<span v-if="favoriteColor === 'red'">Red like apple</span>
<span v-if="favoriteColor === 'blue'>Blue like sky</span>
<span v-else>Hmmm....</span>
Vue is smart and will only replace the parts that are different.
For example if you have a an input for logging in by email or username switching between two parts by condition won’t erase and re-render that input and user’s inputted value won’t be deleted:
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address">
</template>
Though, by using key
you can tell Vue that these fields are completely different and you should re-render them:
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>
By using v-show
you render the element but hide it (setting the display
property to none
) like this:
<span v-show="true">Hello there!</span>
Note: v-show
doesn’t support the <template>
element, nor does it work with v-else
.
Note: v-if
is lazy which means the block with false condition at the beginning won’t be rendered, on the other hand v-show
actually renders but hides the block.
Rendering a list of data is almost like looping in other programming languages.
Often it happens you want to iterate around an array and render them.
This is possible by using v-for
directive:
<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
});
You can also pass a second argument to access the index of current item:
<ul id="example-2">
<li v-for="(item, index) in items">
{{ index }} - {{ item.message }}
</li>
</ul>
var example2 = new Vue({
el: '#example-2',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
});
Object rendering is no harder than array rendering:
<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ value }}
</li>
</ul>
new Vue({
el: '#v-for-object',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
});
You can also have access to the name of the property using the second argument:
<ul id="v-for-object" class="demo">
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>
</ul>
new Vue({
el: '#v-for-object',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
});
Accessing to the index is also available when iterating around an object:
<ul id="v-for-object" class="demo">
<div v-for="(value, name, index) in object">
{{ index }}. {{ name }}: {{ value }}
</div>
</ul>
new Vue({
el: '#v-for-object',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
});
Iterating in a range of numbers is also pretty easy:
<div>
<span v-for="n in 10">{{ n }} </span>
</div>
Lifecycle hooks are simply some functions that run on a specific event/time during your Vue component.
Called synchronously immediately after the instance has been initialized, before data observation and event/watcher setup.
Sample:
let app = new Vue({
beforeCreate() {
console.log('I\'m not created yet');
}
});
Called synchronously after the instance is created. At this stage, the instance has finished processing the options which means the following have been set up: data observation, computed properties, methods, watch/event callbacks. However, the mounting phase has not been started, and the $el property will not be available yet.
Sample:
let app = new Vue({
created() {
console.log('I\'m created');
}
});
Called right before the mounting begins: the render function is about to be called for the first time.
Note: This hook is not called during server-side rendering.
Sample:
let app = new Vue({
beforeMount() {
console.log('Let\'s begin!');
}
});
Called after the instance has been mounted, where el
is replaced by the newly created vm.$el
. If the root instance is mounted to an in-document element, vm.$el
will also be in-document when mounted is called.
Note: This hook is not called during server-side rendering.
Sample:
let app = new Vue({
mounted() {
console.log('I\'m ready!');
}
});
Called when data changes, before the DOM is patched. This is a good place to access the existing DOM before an update, e.g. to remove manually added event listeners.
Note: This hook is not called during server-side rendering, because only the initial render is performed server-side.
Sample:
let app = new Vue({
beforeUpdate() {
console.log('Your DOM is about to change. Be careful!');
}
});
Called after a data change causes the virtual DOM to be re-rendered and patched.
The component’s DOM will have been updated when this hook is called, so you can perform DOM-dependent operations here. However, in most cases you should avoid changing state inside the hook. To react to state changes, it’s usually better to use a computed property or watcher instead.
Note: This hook is not called during server-side rendering.
Sample:
let app = new Vue({
updated() {
console.log('Hello new DOM!');
}
});
Called right before a Vue instance is destroyed. At this stage the instance is still fully functional.
Note: This hook is not called during server-side rendering.
Sample:
let app = new Vue({
beforeDestroy() {
console.log('Well it\'s the time I think...');
}
});
Called after a Vue instance has been destroyed. When this hook is called, all directives of the Vue instance have been unbound, all event listeners have been removed, and all child Vue instances have also been destroyed.
Note: This hook is not called during server-side rendering.
Sample:
let app = new Vue({
destroyed() {
console.log('BOOOOM!');
}
});
Events are called when a specific action is performed on an element.
In the previous Vue cheat sheet I described them really basically. Here I will describe more aspects of events.
Keep in mind that @
is a short hand of v-on:
.
By using v-on
you can access all JavaScript events. These are some samples:
<button @click="() => alert('Hello')">Do it</button>
<button @mouseover="() => alert('Hello')">Do it</button>
<button @mouseout="() => alert('Hello')">Do it</button>
<button @contextmenu="() => alert('Hello')">Do it</button>
You can also submit
event on forms:
<form @submit="() => alert('This form is submitted')">
<input type="text" />
</form>
Event modifiers are used to alter some behaviour of the event or have a more control on it.
Modifiers are added following by a .
after the event.
So this is the structure v-on:event.modifier
or @event.modifier
.
Modifiers can also be chained to be performed at the respective order, like: @event.modifier-one.modifier-two
<!-- 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>
<!-- 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>
<!-- the click event will be triggered at most once -->
<a v-on:click.once="doThis"></a>
<!-- only trigger handler if event.target is the element itself -->
<!-- i.e. not from a child element -->
<div v-on:click.self="doThat">...</div>
<!-- the scroll event's default behavior (scrolling) will happen -->
<!-- immediately, instead of waiting for `onScroll` to complete -->
<!-- in case it contains `event.preventDefault()` -->
<div v-on:scroll.passive="onScroll">...</div>
Listening to keyboards event is easy but detecting which key is pressed would need the key code. Vue has some modifiers in order to listen to a specific key when using keyboard events.
These modifiers can be used with any key events such as keydown
or keyup
<input @keydown.enter="() => alert('Hey there!')"></input>
<input @keydown.tab="() => alert('Hey there!')"></input>
<input @keydown.delete="() => alert('Hey there!')"></input>
<input @keydown.esc="() => alert('Hey there!')"></input>
<input @keydown.space="() => alert('Hey there!')"></input>
<input @keydown.up="() => alert('Hey there!')"></input>
<input @keydown.down="() => alert('Hey there!')"></input>
<input @keydown.right="() => alert('Hey there!')"></input>
<input @keydown.left="() => alert('Hey there!')"></input>
<input @keydown.home="() => alert('Hey there!')"></input>
<input @keydown.end="() => alert('Hey there!')"></input>
<input @keydown.ctrl="() => alert('Hey there!')"></input>
<input @keydown.alt="() => alert('Hey there!')"></input>
<input @keydown.shift="() => alert('Hey there!')"></input>
<input @keydown.meta="() => alert('Hey there!')"></input>
If Vue doesn’t provide an alias for the key you want, you can use its key code as below:
<input @keydown.49="() => alert('Hey there!')"></input>
Key code 49 is for the number 1 on top of keyboard. (Not the number pad)
You can chain key modifiers in order to create a combined structure, like this:
<input @keydown.ctrl.shift="() => alert('Hey there!')"></input>
Using exact
will allow you to capture the button you need and nothing else can be combined.
By using the code below if you hold shift and press ctrl it will respond normally:
<input @keydown.ctrl="() => alert('Hey there!')"></input>
But by using the code below the only key which should be pressed is ctrl:
<input @keydown.exact.ctrl="() => alert('Hey there!')"></input>
Components are reusable Vue instances used to simplify your code and split your code in a better manner.
This is a Vue component:
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
As you can it has its template embedded in it as well as the data it uses and can be used in other Vue components like this:
<div id="components-demo">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
This will render three different buttons which has nothing to do with each other. Each of them will function separately and each has its own count
data.
Important: When defining a component the data
should be a function returning an object if not each instance won’t have its own data and it will be shared.
A single file component (or SFC) is a component which is in one file (holy crap! really?).
It has more clean syntax and it is as below:
<template>
<div>
</div>
</template>
<script>
export default {
};
</script>
<style scoped>
</style>
By registering components you can use them inside your templates.
By doing this method your component will be available in every Vue instance (in case you have more than one):
import Vue from 'vue';
Vue.component('my-component', require('/path/to/your/component'));
By doing this the component will only be available in the specified Vue instance:
import Vue from 'vue';
const myComponent = require('/path/to/your/component');
let app = new Vue({
components: {
myComponent
}
});
This method is pretty cool since it will not bundle your component with your main entry file thus your website will be loaded faster and only the needed components will be required.
import Vue from 'vue';
const myComponent = () => import('./components/myComponent ');
let app = new Vue({
components: {
myComponent
}
});
Bonus Tip: This will extract your components named by numbers from 0 and so on. If you are using webpack you can use a magic comment in order to change your components’ file names like below:
import Vue from 'vue';
const myComponent = () => import(/* webpackChunkName: "myComponent" */ './components/myComponent ');
let app = new Vue({
components: {
myComponent
}
});
Components can have props which act literally like HTML tags’ attributes.
By having a component like this:
Vue.component('blog-post', {
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
You can use it like this:
<blog-post post-title="hello!"></blog-post>
Note: When defining props it is better to define it using camelCase but when using it, use it as kebab-case. Although it is possible to use kebab-case defined props as camelCase in Vue but IDEs might get confused about it.
Your single file components can also have props:
<template>
<div>
</div>
</template>
<script>
export default {
props: ['myProp'];
};
</script>
<style scoped>
</style>
Slots are used to embed other elements or components inside a component.
A simple slot is an unnamed slot and is used like below in a template:
<a :href="url" class="strange-class"><slot></slot></a>
After defining the template above assuming that the component name is navigation-link
and url
is a prop, you can use it as below:
<navigation-link url="/my-profile">Your profile</navigation-link>
As you see we have a text inside of our components and that is going to be inserted instead of <slot></slot>
.
Named slots are a little different than an unnamed one.
By defining a component called base-layout
like this:
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
You can use it like this:
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
The templates with v-slot:slot-name
will be placed in their respective slots defined in the component and other ones will be placed in <slot></slot>
which is unnamed.
Note: An unnamed slot is actually accessible with the name default
like below:
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<template v-slot:default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
A slot can have access to its parents prop in order to avoid such a thing (if needed) you can define a slot prop like below:
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
And when using:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
This slot will use the user
available in the component and not the one available in the parent component.
To be simple, mixins are just parts of your component stored in a separate file son it can be used again in other components.
A mixin can look like this:
// define a mixin object
export const myMixin = {
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('Hello from mixin!')
}
}
}
As you see this has a created
hook and a method called hello
so now this mixing can be used in a component, like below:
<script>
import { myMixin } from './myMixin.js';
export default {
mixins: [myMixin]
}
</script>
So this will function as if you wrote those hooks and methods in this component.
Well in case of any conflicts between a components self-assigned properties or methods and the mixin’s, the component it self will be in priority, see this:
let 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" }
}
})
The way Vue handles overwriting can be changed but we will cover that in the other cheat sheet.
A global mixin is no different than a normal mixin rather than its affection scope which will include all Vue instances created.
import Vue from 'vue';
Vue.mixin({
methods: {
sayHi() {
alert('Salam!');
}
}
});
const app = new Vue({
el: '#app'
});
The method sayHi
will be available for every component and Vue instance in the code above.
As you know directives are the way Vue handles DOM. For instance v-model
or v-show
are directives.
In order to define a directive you can do as below:
<script>
export default {
directives: {
focus: {
inserted: function (el) {
el.focus()
}
}
}
}
</script>
The focus
directive will be available as v-focus
and can be used like this:
<input v-focus />
So the input will be focused as soon as the component renders.
In order for your custom directives to be available throughout your Vue instance and globally you can define it like below:
Vue.directive('focus', {
inserted: function (el) {
el.focus()
}
})
Filters are simply used to alter a value and return it.
They can be used in both mustaches and v-bind directive.
To define a filter in a component you can de as below:
<script>
export default {
filters: {
capitalize: function(value) {
if (!value) return '';
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1);
}
}
};
</script>
Then the capitalize filter can be used as below:
<span>{{ msg | capitalize }}</span>
Or in a v-bind as below:
<a v-bind:href="url | capitalize">My capitalized link!</a>
Global filters are no different than normal filters but they will be defined once and can be used in every Vue instance or component.
import Vue from 'vue';
Vue.filter('focus', {
capitalize: function(value) {
if (!value) return '';
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1);
}
});
Vue router is used to design a routing system on the client-side using Vue.
In order to start using the router you need to install it. These are steps:
It is recommended to install it using npm:
npm i vue-router --save
It can be installed by including the file as well:
<script src="/path/to/vue.js"></script>
<script src="/path/to/vue-router.js"></script>
After installing it, it is time to tell Vue to use the router. To do so you can do as below:
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
Your components which are bound to routes should be rendered somewhere in your page. This be declared as below:
<div id="app">
<div>
Hello World!
</div>
<router-view></router-view>
</div>
Each route will have its own unique component bound. You can define your routes as below:
const routes = [
{ path: '/foo', component: require('./path/to/foo/component') },
{ path: '/bar', component: require('./path/to/bar/component') }
];
const router = new VueRouter({
routes // short for `routes: routes`
});
If you want yo push the routes to history of user’s browser you should activate the history mode as below:
const router = new VueRouter({
mode: 'history',
routes // short for `routes: routes`
});
And then attach your routes to your view instance:
const app = new Vue({
router
}).$mount('#app');
Note: If you are using the history mode, in order to redirect all your requests to your index.html
file so Vue can take care of rest of it you should configure your web server. Unless, by refreshing the browser on a page, it will return 404 since that page actually doesn’t exist on the server.
Router links are special since they don’t refresh the page but only getting the component that is needed (and push the URL to the history in history mode) so it seems like a new page.
Instead of a hyper-link (a
tag) you should use router-link
as below:
<router-link to="/foo">Go to foo</router-link>
Vue router is beyond just few simple routes and it provides some great ways of handling routes.
Dynamic routes are used to match a series of routes with some params to be acquired.
A dynamic route is defined just like a normal route but with a colon at the beginning of the dynamic segment(s):
const routes = [
{ path: '/user/:username', component: require('./path/to/user/component') },
];
Now by the route above all of links such as /user/adnanbabakan
, /user/dev/
or /user/vue
is valid.
The username
can be accessed in the route component as below:
<div>This is {{ $route.params.username }}'s profile!</a>
Considering the example above. If the user moves from /user/adnanbabakan
to /user/dev
Vue won’t destroy the previous instance since it is already going to be the same component rendered again, thus the lifecycle hooks won’t be called in order to react to any params changes you can watch the $route
object like
this:
<script>
export default {
watch: {
$route(to, from) {
}
}
};
</script>
Every website needs a great 404 route. In a Vue Router we can define an asterisk *
route at the end so it catches everything that is not defined.
Warning: The asterisk route should be defined at the end and after any other route. Unless it will match everything else and ruin your routing system.
In order to do so look at the code below:
const routes = [
// ... Any other routes ...
{ path: '*', component: require('./path/to/404/component') },
];
Asterisks can be used to match another kind of dynamic routes. A dynamic route can only match the dynamic segments between two slashes /
but asterisk can do beyond that.
Look at the route below:
const routes = [
{ path: '/user-*', component: require('./path/to/user/component') },
];
So by the route above routes such as /user-adnan
and /user-dev
can be rendered.
By using the route below the $route.params
will have a property called pathMatch
which will include the part that matched the asterisk.
For example $route.params.pathMatch
in the page /user-adnan
will return adnan
.
Named routes are used to access long route pattern with their shorter name.
Imagine you have a pattern like this:
const routes = [
{
path: '/user/profile/setting/',
component: require('./path/to/user/component')
}
];
You can define a name for it like this:
const routes = [
{
path: '/user/profile/setting/',
component: require('./path/to/user/component'),
name: 'settings'
}
];
Now your links can be like this:
<router-link :to='{name: "settings"}'>
Profile settings
</router-link>
Instead of this:
<router-link to="/user/profile/setting/">
Profile settings
</router-link>
Note: When passing an object to to
attribute you should bind it.
Some routes might have params as we had some examples above. You can define a name for them as well.
For example for the route below:
const routes = [
{
path: '/posts/from/:username',
component: require('./path/to/posts/component'),
}
];
You can have this:
const routes = [
{
path: '/posts/from/:username',
component: require('./path/to/posts/component'),
name: 'posts'
}
];
And in order to create a link for this you can have the code below:
<router-link :to='{name: "posts", params: {username: "adnanbabakan"}}'>
Profile settings
</router-link>
As you read before in this cheat sheet you can create a router link using <router-link></router-link>
but what if you needed to redirect user programmatically? Well you can do that by this code:
router.push('/foo');
This code will redirect your user to /foo
. This is especially used in a condition or other situations like redirection after login.
You can also use router.push()
for named routes like this:
router.push({name: 'myRoute'});
As well, router.push()
can be used for redirecting with params, like this:
router.push({name: 'myRoute', params: {paramOne: 'Hello', paramTwo: 'Salam'}});
Routes can be defined to be redirected to each other. Like this:
const routes = [
{
path: '/foo',
redirect: '/bar'
}
];
A route can also be redirected to a named route, like this:
const routes = [
{
path: '/foo',
redirect: { name: 'myRoute' }
}
];
A route can be redirected using a function to evaluate the destination, like this:
const routes = [
{
path: '/foo',
redirect: to => {
// the function receives the target route as the argument
// return redirect path/location here.
}
}
];
If the target route has a param it can be passed to the destination as well:
const routes = [
{
path: '/profile/:username',
redirect: '/user/:username'
}
];
A route alias means a route can have multiple addressed to be accessed from.
For example:
const routes = [
{
path: '/foo',
alias: '/bar'
}
];
Now the route /foo
can be accessed as /bar/
as well.
A route can have multiple aliases as well:
const routes = [
{
path: '/foo',
alias: ['/bar', '/baz']
}
];
In some cases, it is necessary to force Vue in order to re-render your component since it won’t track some changes.
There are some ways of doing so, such as using the v-if
hack, but the correct way is by using forceUpdate
method:
export default {
methods: {
forceUpdateMyComponent() {
this.$forceUpdate()
},
},
}
Keep that in mind that $
is necessary to use this method in your Vue instance.
And you better be notified that this won’t update any computed property but only force the view of your component to be re-rendered.
Sometimes you might need to watch some nested data you can do this using dot notation:
export default {
data() {
return {
myInfo: {
firstName: 'Adnan'
}
}
},
watch: {
'myInfo.firstName'() {
console.log('Here');
}
}
}
The code above is when you know which property inside your object to watch!
But what if you want to watch your whole object and also its values?
export default {
data() {
return {
myFruits: {apple: 'red', banana: 'yellow'},
}
},
methods: {
changeIt() {
this.myFruits.apple = 'green'
},
},
watch: {
myFruits: {
deep: true,
handler() {
console.log('Fruits updated!')
},
},
},
}
You can define your watch not as a function immediately but as an object, then by using the deep
key and the value true
watch your object and put what you want to be fired when the data got changed inside a function called handler
.
As you know v-model
is used to make a two-way binding with an input element/component and a data property.
If you are making a custom component and want it to support v-model
you can emit the input
keyword and in order to receive what is passed to your component initially with the v-model
you simply need to get a prop called value
.
For an easier comprehension check the code below:
<template>
<div>
<label>My custom test input: <input :value="inputValue" @input="emitTheData" /></label>
</div>
</template>
<script>
export default {
props: ['value'],
data() {
return {
inputValue: value
}
},
methods: {
emitTheData() {
this.$emit('input', this.inputValue)
}
}
}
</script>
This simple component will bind the data passed to it in two directions.
Note: As you can see, I assigned the prop called value
to a data called inputValue
and used it in my input, you might think that I could pass the prop directly to my input but as Vue suggests it is better not to alter props directly.
Imagine having a component with no watch or computed property and no methods! You would only use it to render some other components as one with some props. If it is so then why waste Vue’s time when there are no lifecycle methods?
A functional component can be defined as below:
<template functional>
<div>{{ props.foo }}</div>
</template>
Note: Keep in mind that there is no this
context in these components since it is a functional component!
#vuejs #javascript #webdev