How do you install and run a new vue project?
sudo npm install -g @vue/cli
vue create my-app
cd my-app
npm run serve
or yarn serve
What are the two styles of writing vue?
this
component instance<script setup>
so you do not have to explicitly export varsHow do you create a Vue3 app?
import { createApp } from 'vue';
const app = createApp({
data() {
return {
count: 0
}
}
});
app.mount('#app')
<div id="app">
<button @click="count++">{{ count }} </button>
</div>
app.mount('#app');
What is a directive? Give a few examples of directives.
A directive is a special attribute that extends HTML elements with added functionality. They offer a way to manipulate the DOM directly from Vue templates
v-bind:class="{ active: isActive" }
const myHTML = const myHTML = '<span style="color: red">Red</span>'
<!-- eslint-disable-next-line vue/no-v-html -->
<div v-html="myHTML"></div> // renders Red
How do you print out actual html of the following using interpolation?
const rawHtml = '<span style="color: red">Red</span>'
Just use the double mustache: {{ rawHtml }}
// Prints the actual html: <span style="color: red">Red</span>
How do you print out the interpreted html value of the following? const rawHtml = '<span style="color: red">Red</span>'
Prints: Red
Also note: You need the eslint-disable or you will break because interpreting embedded HTML is a serious security risk.What must a reactive var type be?
Object or array; No primitives;
What are two reactive state vars?
reactive = Object or array;
ref() for primitives other non objects or non array types.
How do you create a reactive var from a primitive or any type that is not an object or array?
const count = ref(0)
Use the ref() method, passing in the value. This creates an object with value key.
How do you retrieve the value of a nested reactive() object?
Either deconstruct the object's key for the value or explicitly give the path to the nested value.
In the template, print the value of "second level" in the following object:
const deepObj = reactive({
first: {
'first_level': 'first level',
second: {
'second_level': 'second level'
}
}
})
<template>
<div>{{ deepObj.first.second.second_level }}</div>
</template>
For the following array, change the value of the 1st index to 123
- a number.
const myArray = reactive([1, 2, 3]);
myArray[1] = 123
You have const myRef = ref('Hello World'); You want to console.log the value. How?
myRef must use .value in the script block: myRef.value
You have const myRef = ref('Hello World'); You want to display this value in the template. How?
Providing myRef is not a deeply nested object, or you've dereferenced it down to the last nest you do not need to use .value{{ myRef }}
You want to change the value of const myRef = ref('Hello World')
to 'I have changed'. Can you do the following?
myRef = 'I have changed'
No! myRef is a constant. You cannot change a constant value. You MUST use myRef.value = 'I have changed'
In a <script setup> block, which variables can be used as state variables directly in the template?
A reactive state declared in the < script setup > block. e.g.:
<script setup>
const myReactive = { foo: 'bar' }
const myRef = ref('fooBar')
</script>
<template>
<h1>{{ myReactive.foo }}<h1>
<h1>{{ myRef }}<h1>
</template>
How do you bind a dynamic value inside an element?
Use either vbind:
or the shorthand :
inside the element.
<div v-bind:id="dynamicId"></div>
You need to add 4 to the myArray = reactive([1,2,3]); How do you do this?
myArray.push(4)
You need to add a new todo to the myArray = ref([{id: id++, text: 'First'}]); How do you do this?
myArray.value.push({id: id++, text: 'Second'})
You need to add a new todo to the myArray = reactive([{id: id++, text: 'First'}]); How do you do this?
myArray.push({id: id++, text: 'Second'})
When you are pushing a new array member to a ref(), do you need to use .value?
Yes! With ref()'s you must use .value.myRef.value.push({id: id++, text: 'Second'})
When you are pushing a new array member to a reactive() var, do you need to use .value?
No! With reactive vars you only use .push -- not .value!myReactive.push({id: id++, text: 'Second'})
What is the shorthand for v-bind:id?
<div :id="dynamicId"></div>
How do you add an event listener from the DOM or a custom event in your HTML element?
<button v-on:click="increment">Increment</button>
<button @click="increment">Increment</button>
What is the explicit way to implement two way binding on an input element?
use :value="varName" @input="inputFunctionName" in your input element;
<script setup>
import { ref } from 'vue'
const varName = ref('')
function inputFunctionName(e) {
varName.value = e.target.value
}
</script>
<template>
<input :value="varName" @input="inputFunctionName" placeholder="Type here">
<p>{{ varName }}</p>
</template>
What is the shorthand for j< input v-bind:="text">
:
< input :="text">
What is the shorthand for v-on?
<input v-on:click="onClickMethod">
@
< input @click="onClickMethod"
What is the shorthand for two way binding on your input element?
<input v-model="text">
There is no longer the need for the @input="onInput" function or :value="text" as v-model will directly change the value of your variable "text".value using v-model="text"
%lt;script setup>
import { ref } from 'vue'
const text = ref('')
function onInput(e) {
text.value = e.target.value
}
</script>
<template>
<input :value="text" @input="onInput" placeholder="Type here">
<p>{{ text }}</p>
</template>
<script setup>
import { ref } from 'vue'
const text = ref('')
</script>
<template>
<input v-model="text" placeholder="Type here">
<p>{{ text }}</p>
</template>
How do you conditionally render an element?
use "v-if="
<h1 v-if="showMe">Conditional Statement!!!</h1>
How would you write an if:else block for elements?
<h1 v-if="truthyVar">Print if truthy!!!</h1>
<h1 v-else>Print this if not truthy!!!</h1>
How would you write the following code to use the v-if and v-else?
<script setup>
import { ref } from 'vue';
const awesome = ref(true);
function toggle() {
// insert code here to change
}
</script>
<template>
<button @click="toggle">Toggle</button>
<h1 >Vue is awesome!</h1>
<h1 >Oh no 😢</h1>
</template>
<script setup>
import { ref } from 'vue';
const awesome = ref(true);
function toggle() {
awesome.value = !awesome.value
}
</script>
<template>
<button @click="toggle">Toggle</button>
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
</template>
What are the if, then, else if, else conditional statements for HTML elements to appear?
v-if, v-else-if, v-else
Using a todo list which is an array of objects of the form { id: id++, text: "some text" }, write a for loop to present this as an unordered list of todo items.
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
<button @click="removeTodo(todo)">X</button>
</li>
How did you bind the id of the todo list to the li element?
v-bind:key=, or shorthand: :key=
You have a boolean variable you need to declare, then toggle. How?
let awesome = ref(true);
function toggle() {
awesome.value = !awesome.value;
}
You have the following list array:
const todo = reactive([
{id: 1, text: 'First todo'},
{id: 2, text: 'Second todo'},
{id: 3, text: 'Third todo'
}])
Besides the text value, what is the directive needed on each list item?
:key=todo.id
eg: <li v-for="todo in todos" :key="todo.id">
{{ todo.text}}
</li>
You have the following array. Write a v-for to print each of the todos.
let id = 0;
const todos = ref([
{ id: id++, text: 'First Todo' },
{ id: id++, text: 'Second Todo' },
{ id: id++, text: 'Third Todo' }
]);
<template>
<li v-for="todo in todos" :key="todo.id">
{{todo.text}}
</li>
</template>
Note todo.text
or todo.id
On the array above, what prints out if you console.log(todos.value)
The entire array: {0: {...}, 1: {...}, 2: {...}}
Again, on the array above, what prints out if you console.log(`todos[0]: `, todos[0]);
undefined. A ref must be accessed through the .value key. That is where the array of objects resides.
How do you add a new array item to the todos object array shown above?
todos.value.push( {id: id++, text: newTodo.value } );
newTodo is a ref(''), so it will have a value key.
todos has a value key which represents (amongst other things) the array of todos.
todos.value: Proxy(Array) {0: {…}, 1: {…}, 2: {…}} [[Handler]]:MutableReactiveHandler [[Target]]: Array(4) 0: {id: 0, text: 'Learn HTML'} 1: {id: 1, text: 'Learn JavaScript'} 2: {id: 2, text: 'Learn Vue'} 3: {id: 3, text: 'Learn C++'} length: 4 [[Prototype]]: Array(0) [[IsRevoked]]: false
Again for the todos structure above, what prints in console.log(todos[0]);
?
Remove the 'Learn Vue' from the todo list. Assume the function passes in a todo object with id and text.
You need to create an array of objects based on the current state of vars. How would you do this?
const filteredTodos = computed(() => {
return hideCompleted.value
? todos.value.filter((t) => !t.done)
: todos.value
})
<button @click="hideCompleted = !hideCompleted">
{{ hideCompleted ? 'Show all' : 'Hide completed' }}
</button>
What do we need to do to access the DOM directly?
const pElementRef = ref(null)
because the ref must be null as it will not exist until the component is mounted.ref="pElementRef"
onMounted( () => {
pElementRef.value.textContent = 'mounted!';
});
<script setup>
import { ref, onMounted } from 'vue'
const pElementRef = ref(null)
onMounted(() => {
pElementRef.value.textContent = 'mounted!'
})
</script>
<template>
<p ref="pElementRef">Hello</p>
</template>
What is the difference between displaying/accessing the value of const count = ref(0)
within the script block and the template block?
In the script block, to access the value of count, you must use count.value
.
In the template block, the value may be displayed within double mustaches {{ count }}
You have the following code in the <script setup> block. What is the value of count?
const count = ref(0);
let countString = `The count is: ${count}`
count.value+=1;
The count is 0
Like angular, strings are evaluated only once during onMount.
You want to console.log count each time it is updated. How would you do this?
const count = ref(0);
function incrementCount() { count.value += 1 };
watch(count, (newCount) => {
console.log(`Count has been updated. newCount is: ${newCount}`);
})
incrementCount();
incrementCount();
The console log will be printed twice -- once for each call to incrementCount, as count has changed.
How do we pass reactive vars from a parent to a child?
The same way as svelte:
<script setup>
import AnotherComponent from 'AnotherComponent.vue';
const parentMessage = "Message from parent"
const parentCount = ref(0)
</script>
<template>
<AnotherComponent :msg="parentMessage" :count="parentCount" />
</template>
How do we receive the values from the parent component, assuming they will not change:
In the child component, use defineProps. Then define the incoming variable in the child component.
<script setup>
const props = defineProps({
msg: String // parent component has defined msg. This lets child component know about the var.
count: number
});
<script>
<template>
<h2>{{ msg }}, {{count}}</h2>
You will be sending a msg from the child component. The parent component will use the child's msg. How do you make this happen?
<script setup>
import ChildComponent from './ChildComponent.vue';
const childMsg = ref('Hi from parent component'); // This will change when the child responds.
</script>
<template>
<ChildComponent @response="(msg) => childMsg = msg" />
<h2>childMsg</h2>
</template>
<script setup>
const emit = defineEmits(['response']) // parent components var name 'response' which will be observed for the new value.
emit('response', 'hello from child'); // pass 'hellofrom child' through the response variable to the parent.
</script>
How are slots used in Vue?
<ChildComponent>This is the content of the slot for the child.</>
<slot>Fallback content</slot>
What value for attributes will cause the attribute to be excluded?
If the falsy value is anything other than empty string " "
Will this interpolation work? Explain. {{ var a = 1 }}
Njo. This is not an expression. This is a statement.
Will this work in an interpolation? {{if (ok) { treutn message} }}
This flow control statement won't work. Use a ternary : ok ? message : null
Is it possible to call a component-exposed metthod inside a binding expression. i.e.:
<time :title="toTitleDate(date)" :datetime"date">
{{ formateDate(date) }}
< /time >
Yes
What are two ways watching for a custom event handler called "doSomething" in your HTML element.
There are the standard key references in javascript: [focus] or focus in the following examples:
<a @[focus]="doSomething">
<a v-on:focus="doSomething"
How will the following evaluate? Explain.
const raw = {};
const proxy = reactive(raw)
console.log(proxy === raw)
{}
> will evaluate to false, because the empty object gets reassigned to a reactive object. Two different spaces in memory:
raw = {};
reactive(raw) =
Proxy(Array) 0: {...}, 1: {...}
[[Handler]]: MutableReactiveHandler
[[Target]]: Array(2)
[[IsRevoked]]
When a change is made to a component's reactive variable, what happens?
tick
the buffer is emptied and the new values are updated in the DOMHow would you force an immediate rerender?
Call the tick()
function.
Let's say you have a function that is going to invoke a rerender, eventually. How do you ensure this function waits until the next rerender cycle?
nextTick()
You have the following code. What is the value of state.count after updating count?
const state = reactive({count: 0})
const { count } = state;
count += 1;
state.count
will = 0. You've lost the reactive nature of count when you deconstructed this.
What is the value of the following?
<script setup>
const count = ref(0)
const object = { id: ref(1) }
</script>
<template>
<p>count + 1 {{ count + 1 }}</p>
<p>object.id + 1 = {{ object.id + 1}}</p>
</template>
count + 1 = 1
object.id + 1 = <will not compile>
You need to dereference the value in object.id as object.id.value + 1
because it was declared as a ref(1) in the object. As such, it won't get automatically unwrapped by the interpolater.
You want to write a character count for an input box that shows how many characters are entered as they are entered. i.e. 25/200 where 200 is the max characters allowed. How would you do this?
In the script area, import computed. Then create a const called computedChars = ( () => return newItem.value.length); Then create a p tag under the input box for displaying: <p>{{ computedChars }}/200</p>
What is wrong with the following code?
const reverseList = computed( () => return items.value.reverse() )
.reverse will mutate items.value array. You may not want to mutate the array. For instance, this will interrupt the reactivity of the original array.
How would you fix the code above?
Spread the array, then call reverse on it: return [...items.value].reverse()
How would you bind a class active: isActive within your element?
<div :class="{active: isActive }"></div>
Can you bind reactive objects to class attributes?
Yes! And you use them just like any other object with <div :class="classObject"></div>
How would you bind both active:isActive and 'text-danger': hasError on your html element?
<div :class="{active: isActive, 'text-danger': hasError}"
How would the following appear in your dev tools for your html element?
const classObject = reactive({
active: true,
'text-danger': false
});
< div :class="classObject"></div>
<div class="active"></div>
Only the the truthy classes will appear in devtools.
Can we use computed() properties in :bind statements?
Yes. We need to return the object with the attributes in an object; then use the computedConstVar name in bind;
const isActive = ref(true)
const error = ref(null)
const classObject = computed(() => ({
active: isActive.value && !error.value, // remember, isActive and error are declared as ref's, so you need to access as .value
'text-danger': error.value && error.value.type === 'fatal'
}))
<div :class="classObject"></div>
Can you bind a class to an array?
Yes! Remember the ref nature of values within interpolation. No need to access them with ".value"
const isActive = ref(true)
const error = ref(null)
<div :class="[activeClass, errorClass]"></div>
Is the following legal?
<div :class="[isActive ? activeClass : '', errorClass]"></div>
Yes. You can use ternaries in conjunction with other boolean classes
Is the following legal?
<div :class="[{ [activeClass]: isActive }, errorClass]"></div>
What is a root element in your component?
eg:
<template>
<div>
<h1>Hello from this component!</h1>
<p>From this component here's some text.</p>
</div>
The <div>
is considered the root element.
What if you do not want to add a root element? How would you handle this component?
Define the template as functional: <template functional>
. Then you can have no root elements. However, they lack their own state, if that's important.
What are the kinds of root nodes?
<div>
shown in the example above.<template functional>
but they do now carry their own state.<h1>, <p>)
but attributes and events can get twisted unless you're very careful.Your component has multiple root elements. How would you define an attribute from the parent class?
Use <p :class=&attrs.class">Hi!</p>
in your child class after passing it down from your parent component: <ParentComponent class="baz"/>
Define a fallthrough attribute.
A "fallthrough attribute" is an attribute or v-on event listener that is passed to a component, but is not explicitly declared in the receiving component's props or emits. Common examples of this include class, style, and id attributes.
If a parent component calls a child like: < MyButton class="large" />
, what happens to the child?
If there is only one root element, and the attribute was not declared as an accepted prop, then this is called a "fallthrough" attribute and the class is applied to the root element of the child automatically.
<MyButton class="large" />
// child class button's root element
<button class="large">Click Me</button> // class is applied automatically to root element.
Will a fallthrough attribute fall through to the granchild component?
Yes. However, there are caveats with v-on and attributes declared as props or events. If you see this behavior, reference Vue Page on Attributes
Can you disable this inheritance issue?
Yes, in the defineOptions object:
<script setup>
defineOptions({
inheritAttrs: false
})
</script>
How do you access the fallthrough attributes if the options object has set inheritAttrs: false?
In the $attrs
object: <span>Fallthrough attributes: {{ $attrs }}</span>