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></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>
        
    </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. ``

Can also run methods inside templates eg. ``, 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></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 Propagation
  • prevent - 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.

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"></li>

With an index:

    <li v-for="ingredient, index in ingredients"> ()</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"></span>
    </li>

    <li v-for="person in persons">
        <div v-for="value, key, index in person">:  - ()</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"></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 the ref key on an attribute (not a directive), set to any name you like. If you console this.$refs. You can access with this.$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

VUE API Information

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></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