Vue.js Certification
Bootcamp
Welcome!
Let us introduce ourselves
800+ Video Lessons
150,000 users
Alex Kyriakidis
Daniel Kelly
Debbie O'Brien
Chris Fritz
Maria Lamardo
Roman Kuba
SΓ©bastien Chopin
Filip Rakowski
Mostafa Said
Rolf Haug
Day 1 and Day 2 will look similar
Presentation will look much like what we're doing now
Questions are taken from the chat.
Exercises are your time to practice what you've learned
(show structure in repo)
Section Topics
Section Topics
Day 3 will be a little different
We'll do a live practice exam together!
π We'll send you home with another practice exam too!
Let's join rooms and meet each other!
β° 5 mins
Let's start learning the material for
π¦
1
Section
Build Interactive UI Elements
Interactive Forms
Cookie Consent Dialogs
Carousels
Build Full Applications
React
Angular
Svelte
They are similar in use case just a little different in approach and syntax
React
Angular
Svelte
React
Angular
Svelte
That depends on your needs
Vue is known as a progressive framework
Depending on How You'd like to "Do" Vue
And what your site or apps needs are
Have an existing static or server-rendered site?
Option 1
Use Vue to enhance it with a direct link via a script tag
<script src="https://unpkg.com/vue@3"></script>
π
Have an existing static or server-rendered site?
Use Vue to enhance it with a direct link via a script tag
<script src="https://unpkg.com/vue@3"></script>
π
Have an existing static or server-rendered site?
β No Build Step Required
Use Vue to enhance it with a direct link via a script tag
<script src="https://unpkg.com/vue@3"></script>
π
Have an existing static or server-rendered site?
βοΈBUT can't use Single File Components (SFCs)
Want to create an SPA?
That runs entirely client side and handles all templating and logic with Vue and JavaScript
Option 2
Bootstrap a Vue app with Vite for a build tool
npm create vue@latest
π
Want to create an SPA?
Want to create an SPA?
Want to create a server rendered app?
That uses JavaScript and Vue for logic and templating on both the client and the server
Option 3
Use the meta-framework Nuxt
npx nuxi init
π
Want to create a server rendered app?
Want to create a server rendered app?
There's more but these are the most popular
From a CDN
SPA
SSR
Bootcamp and the Exam Focuses on
Bootcamp and the Exam Focuses on
Bootcamp and the Exam Focuses on
Vue has 2 ways to write components:
βοΈ The options API
π The composition API
βοΈ The options API
BUT
instead of the Options API, the exam FOCUSES on the COMPOSITION API
βFAQβ
Can I use the options API during the exam?
βFAQβ
Can I use the options API during the exam?
Yes! Kind of...
βFAQβ
Can I use the options API during the exam?
You can provide your coding challenge solutions in either API
Multiple Choice Questions will use the Composition API
Coding Challenge Boilerplate will use the Composition API
Bootcamp and the Exam Focuses on
Bootcamp and the Exam Focuses on
Back to Creating a New App...
Every Vue application starts by creating a new application instance
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
All Vue apps have a single top-level (root) component
main.js
Every Vue application starts by creating a new application instance
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
This app only exists in "JavaScript Land"
main.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.mount("#app")
We must mount it to a DOM element to render anything to the page
main.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.config.errorHandler = (err) => {
/* handle error */
}
app.mount("#app")
Use config object to set
some app level settings
main.js
[Application API Docs](vuejs.org/api/application.html)
errorHandler - global handler for uncaught errors
warnHandler - for runtime warnings from Vue
performance - enable component init, compile, render and patch performance tracing
and more - compilerOptions, globalProperties, optionMergeStrategies
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.mount("#app")
main.js
Let's look into the root level App component
<style scoped>
.bg-blue{
background: blue;
}
</style>
App.vue
SFC's encapsulate the component's logic (JavaScript), template (HTML), and styles (CSS) in a single file.
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
<template>
<div class="bg-blue">{{msg}}</div>
</template>
<style scoped>
.bg-blue{
background: blue;
}
</style>
<template>
<div class="bg-blue">{{msg}}</div>
</template>
<style scoped>
.bg-blue{
background: blue;
}
</style>
<style scoped>
.bg-blue{
background: blue;
}
</style>
App.vue
The order of each section is not important
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
<template>
<div class="bg-blue">{{msg}}</div>
</template>
<style scoped>
.bg-blue{
background: blue;
}
</style>
<template>
<div class="bg-blue">{{msg}}</div>
</template>
<style scoped>
.bg-blue{
background: blue;
}
</style>
<style scoped>
.bg-blue{
background: blue;
}
</style>
App.vue
The examples in the Vue.js docs do always start with the Script tag
(so this is a common convention but not required)
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
<template>
<div class="bg-blue">{{msg}}</div>
</template>
<style scoped>
.bg-blue{
background: blue;
}
</style>
<template>
<div class="bg-blue">{{msg}}</div>
</template>
<style scoped>
.bg-blue{
background: blue;
}
</style>
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
<template>
<div class="bg-blue">{{msg}}</div>
</template>
App.vue
An SFC doesn't have to contain ALL of the sections
(for those who use Tailwind CSS you'll often exclude the style tag)
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
<template>
<div class="bg-blue">{{msg}}</div>
</template>
App.vue
But it MUST contain at least a script OR a template
Not using these slides below
But keeping for record, just in case
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
App.vue
Components with ONLY a Script Tag are called
Renderless Components
<template>
<div class="bg-blue">{{msg}}</div>
</template>
App.vue
Components with ONLY a template Tag are often (unofficially) calledΒ Presentational Components
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
<template>
<div>{{msg}}</div>
</template>
App.vue
The setup attribute enables "script setup" mode which makes it easier to use the Composition API
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
<template>
<div>{{msg}}</div>
</template>
App.vue
What's happening in each section?
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
<template>
<div>{{msg}}</div>
</template>
App.vue
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
<template>
<div>{{msg}}</div>
</template>
App.vue
App.vue
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
<template>
<div>{{msg}}</div>
</template>
Whenever the data updates the DOM re-renders the div
A common way of updating data is by accepting user input with v-model
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
<template>
<input v-model="msg">
<div>{{msg}}</div>
</template>
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
<template>
<input v-model="msg">
<div>{{msg}}</div>
</template>
Questions?
ππΎββοΈ
Exercise 1
π©βπ»π¨π½βπ»
2
Section
display text to the page
<div>{{msg}}</div>
<div>
{{msg}}
<input v-model="msg">
</div>
<script setup>
const path = ref("/path/to/cat.jpg");
const alt = ref("a smiling cat");
</script>
<template>
<div>
<img v-bind:src="path" v-bind:alt="alt" />
</div>
</template>
The attribute is an argument to the v-bind directive
<div>
<img src="/path/to/cat.jpg" alt="a smiling cat" />
</div>
Rendered Output
<script setup>
const path = ref("/path/to/cat.jpg");
const alt = ref("a smiling cat");
</script>
<template>
<div>
<img v-bind:src="path" v-bind:alt="alt" />
</div>
</template>
use square brackets to make dynamic
<script setup>
import { ref } from "vue";
const path = ref("/path/to/cat.jpg");
const alt = ref("a smiling cat");
const dynamicAttr = ref("src")
</script>
<template>
<div>
<img v-bind:[dynamicAttr]="path" v-bind:alt="alt" />
</div>
</template>
shorten v-bind to just a colon
<script setup>
import { ref } from "vue";
const path = ref("/path/to/cat.jpg");
const alt = ref("a smiling cat");
const dynamicAttr = ref("src")
</script>
<template>
<div>
<img v-bind:[dynamicAttr]="path" :alt="alt" />
</div>
</template>
v-if allows us to conditionally render elements
<script setup>
import {ref} from "vue";
const sunny = ref(true);
</script>
<template>
<div>
<p v-if="sunny">
It's sunny today! π
</p>
</div>
</template>
<script setup>
import {ref} from "vue";
const sunny = ref(false);
</script>
<template>
<div>
<p v-if="sunny">It's sunny today! π</p>
<p v-else>Is it raining? βοΈ</p>
</div>
</template>
<script setup>
import {ref} from "vue";
const sunny = ref(false);
const windy = ref(true);
</script>
<template>
<p v-if="sunny">It's sunny today! π</p>
<p v-else-if="windy">It's windy today! π¬</p>
<p v-else>Is it raining? βοΈ</p>
</template>
<script setup>
import {ref} from "vue";
const sunny = ref(false);
</script>
<template>
<p v-if="sunny">It's sunny today! π</p>
<p v-show="sunny">It's sunny today! π</p>
</template>
Neither will display to the page
<script setup>
import {ref} from "vue";
const sunny = ref(false);
</script>
<template>
<p style="display: none;">It's sunny today! π</p>
</template>
Rendered Result
v-if leaves NO DOM element
v-show hides with style
Use v-show if the element will be toggled often and/or quickly. This will be slightly more performant
<script setup>
import {ref} from "vue";
const weather = ref("hurricane");
</script>
<template>
<div>
<p v-if="weather === 'sunny'">It's sunny today! π</p>
<p v-else-if="weather === 'windy'">It's windy today! π¬</p>
<p v-else>Is it raining? βοΈ</p>
</div>
</template>
<script setup>
import {ref} from "vue";
const ok = ref(true);
</script>
<template>
<div>
Is everything ok? {{ ok ? "Yes" : "No" }}
</div>
</template>
Keep it simple or extract the logic
<script setup>
import {ref} from "vue";
const heroes = ref([
{id: 1, name: 'Bruce Wayne', alterEgo: 'Batman'},
{id: 2, name: 'Clark Kent', alterEgo: 'Superman'},
{id: 3, name: 'Tony Stark', alterEgo: 'Ironman'},
{id: 4, name: 'Diana Prince', alterEgo: 'Wonder Woman'}
])
</script>
Is the individual array item
Name of the reactive data
Can be any name
<script setup>
import {ref} from "vue";
const heroes = ref([
{id: 1, name: 'Bruce Wayne', alterEgo: 'Batman'},
{id: 2, name: 'Clark Kent', alterEgo: 'Superman'},
{id: 3, name: 'Tony Stark', alterEgo: 'Ironman'},
{id: 4, name: 'Diana Prince', alterEgo: 'Wonder Woman'}
])
</script>
<template>
<ul>
<li v-for="hero in heroes"> {{ hero.name }} </li>
</ul>
</template>
Can also access the index
<li v-for="(hero, index) in heroes"> {{ hero.name }} </li>
<ul>
<li> Bruce Wayne </li>
<li> Clark Kent </li>
<li> Tony Stark </li>
<li> Diana Prince </li>
</ul>
Rendered Output
<div v-for="hero in heroes">
{{ hero.name }}
</div>
The item is available inside the element
<div v-for="hero in heroes">
<span>{{ hero.name }}</span>
</div>
The item is available inside child elements
<img
v-for="image in myImages"
:src="image.src"
:alt="image.title" />
The item is available on the element
<img
v-if="image.src"
v-for="image in myImages"
:src="image.src"
:alt="image.title" />
It is not recommended to use v-if with v-for on the same element
<img
v-for="image in filteredImages"
:src="image.src"
:alt="image.title" />
<template v-for="image in myImages">
<img
v-if="image.src"
:src="image.src"
:alt="image.title" />
</template>
OR
<li v-for="hero in heroes" :key="hero.id"> {{ hero.name }} </li>
<script setup>
import { ref } from 'vue';
const framework = ref({
name: 'Vue',
isAwesome: true,
latestMajorVersion: 3,
});
</script>
<template>
<ul>
<li v-for="value in framework">{{ value }}</li>
</ul>
</template>
<ul>
<li>Vue</li>
<li>true</li>
<li>3</li>
</ul>
Rendered Output
<li v-for="(value, key) in framework">{{key}} {{value}}</li>
access property key
<li>name Vue</li>
<li>isAwesome true</li>
<li>latestMajorVersion 3</li>
Rendered Output
<li v-for="n in 3">{{n}}</li>
<li>1</li>
<li>2</li>
<li>3</li>
Rendered Output
<li v-for="char in 'Hello'">{{char}}</li>
<li>H</li>
<li>e</li>
<li>l</li>
<li>l</li>
<li>o</li>
Rendered Output
Questions?
ππΎββοΈ
Exercise 2
π©βπ»π¨π½βπ»
Coffee Break
βοΈ
3
Section
<button v-on:click="raining = true">Make it rain!</button>
(inline handler)
<button @click="raining = true">Make it rain!</button>
<button @click="raining = true">Make it rain!</button>
makeItRain()
<script setup>
import {ref} from "vue";
const raining = ref(false);
function makeItRain(){
raining.value = true;
}
</script>
<template>
<button @click="makeItRain()">Make it rain!</button>
</template>
<button v-on:click="raining = true">Make it rain!</button>
makeItRain()
Define a handler function in script setup
Notice .value
<script setup>
import {ref} from "vue";
const raining = ref(false);
function makeItRain(){
raining.value = true;
}
</script>
<template>
<button @click="makeItRain">Make it rain!</button>
</template>
Can shorten handler by excluding the parens
<script setup>
import {ref} from "vue";
const raining = ref(false);
function makeItRain(e){
raining.value = true;
}
</script>
<template>
<button @click="makeItRain">Make it rain!</button>
</template>
This automatically passes the event
in this case it's a browser native Event object
The same event is available inline as $event
<script setup>
import {ref} from "vue";
const raining = ref(false);
function makeItRain(e){
raining.value = true;
}
</script>
<template>
<button @click="makeItRain($event)">Make it rain!</button>
</template>
It's just a directive argument!
<script setup>
//...
const listener = ref("click");
</script>
<template>
<button v-on:[listener]="makeItRain">Make it rain!</button>
</template>
<script setup>
//...
const listener = ref("click");
</script>
<template>
<button @[listener]="makeItRain">Make it rain!</button>
</template>
It works with the shorthand too
<script setup>
const handleClick = ()=> console.log("clicked");
const handleMouseEnter = ()=> console.log("mouse entered")
</script>
<template>
<button
@click="handleClick"
@mouseenter="handleMouseEnter"
>
Make it rain!
</button>
</template>
<script setup>
const listeners = {
click: () => console.log('clicked'),
mouseenter: () => console.log('mouse entered'),
};
</script>
<template>
<button v-on="listeners">Make it rain!</button>
</template>
All listeners as object
<form @submit.prevent="submitForm">
...
</form>
submitForm(event) {
event.preventDefault()
// ...
}
π‘ TIP: Order Matters
// prevents click's default action on
// the element itself and its children
@click.prevent.self
// only prevent click's default action
// on the element itself.
@click.self.prevent
<textarea @keydown.esc="clearText" />
.enter
.tab
.delete
.esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
.meta
.a
.b
....
Questions?
ππΎββοΈ
Exercise 3
π©βπ»π¨π½βπ»
4
Section
So far we've used
ref()
to define reactive data
You could also use
reactive()
What's the difference? π€
According to the docs:
Practically speaking what does that mean?
// β
ref works
const framwork = ref('Vue')
const isAwesome = ref(true)
const created = ref(2014)
// β won't work
const framwork = reactive('Vue')
const isAwesome = reactive(true)
const created = reactive(2014)
// β
ref works
let posts = ref(['post 1', 'post 2'])
posts.value = ['post 3', 'post 4']
// β won't work
let posts = reactive(['post 1', 'post 2'])
posts = ['post 3', 'post 4']
// ref
const framework = ref({
name: 'Vue',
author:'Evan You',
tags: ['javascript', 'vue']
})
β¬οΈ
console.log(framework.value.name)
// reactive
const framework = reactive({
name: 'Vue',
author:'Evan You',
tags: ['javascript', 'vue']
})
console.log(framework.name)
// β
ref works
const framework = {
name: ref('Vue'),
author: ref('Evan You'),
tags: ref(['javascript', 'vue'])
}
const { name } = framework
// β reactive doesn't
const framework = reactive({
name: 'Vue',
author:'Evan You',
tags: ['javascript', 'vue']
})
// name is no longer reactive
const { name } = framework
// β
will work
const framework = toRefs(reactive({
name: 'Vue',
author:'Evan You',
tags: ['javascript', 'vue']
}))
const { name } = framework
Ref or Reactive
Besides reactive state, we can also define derived reactive state with
computed()
<script setup>
import {ref} from "vue";
const message = ref("Hello world");
</script>
<template>
<h1>{{ message.split('').reverse().join('') }}</h1>
<input v-model="message">
</template>
We can do inline expressions
BUT this has drawbacks:
Instead we can use computed
<script setup>
import { ref, computed } from "vue";
const message = ref("Hello world");
const backwardsMessages = computed(()=>{
return message.value.split('').reverse().join('')
})
</script>
<template>
<h1>{{backwardsMessages}}</h1>
<input v-model="message">
</template>
Filtering Array Data
<script setup>
import { ref, computed } from 'vue';
const movies = ref([
{ title: 'Jurassic Park', rating: 8.2 },
{ title: 'The Shawshank Redemption', rating: 9.3 },
{ title: 'The Dark Knight', rating: 9.0 },
{ title: 'The Master of Disguise', rating: 3.3 },
]);
const goodMovies = computed(() => {
return movies.value.filter((movie) => movie.rating > 5);
});
console.log(goodMovies.value.length) // 3
</script>
Sorting Array Data
<script setup>
import { ref, computed } from 'vue';
const movies = ref([
{ title: 'Jurassic Park', rating: 8.2 },
{ title: 'The Shawshank Redemption', rating: 9.3 },
{ title: 'The Dark Knight', rating: 9.0 },
{ title: 'The Master of Disguise', rating: 3.3 },
]);
const moviesOrderedByRatingDesc = computed(() => {
return [...movies.value].sort((a, b) => b.rating - a.rating);
});
</script>
Notice we cloned the movies array
Sort alters the array its called on!
β οΈ
Be careful to NEVER mutate data or trigger side effects in a computed prop
Computed values are cached based on reactive deps
Cached example
<script setup>
import { ref, computed } from 'vue';
const message = ref('Hello world');
const backwardsMessage = computed(() => {
console.log('computing');
return message.value.split('').reverse().join('');
});
</script>
<template>
{{ backwardsMessage }}
{{ backwardsMessage }}
{{ backwardsMessage }}
</template>
This will only log once!
Common Mistake
<script setup>
import { ref, computed } from 'vue';
const randomNumber = computed(() => {
return window.localStorage.getItem('randomNumber');
});
setInterval(() => {
window.localStorage.setItem('randomNumber', Math.random());
}, 1000);
</script>
Expecting non-reactive deps to trigger computed to re-evaluate
Questions?
ππΎββοΈ
Exercise 4
π©βπ»π¨π½βπ»
Coffee Break
βοΈ
5
Section
You can bind classes and styles with v-bind just like any other attribute
<script setup>
import { ref } from 'vue';
const active = ref(false);
</script>
<template>
<div :class="active ? 'is-active' : ''"></div>
</template>
Boolean Classes
<div class=""></div>
Rendered Result
<script setup>
import { ref } from 'vue';
const active = ref(true);
</script>
<template>
<div :class="active ? 'is-active' : ''"></div>
</template>
Boolean Classes
<div class="is-active"></div>
Rendered Result
Boolean Classes
<script setup>
import { ref } from 'vue';
const active = ref(true);
</script>
<template>
<div :class="{ 'is-active': active }"></div>
</template>
Can shorten to an object
Boolean Classes
<script setup>
import { ref } from 'vue';
const active = ref(true);
</script>
<template>
<div :class="{ active }"></div>
</template>
Can shorten further if the class-name is the same as the reactive data
<div class="active"></div>
Rendered Result
Mix static and dynamic classes
<script setup>
import { ref } from 'vue';
const active = ref(true);
</script>
<template>
<div
class="static"
:class="{ active }"
></div>
</template>
<div class="static active"></div>
Rendered result
Multiple Classes as an Array
<div class="class-1 class-2 class-3"></div>
<div :class="['class-1', 'class-2', 'class-3']"></div>
Same as
(easier to work with if your class list is dynamic)
Can Mix Arrays and Objects
<div :class="[ { active }, 'static' ]"></div>
Can bind to computed prop or reactive data
<script setup>
import { ref, computed } from 'vue';
const active = ref(true);
const classes = computed(()=>{
return [
'static',
{ active: active.value }
]
})
</script>
<template>
<div
:class="classes"
></div>
</template>
Vue also has shortands for
<div :style="{
color: activeColor,
fontSize: fontSize + 'px'
}"></div>
const activeColor = ref('red')
const fontSize = ref(30)
Styles Shorthand
camelCase is recommended
<div :style="{
color: activeColor,
'font-size': fontSize + 'px'
}"></div>
const activeColor = ref('red')
const fontSize = ref(30)
Styles Shorthand
Kebab case is also supported
(but must have quotes)
<div :style="styleObject"></div>
const styleObject = ref({
color: 'red',
fontSize: '13px'
})
Can bind full reactive ref
<div :style="[baseStyles, overridingStyles]"></div>
const baseStyles = ref({ /*...*/ })
const overridingStyles = ref({/*...*/})
Can bind multiple objects that will be merged
When you use a CSS property that requires a vendor prefix in :style
, Vue will automatically add the appropriate prefix.
(Vue checks support at runtime)
Questions?
ππΎββοΈ
Exercise 5
π©βπ»π¨π½βπ»
6
Section
Forms are the most common way of gathering user input
v-model is the primary way of interacting with form inputs
We already saw it in action
<script setup>
const msg = ref("Hello Bootcampers!");
</script>
<template>
<input v-model="msg">
<div>{{msg}}</div>
</template>
v-model behaves differently based on the input type
<input type="text" v-model="msg">
const msg = ref("Hello World");
Great for string data
Syntactic Sugar
<input type="text" v-model="msg">
<input type="text" :value="msg" @input="msg = $event.target.value">
<textarea v-model="msg"></textarea>
const msg = ref("Hello World");
Also great for strings
<select v-model="framework">
<option value="Vue">Vue</option>
<option value="React">React</option>
<option value="Svelte">Svelte</option>
</select>
const framework = ref("Vue");
Work with strings but you want to limit options
<select v-model="framework">
<option v-for="option in options" :key="option.name" :value="option">
{{option.name}}
</option>
</select>
const framework = ref({ name: "Vue", version: 3 });
const options = [
{ name: "Vue", version: 3 },
{ name: 'React', version: 'x' },
{ name: 'Svelte', version: 'x' }
]
Also works with other data types
<select v-model="framework" multiple>
<option v-for="option in options" :key="option.name" :value="option">
{{option.name}}
</option>
</select>
const framework = ref([{ name: "Vue", version: 3 }]);
const options = [
{ name: "Vue", version: 3 },
{ name: 'React', version: 'x' },
{ name: 'Svelte', version: 'x' }
]
Works with arrays and the multiple attribute to allow selection of more than one option
<label>
<input type="radio" value="Vue" v-model="framework"/> Vue
</label>
<label>
<input type="radio" value="React" v-model="framework"/> React
</label>
<label>
<input type="radio" value="Svelte" v-model="framework"/> Svelte
</label>
const framework = ref("Vue");
Works much like selects but instead of options, its inputs with the SAME v-model
<label>
<input type="checkbox" value="Vue" v-model="framework"/> Vue
</label>
<label>
<input type="checkbox" value="React" v-model="framework"/> React
</label>
<label>
<input type="checkbox" value="Svelte" v-model="framework"/> Svelte
</label>
const framework = ref([]);
Works with arrays (just like select with multiple attribute)
<label>
<input type="checkbox" v-model="agree"/> I agree
</label>
const agree = ref(false);
Also works with Booleans
<label>
<input
type="checkbox"
v-model="agree"
true-value="Yes"
false-value="No"
/> I agree
</label>
const agree = ref("No");
Can customize boolean values
<!-- trims whitespace from either side -->
<input type="text" v-model.trim="msg">
<!-- auto cast to number -->
<input type="string" v-model.number="age">
<!-- number modifier not needed on number inputs -->
<input type="number" v-model="age">
<!-- lazily update the bound data via the change event-->
<!-- (when the element's value changes and then loses focus) -->
<input type="string" v-model.lazy="msg">
Questions?
ππΎββοΈ
Exercise 6
π©βπ»π¨π½βπ»
π
That's all for day 1
Homework
Continue practicing the concepts we learned today if you choose
Official Training Module
Resources for Helping to Complete Homework
ππΎββοΈ
Any final questions?
π
See you next week!