Professional Documents
Culture Documents
2
:key
3
:key v-for
4
v-if
v-if
template v-if
<template>
<my-component v-if="renderComponent" />
</template>
script nextTick
5
<script>
export default {
data() {
return {
renderComponent: true,
};
},
methods: {
forceRerender() {
// Remove my-component from the DOM
this.renderComponent = false;
this.$nextTick(() => {
// Add the component back in
this.renderComponent = true;
});
}
}
};
</script>
forceRerender renderComponent
false
my-component v-if
false
renderComponent true
6
v-if true
my-component
renderComponent
my-component
created mounted
7
nextTick
forceRerender() {
// Remove my-component from the DOM
this.renderComponent = false;
forceUpdate
8
forceUpdate
9
// Globally
import Vue from 'vue';
Vue.forceUpdate();
forceUpdate
key
10
key
created mounted
11
key
const people = [
{ name: 'Evan', age: 34 },
{ name: 'Sarah', age: 98 },
{ name: 'James', age: 45 },
];
<ul>
<li v-for="(person, index) in people" :key="index">
{{ person.name }} - {{ index }}
</li>
</ul>
// Outputs
Evan - 0
Sarah - 1
James - 2
Evan - 0
James - 1
12
const people = [
{ id: 'this-is-an-id', name: 'Evan', age: 34 },
{ id: 'unique-id', name: 'Sarah', age: 98 },
{ id: 'another-unique-id', name: 'James', age: 45 },
];
<ul>
<li v-for="person in people" :key="person.id">
{{ person.name }} - {{ person.id }}
</li>
</ul>
13
<template>
<component-to-re-render :key="componentKey" />
</template>
14
export default {
data() {
return {
componentKey: 0,
};
},
methods: {
forceRerender() {
this.componentKey += 1;
}
}
}
forceRerender componentKey
15
16
Data
data
data
17
<template>
<template>
<my-component cool-prop="hello world"></my-component>
</template>
18
cool-prop
"hello world"
my-component
data
count data
19
<template>
<div>
{{ count }}
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
export default {
name: 'Counter',
data() {
return {
// Initialized to zero to begin
count: 0,
}
},
methods: {
increment() {
this.count += 1;
},
decrement() {
this.count -= 1;
}
}
}
20
setState
data
methods: {
increment() {
this.count += 1;
},
decrement() {
this.count -= 1;
}
}
21
count
export default {
props: ['propA', 'propB'],
data() {
return {
dataA: 'hello',
dataB: 'world',
};
},
};
22
this.props.propA this.data.dataA props data
this.propA this.dataA
methods: {
coolMethod() {
// Access a prop
console.log(this.propA);
props
data
23
export default {
props: ['secret'],
data() {
return {
secret: '1234',
};
},
methods: {
printSecret() {
// Which one do we want?
console.log(this.secret);
}
}
};
data
ContactInfo
24
// ContactInfo
<template>
<div class="container">
<div class="row">
Email: {{ emailAddress }}
Twitter: {{ twitterHandle }}
Instagram: {{ instagram }}
</div>
</div>
</template>
export default {
name: 'ContactInfo',
props: ['emailAddress', 'twitterHandle', 'instagram'],
};
ContactInfo emailAddress
twitterHandle instagram
ProfilePage
// ProfilePage
<template>
<div class="profile-page">
<div class="avatar">
<img src="user.profilePicture" />
{{ user.name }}
</div>
</div>
</template>
25
export default {
name: 'ProfilePage',
data() {
return {
// In a real app we would get this data from a server
user: {
name: 'John Smith',
profilePicture: './profile-pic.jpg',
emailAddress: 'john@smith.com',
twitterHandle: 'johnsmith',
instagram: 'johnsmith345',
},
}
}
};
ProfilePage
ProfilePage
ContactInfo
ContactInfo ProfilePage
26
// Import the component
import ContactInfo from './ContactInfo.vue';
export default {
name: 'ProfilePage',
// Add it as a dependency
components: {
ContactInfo,
},
data() {
return {
user: {
name: 'John Smith',
profilePicture: './profile-pic.jpg',
emailAddress: 'john@smith.com',
twitterHandle: 'johnsmith',
instagram: 'johnsmith345',
},
}
}
};
<template>
27
// ProfilePage
<template>
<div class="profile-page">
<div class="avatar">
<img src="user.profilePicture" />
{{ user.name }}
</div>
</div>
</template>
ContactInfo
ContactInfo ProfilePage
ProfilePage ContactInfo
28
29
deep
watch
30
immediate handler
colour
export default {
name: 'ColourChange',
props: ['colour'],
watch: {
colour()
console.log('The colour has changed!');
}
}
}
31
computed
32
data
<template>
data
watch
33
const array = [1, 2, 3, 4];
// array = [1, 2, 3, 4]
array.push(5);
array.push(6);
array.push(7);
// array = [1, 2, 3, 4, 5, 6, 7]
array
array array
34
deep true
export default {
name: 'ColourChange',
props: {
colours: {
type: Array,
required: true,
},
},
watch: {
colours: {
// This will let Vue know to look inside the array
deep: true,
handler
35
MovieData
movie
36
export default {
name: 'MovieData',
props: {
movie: {
type: String,
required: true,
}
},
data() {
return {
movieData: {},
}
},
watch: {
// Whenever the movie prop changes, fetch new data
movie(movie) {
// Fetch data about the movie
fetch(`/${movie}`).then((data) => {
this.movieData = data;
});
}
}
}
movie
movie
37
immediate
watch: {
// Whenever the movie prop changes, fetch new data
movie: {
// Will fire as soon as the component is created
immediate: true,
handler(movie) {
// Fetch data about the movie
fetch(`/${movie}`).then((data) => {
this.movieData = data;
});
}
}
}
handler
immediate
deep
38
handler
handler
immediate deep
watch: {
movie: {
handler(movie) {
// Fetch data about the movie
fetch(`/${movie}`).then((data) => {
this.movieData = data;
});
}
}
}
39
watch: {
movie(movie) {
// Fetch data about the movie
fetch(`/${movie}`).then((data) => {
this.movieData = data;
});
}
}
String
movie actor
40
watch: {
// Whenever the movie prop changes, fetch new data
movie {
handler: 'fetchData'
},
// Whenever the actor changes, we'll call the same method
actor: {
handler: 'fetchData',
}
},
methods: {
// Fetch data about the movie
fetchData() {
fetch(`/${this.movie}/${this.actor}`).then((data) => {
this.movieData = data;
});
}
}
41
42
43
colour
export default {
name: 'ColourChange',
props: ['colour'],
watch: {
colour()
console.log('The colour has changed!');
}
}
}
data()
localstorage
44
firstName
lastName fullName
export default {
name: 'FullName',
props: ['firstName', 'lastName'],
computed: {
fullName() {
return this.firstName + ' ' + this.lastName;
}
}
}
firstName lastName
fullName
45
export default {
name: 'FullName',
props: ['firstName', 'lastName'],
data() {
return {
fullName: this.firstName + ' ' + this.lastName,
};
},
watched: {
firstName() {
this.fullName = this.firstName + ' ' + this.lastName;
},
lastName() {
this.fullName = this.firstName + ' ' + this.lastName;
}
}
}
data()
46
47
MovieData
movie
export default {
name: 'MovieData',
props: {
movie: {
type: String,
required: true,
}
},
data() {
return {
movieData: {},
}
},
watch: {
// Whenever the movie prop changes, fetch new data
movie(movie) {
// Fetch data about the movie
fetch(`/${movie}`).then((data) => {
this.movieData = data;
});
}
}
}
movie
48
watch
49
data.nested.really.deeply.importantValue
computed() {
importantValue() {
return this.data.nested.really.deeply.importantValue;
},
}
this.importantValue
50
51
52
53
54
this is undefined
fetch axios
lodash underscore
55
this
methods: {
regularFunction: function() {
// Do some stuff
}
}
56
methods: {
shorthandFunction() {
// Do some stuff
}
}
this
this
57
methods: {
arrowFunction: () => {
// Do some stuff
}
}
this
this
this
this
this
58
data() {
return {
text: 'This is a message',
};
},
methods: {
arrowFunction: () => {
console.log(this.text); // ERROR! this is undefined
}
}
this
computed: {
location: () => window.location,
}
59
fetch axios
// Fetching data
fetch('/getSomeData').then((data) => {
this.data = data;
});
// Functional methods
const array = [1, 2, 3, 4, 5];
const filtered = array.filter(number => number > 3);
const mapped = array.map(number => number * 2);
const reduced = array.reduce((prev, next) => prev + next);
60
this
this
this
this
61
data() {
return {
match: 'This is a message',
};
},
computed: {
filteredMessages(messages) {
console.log(this); // Our Vue component
return filteredMessages;
}
}
this.match
filteredMessages
axios
fetch
62
fetch axios
this
export default {
data() {
return {
dataFromServer: undefined,
};
},
methods: {
fetchData() {
fetch('/dataEndpoint')
.then(data => {
this.dataFromServer = data;
})
.catch(err => console.error(err));
}
}
};
63
.then(data => {
this.dataFromServer = data;
})
fetchData() this
this
this
dataFromServer
lodash
underscore
this is undefined
64
created() {
this.methodToDebounce = _.debounce(this.methodToDebounce, 500);
},
methods: {
methodToDebounce() {
// Do some things here
}
}
this.methodToDebounce()
65
window
this
this this
this
66
// This variable is in the window's scope
window.value = 'Bound to the window';
const object = {
// This variable is in the object's scope
value: 'Bound to the object',
arrowFunction: () => {
// The arrow function uses the window's scope for `this`
console.log(this.value); // 'Bound to the window'
},
regularFunction() {
// The regular function uses the object's scope for `this`
console.log(this.value); // 'Bound to the object'
}
};
this
this
67
68
69
v-model
70
71
export default {
props: {
movies: Array,
user: Object,
searchQuery: String,
}
}
export default {
props: {
movies: Array,
user: Object,
searchQuery: String,
},
methods: {
sortMovies() {
this.movies = this.movies.sort();
}
}
72
export default {
props: {
movies: Array,
user: Object,
searchQuery: String,
},
methods: {
sortMovies() {
this.movies = this.movies.sort();
},
search(query) {
this.searchQuery = query;
}
}
}
73
export default {
props: {
movies: Array,
user: Object,
searchQuery: String,
},
methods: {
sortMovies() {
this.movies = this.movies.sort();
},
search(query) {
this.searchQuery = query;
},
addToFavourites(movie) {
this.user.favourites.push(movie);
}
}
}
74
75
76
ReversedList
77
<template>
<ul>
<li v-for="item in list" />
</ul>
</template>
export default {
name: 'ReversedList',
props: {
list: {
type: Array,
required: true,
}
},
created() {
// Mutating the prop :(
this.list = this.list.reverse();
}
};
78
<template>
<ul>
<li v-for="item in reversedList" />
</ul>
</template>
export default {
name: 'ReversedList',
props: {
list: {
type: Array,
required: true,
}
},
computed: {
reversedList() {
return this.list.reverse();
}
}
};
reversedList
li
reversedList
list
79
<template>
<div>
<!-- Add in a button that toggles our `reversed` flag -->
<button @click="reversed = !reversed">Toggle</button>
<ul>
<li v-for="item in reversedList" />
</ul>
</div>
</template>
80
export default {
name: 'ReversedList',
props: {
list: {
type: Array,
required: true,
}
},
data() {
return {
// Define a reversed data property
reversed: false,
};
},
computed: {
reversedList() {
// Check if we need to reverse the list
if (this.reversed) {
return this.list.reverse();
} else {
// If not, return the plain list passed in
return this.list;
}
}
}
};
reversed
reversed
true false
81
reversedList
reversed
reversedList
reversed list
v-model
v-model
v-model
82
<template>
<input v-model="firstName" />
</template>
export default {
props: {
firstName: String,
}
}
v-model
83
84
85
86
prop prop
data
87
<template>
<div>
{{ messag }}
</div>
</template>
export default {
data() {
return {
message: "Hello, world!"
};
}
};
88
<!-- Template for the Page component -->
<template>
<ul>
<link-item url="google.com" text="Google" />
<link-item url="yahoo.com" text="Yahoo" />
<link-item url="facebook.com" text="Facebook" />
</ul>
</template>
89
// Clean up some code by using another component
const LinkItem = {
props: ['url', 'text'],
template: `
<li>
<a
:href="url"
target="_blank"
>
{{ text }}
</a>
</li>
`
};
<li>
LinkItem
Page
methods: {
forceHTTPS(url) {
// ...
}
}
90
forceHTTPS
LinkItem
const LinkItem = {
props: ['url', 'text'],
template: `
<li>
<a
- :href="url"
+ :href="forceHTTPS(url)"
target="_blank"
>
{{ text }}
</a>
</li>
`
};
forceHTTPS LinkItem
Page
91
const LinkItem = {
props: ['url', 'text'],
+ methods: {
+ forceHTTPS(url) {
+ // Do some stuff...
+ }
+ },
template: `
<li>
<a
:href="forceHTTPS(url)"
target="_blank"
>
{{ text }}
</a>
</li>
`
};
92
93
94
95
hover :hover
.item {
background: blue;
}
.item:hover {
background: green;
}
96
mouseenter mouseenter
mouseover mouseenter
mouseover
97
v-on
v-on:event @event
<template>
<div
@mouseover="hover = true"
@mouseleave="hover = false"
/>
</template>
98
export default {
data() {
return {
hover: false,
};
}
}
hover
<template>
<div>
<span
@mouseover="hover = true"
@mouseleave="hover = false"
>
Hover me to show the message!
</span>
<span v-if="hover">This is a secret message.</span>
</div>
</template>
99
export default {
data() {
return {
hover: false,
};
}
}
<template>
<div>
<span
@mouseover="hover = true"
@mouseleave="hover = false"
:class="{ active: hover }"
>
Hover me to change the background!
</span>
</div>
</template>
100
export default {
data() {
return {
hover: false,
};
}
}
.active {
background: green;
}
<template>
<span>
Hover me to change the background!
</span>
</template>
span:hover {
background: green;
}
101
mouseover mouseleave
.native
<template>
<my-custom-component
@mouseover.native="hover = true"
@mouseleave.native="hover = false"
/>
</template>
export default {
data() {
return {
hover: false,
};
}
}
102
.native
103
104
105
<template>
<ChildComponent :function="myFunction" />
</template>
export default {
methods: {
myFunction() {
// ...
}
}
};
106
107
// ChildComponent
export default {
created() {
this.$emit('created');
}
}
<template>
<ChildComponent @created="handleCreate" />
</template>
export default {
methods: {
handleCreate() {
console.log('Child has been created.');
}
}
};
108
109
<!-- Parent -->
<template>
<ChildComponent :method="parentMethod" />
</template>
// Parent
export default {
methods: {
parentMethod() {
// ...
}
}
}
110
// Child
export default {
props: {
method: { type: Function },
},
mounted() {
// Use the parent function directly here
this.method();
}
}
111
<!-- Parent -->
<template>
<ChildComponent :method="parentMethod" />
</template>
// Parent
export default {
methods: {
parentMethod(valueFromChild) {
// Do something with the value
console.log('From the child:', valueFromChild);
}
}
}
112
// Child
export default {
props: {
method: { type: Function },
},
data() {
return { value: 'I am the child.' };
},
mounted() {
// Pass a value to the parent through the function
this.method(this.value);
}
}
113
// Parent
export default {
methods: {
handleSendMessage(event, value) {
// Our event handler gets the event, as well as any
// arguments the child passes to the event
console.log('From the child:', value);
}
}
}
// Child
export default {
props: {
method: { type: Function },
},
data() {
return { value: 'I am the child.' };
},
mounted() {
// Instead of calling the method we emit an event
this.$emit('send-message', this.value);
}
}
114
115
116
:class="classname" classname
117
<template>
<span class="description">
This is how you add static classes in Vue.
</span>
</template>
v-bind
118
<template>
<span v-bind:class="'description'">
This is how you add static classes in Vue.
</span>
</template>
v-bind
v-bind
<template>
<span :class="'description'">
This is how you add static classes in Vue.
</span>
</template>
119
<template>
<span
class="description"
:class="theme"
>
This is how you add static classes in Vue.
</span>
</template>
export default {
data() {
return {
theme: 'blue-theme',
};
}
};
.blue-theme {
color: navy;
background: white;
}
theme
v-bind
120
&&
<template>
<span
class="description"
:class="useTheme && theme"
>
This is how you add dynamic classes in Vue.
</span>
</template>
useTheme theme
false
true true
false
false
121
useTheme false false
useTheme theme
theme
theme
122
expression true ifTrue
ifFalse
<template>
<span
class="description"
:class="darkMode ? 'dark-theme' : 'light-theme'"
>
This is how you add dynamic classes in Vue.
</span>
</template>
light-theme
123
<template>
<span
class="description"
:class="[
fontTheme,
darkMode ? 'dark-theme' : 'light-theme',
]"
>
This is how you add dynamic classes in Vue.
</span>
</template>
fontTheme
darkMode
124
true
<template>
<span
class="description"
:class="{
'dark-theme': darkMode,
'light-theme': !darkMode,
]"
>
This is how you add dynamic classes in Vue.
</span>
</template>
dark-theme light-theme
darkMode
light-theme !darkMode
125
false
darkMode light-theme
dark-theme
<template>
<MovieList
:movies="movies"
:genre="genre"
/>
</template>
126
:class
<template>
<MovieList
:movies="movies"
:genre="genre"
:class="darkMode ? 'dark-theme' : 'light-theme'"
/>
</template>
class
MovieList
props
MovieList class
127
Button
128
<template>
<span
class="description"
:class="theme"
>
This is how you add static classes in Vue.
</span>
</template>
export default {
data() {
return {
theme: 'blue-theme',
};
}
};
.blue-theme {
color: navy;
background: white;
}
Button
129
<template>
<button
@click="$emit('click')"
class="button"
:class="theme"
>
{{ text }}
</button>
</template>
export default {
props: {
theme: {
type: String,
default: 'default',
}
}
};
.default {}
.primary {}
.danger {}
Button theme
.default
primary .primary
130
<template>
<MovieList
:movies="movies"
:genre="genre"
:class="class"
/>
</template>
export default {
computed: {
class() {
return darkMode ? 'dark-theme' : 'light-theme';
}
}
};
131
132
133
mounted
mounted created
134
data
135
136
export default {
created() {
console.log('Component has been created!');
}
};
export default {
destroyed() {
console.log('Component has been destroyed!');
}
};
created mounted
137
mounted
mounted
mounted
data
created mounted
138
created mounted
created
created
created
export default {
data() {
cars: {},
},
created() {
fetch('/cars').then(cars => {
this.cars = cars;
});
}
};
139
created
mounted
created() {
console.log(this.$el);
},
mounted() {
console.log(this.$el);
}
undefined
this.$el
created
140
mounted
141