Vue Js 2
VueJs#
Why javascript?#
It runs in the browser
Why use vue?#
- lean, small (16 kb)
- fast at runtime
Vue Instance#
new Vue({
el: '#app',
data: {
title: 'Hello World'
}
});
<div id="app">
<p>{{ title }}</p>
</div>
- Core of vue application
- Control their own template of HTML
- Pass a javascript object to constructor
Directive#
A command or instruction that vuejs will recognise
<input type="text" v-on:input="changeTitle"/>
Add method
to the Vue Instance
Remember the default event
object is created by vanilla js
Quick start#
JS#
new Vue({ el: 'div#app',
data: {
title: 'Hello World!'
},
methods: {
changeTitle: function(event){
this.title = event.target.value;
}
}
})
HTML#
<script src="https://unpkg.com/vue@2.2.6"></script>
<div id="app">
<input type="text" v-on:input="changeTitle">
<p>
{{ title }}
</p>
</div>
VueJS Templates#
- Creates a template based on html code, which it uses to create the real HTML rendered as the DOM
- The html is the layer in the middle, not the same html in the DOM
Access to data
object properties of Vue
instance are accesses by their variable name eg. {{ title }}
Can also run methods
inside templates eg. {{ sayHello() }}
, but has to be something that can be converted to string
Accessing data in Vue Instance#
Accessing data and methods from the Vue
object is done though the this
keyword. Even though the title may be a property of the data
object it is accessed with this.title
within the Vue
Object
Cannot use curly braces (parenthesis) in any html element attribute
Need to use v-bind
: eg: v-binf:href="link"
All instances of a variable change in the DOM when it is updated
Adding v-once
to an element will not be updated later on.
Eg. <p v-once>{{ title }}</p>
Html elements as data attributes - Output Raw HTML#
By default Vue escapes html. However if there is a case where you know it is safe.
Use v-html
Eg. vhtml=finishedLink
Events#
Use the v-on
keyword
You can listen to any event available for that DOM element
eg.
<button v-on:click="increase">Click me</button>
How do we access the default event object created by the DOM#
Well it is passed automatically to all vueJS methods from v-on
How do you pass your owner argument#
<button v-on:click="increase(2)">Click me</button>
...
methods:
increase: function(step){
...
}
...
Passing both your own argument and the default event object#
Use the protected $event
variable
<button v-on:click="increase(2, $event)">Click me</button>
...
methods:
increase: function(step, event){
...
}
...
Event Modifiers#
Vue has a function in between
.stop
- stop Propagationprevent
- prevent Default
Eg.
<span v-on:mousemove.stop>DEAD SPOT</span>
Key modifiers#
Only avaialble for keyboard related events
Listen only for Enter keyup
Eg.
<input type="text" v-on:keyup.enter="alertMe">
Writing javascript in template#
Wherever you can access your Vue instance, you can run any valid single javascript expression and does not contain an if
or loop
Can also put ternary expressions there
Eg.
{{ counter > 50 ? 'Hello' : counter++}}
Two way data binding#
Is done by using the v-model
directive
Reactive#
Data is not reactive
Computed#
Another option for VueJS constructor called computed
Where functions are declared but are used like properties in data object
Computed properties is aware of data that has changed and whether the function should be rerun
new Vue({
computed: {
functionName : function(){
}
}
})
Watch#
Set up property name you want to watch
Specific code you want to execute when property changes
Computed properties always need synchronous tasks. For asynchronous tasks you msut use watch
Best practice to use computed
as they are more optimised
new Vue({
watch: {
counter : function(value){
}
}
})
keyword this
is not available in a callback closure
You can also watch a computed variable
Shorthand#
- Events - can replace
v-on
with@
Eg. @click=...
=== v-on:click=...
- Bind - replace
v-bind
with:
Eg. :href
=== v-bind:href
Attributes are Merged#
You can have a class
attribute on an element, but a bound attribute :class
can also be added and vue js will manage it.
<div :class="{red: attachRed}">
With the v-class
or :class
bound value it expects a list or javascript object.
key
- name of class
value
- true/false, whether to add that class
Can also directly change properties#
<div :style="{ 'background-color':color }">
And it bind to the color
data attribute
Source#
Udemy Vuejs 2 Course
Conditionals#
Actually removes or adds the element to the DOM (Including nested) based on a data field that resovles to true of false
Use v-if=
<p v-if="show">See me</p>
Very important to use v-if=
instead of v-if:
as that will break html on the page
Basically if html on the page is borked, then ensure it is formatted correctly
Can switch to the negative if we use v-else
No need for a condition on the v-else
Show or Hide instead of Removing or adding#
Use v-show=
Lists#
v-for=
directive
<li v-for="ingredient in ingredients">{{ ingredient }}</li>
With an index:
<li v-for="ingredient, index in ingredients">{{ ingredient }} ({{ index }})</li>
Can also put a v-for
on a template
element
Loop through properties of Objects#
<li v-for="person in persons">
<span v-for="value in person">{{ value }}</span>
</li>
<li v-for="person in persons">
<div v-for="value, key, index in person">{{ key }}: {{ value }} - ({{ index }})</div>
</li>
new Vue({
el: '#app',
data: {
ingredients: ['Meat', 'fruit', 'cookies'],
persons: [
{name: 'Max', age:27 , colour:'red'},
{name: 'Anna', age:'unknown' , colour: 'blue'},
]
}
})
Looping through a range of integers#
<span v-for="n in 10">{{ n }}</span>
For loop and keeping track#
Sometimes there are issues where updates are not where they should be or sorting is not correct. This is due to be a reference to the value in memeory and not to the actual value.
So sometimes we need to bind the :key=
directive
Check if variable is an array#
Array.isArray(value)
The Vue Instance in Detail#
Multiple Vue Instances are allowed, as long as there is no connection between them.
Can store the vue instance in a variable with:
var vm1 = new Vue({
el: "#app1",
data: {
title: "Hello world"
},
methods: {
onChange: function(){
vm1.title = 'Changed!';
}
}
})
Access properties and functions with:
vm1.title = 'Changed by Me';
vm1.onChange();
However Vue JS will not watch or be reactive to properties created from outside the instance:
VueJS doesn’t proxy or watch these properties with getters and setters.
vm1.newProp = 'New!';
Can console.log()
the instance:
console.log(vm1);
Inspecting the Vue Instance#
$el
- refers to instance, the html representation of the instance$data
- holds data properties, a way of accesing the data from outside: eg.vm1.$data.title
$ref
- put theref
key on an attribute (not a directive), set to any name you like. If you consolethis.$refs
. You can access withthis.$this.myButton.text = "Hello world";
. If we access from outside Vue, we are changing in the DOM but not in VueJS. So VueJS will overwrite the change of DOM. Not Reactive
Can create the data variable before Vue Instance and then pass it#
var data = {
title: 'The VueJS Instance',
showParagraph: false
}
var vm1 = new Vue({
el: '#app1',
data: data
})
More info on the API#
Mount#
Properties prefixed by $
are native Vue
js methods and properties.
vm.$mount('#app1`);
You can specify the template of the Vue
instance and not have it derive from the html
with:
var vm3 = new Vue({
template: `<h1>Hello!</h1>'
});
vm3.$mount('#app3');
Can also create it off screen:
vm3.$mount();
//then append it
document.getElementById('app3').appendChild(vm3.$el);
Components#
Creating reusable components are greated with:
Vue.components('hello', {
template: '<h1>Hello!</h1>'
});
Add the new element:
<hello></hello>
<hello></hello>
Limitation of templates: We have to specify everything as a string
Versions#
- Compiler version: respects DOM rules
- No-compiler: compiler is stripped out, compile templates during build process
How Vuejs Updates the DOM#
Each property has it’s own watcher
Accessing the real DOM is the biggest performance bottleneck, so want to do as selodom as posible.
Vue Instance -> Virtual DOM -> DOM
VueJS Instance Lifecycle#
new Vue()
- beforeCreate() - Initialise Data and Events
- created() - Instance Created - Compile template or el’s template
- beforeMount() - before template written to real DOM - replace
el
with compiled template - Mount to DOM
- Data changed
- beforeUpdate()
- updated()
- beforeDestroy()
- destroyed()
These are all fucntions of the Vue Instance:
new Vue({
el: '#app',
data: {
title: 'The Vue Instance'
},
beforeCreated: function() {
console.log('beforeCreated()');
},
created: function() {
console.log('created()');
},
beforeMount: function() {
console.log('beforeCreate()');
},
mounted: function(){
console.log('mounted()');
},
beforeUpdate: function(){
console.log('beforeUpdate()');
},
updated: function(){
console.log('updated()')
},
beforeDestroy: function(){
console.log('beforeDestroy()')
},
destroyed: functino(){
console.log('destroyed()')
}
})
Filters#
Filter helps you transform output in the data Transforms what the user sees
Ie. Turning to uppercase letters
No built-in filters, have to create your own
Local filter:
<p>{{ text || toUppercase }}</p>
export default {
filters: {
'to-uppercase'(value) {
return value.toUpperCase();
}
}
}
Global filter:
Vue.filter('to-lowercase');
Sometimes a computed property is the better solution - performance reasons
Mixins#
Reusable pieces of code
import { fruitMixin } from './fruitMixin';
export default {
mixins: [fruitMixin],
}
A global instance is added to every instance and eery component. Rarely should use this.
Vue.mixin({
created() {
console.log('Global Mixin - Created Hook');
}
});
Mixin Order#
Global Mixins, local mixins then local instance code