LaravelLaravel & VueJsVueJs

4 Essential ES2015 Features For Vue.js Development



ES2015 (aka ES6) is the current specification used by the JavaScript language. If you’re new to JavaScript or haven’t updated your JavaScript knowledge recently, there are a number of new features in ES2015 that make JavaScript development better and more enjoyable.

If you’re a Vue developer, you’d benefit from learning all these features. As a means of triage, you might start with those features that apply to Vue specifically.

In this article, I’ll show you four ES2015 features that you’ll use on a daily basis with Vue, providing a brief example of each:

  1. Arrow functions
  2. Template literals
  3. Modules
  4. Destructuring and spread syntax

1. Arrow functions

Arrow functions are a new way to declare JavaScript functions. They provide a shorter syntax, but differ from regular JavaScript function in other ways, too.

// Regular JavaScript function
function(parameters) {
  statements
}

// Arrow function
(parameters) => {
  statements
}

No bound this

An important feature of arrow functions is that they do not bind a value for this. Instead, they use the this of the enclosing context.

What does that mean? Consider JavaScript array methods that require a callback function. Array.filter, for example, allows you to return a new array only including those items that match the filter defined in the callback.

If you use a regular function for the callback, it will bind its own value for this. You can’t then refer to properties of the Vue object as this.vueProperty from within the callback, you have to manually create them in the scope of the callback.

In the below example, size is a data property. In the fitlerBySize computed property, we declare a variable size and assign the data property to it so that it’s present in the scope of the filter callback:

new Vue({
  data: {
    size: 'large',
    items: [ { size: 'small' }, { size: 'large' } ]  
  },
  computed: {
    filterBySize() {
      let size = this.size;
      return this.items.filter(function(item) {
        return item.size === size;
      });
    }
  }  
});

An arrow function gets this from the enclosing context. In this case, it’s from the filterBySize computed property, which has the Vue object as its this context. This simplifies the filter callback:

filterBySize() {
  return this.items.filter((item) => {
    return item.size === this.size;
  });
}

Gotcha

While arrow functions can be used effectively in many situations, it doesn’t mean we should use them all the time when developing Vue. Indeed, you should never use arrow functions as function properties on Vue configuration object as these need access to the this context from the Vue constructor.

// Regular function

var regular = new Vue({
  data: {
    val: 'Hello world'
  },
  computed: {
    upperCase() {
      return this.val.toUpperCase();
    }  
  }
});

console.log(regular.upperCase); // HELLO WORLD

// Arrow function

var arrow = new Vue({
  data: {
    val: 'Hello world'
  },
  computed: {
    upperCase: () => {
      return this.val.toUpperCase();
    }  
  }
});

console.log(arrow.upperCase);
// Uncaught TypeError: Cannot read property 'toUpperCase' of undefined

Single parameter and implicit return

You can make arrow function syntax even terser in certain scenarios. If you only have one parameter for your function, you can drop the brackets (). If you only have one expression in your function, you can even drop the curly braces {}!

Here’s the array filter callback from above with those shorthands implemented:

filterBySize() {
  return this.items.filter(item => item.size === this.size);
}

See more about Arrow functions on MDN.

★ READ ALSO ★  adminScheduler App: Powered by Electron, Vue.js, and Fullcalendar.io

2. Template literals

Template literals use backticks (“) instead of double or single quotes to define a string.

Template literals allow us to do two super-useful things in Vue.js:

  • Multi-line strings (great for component templates)
  • Embedded expressions (great for computed properties)

Multi-line strings

Writing a template in JavaScript code is not ideal, but sometimes we want/need to. But what if the template has a lot of content? Pre-ES2015, we have two options:

First, put it all on one line:

Vue.component({
  template: '

'
});

This is really hard to read when the line gets long.

Second option: make it multi-line. Due to how JavaScript strings are parsed, you’ll need to break the string at the end of each line and concatenating with a +. This makes the template much harder to read and edit:

Vue.component({
  template: '
' + '

'
+ '

'
+ '
'
});

Template literals solve the problem as they allowing multi-line strings without requiring the string to be broken. See how much easier this is to read:

Vue.component({
  template: `<div>
              <h1></h1>
              <p></p>
            </div>`
});

Embedded expressions

Sometimes we want a string to by dynamic i.e. include a variable. This is very common in computed properties where you may want to interpolate a string in the template which is derived from a reactive Vue.js data property.

Using regular strings, we have to break up the string to insert a variable and join it back together with +. This makes the string hard to read and edit:

new Vue({
  data: {
    name: 'George'
  },
  computed: {
    greeting() {
      return 'Hello, ' + this.name + ', how are you?'
    }
  }
});

By using a placeholder ${} in a template literal, we can insert variables and other expressions without breaking the string. Again, much easier to read:

new Vue({
  data: {
    name: 'George'
  },
  computed: {
    greeting() {
      return `Hello, ${this.name}, how are you?`
    }
  }
});

See more about Template literals on MDN.

3. Modules

How do you load a JavaScript object from one file into another? There was no native way to do it pre-ES2015. Using JavaScript modules, we can do it like this:

file1.js

export default {
  myVal: 'Hello'
}

file2.js

import obj from './file1.js';
console.log(obj.myVal); // Hello

Modules allow us two great benefits:

  1. We can split our JavaScript app up into multiple files
  2. We can make certain code reusable across projects

Component modules

Pre-ES2015, we’d need to put all our component definitions in the one big file including our Vue instance e.g.

app.js

Vue.component('component1', { ... });
Vue.component('component2', { ... });
Vue.component('component3', { ... });

new Vue({ ... });

If we keep doing this, our app.js file will get very large and complicated. Using modules, we can put our component definitions in separate files and achieve better organization, e.g.:

component1.js

export default {
  // component definition
};

We can import this component now in our main file:

app.js

import component1 from './component1.js';
Vue.component('component1', component1);

...

An even better option for modularizing your components is to utilize Single-File Components. These make use of JavaScript modules, but also require a build tool like Webpack. Refer to this article for more info.

See more about JavaScript modules, start here with the import feature.

4. Destructuring and spread syntax

Objects are an essential part of JavaScript development. ES2015 makes it easier to work with object properties with some new syntax

Destructuring assignment

Destructuring allows us to unpack object properties and assign them to distinct variables.

Take this simple object myObj. To assign its properties to new variables, we use the . notation:

let myObj = {
  prop1: 'Hello',
  prop2: 'World'
};

const prop1 = myObj.prop1;
const prop2 = myObj.prop2;

Using destructuring assignment, we can do this more succinctly:

...

const { prop1, prop2 } = myObj;

console.log(prop1);
// Output: Hello

Destructuring is useful in Vuex actions. Actions receive a context object which includes properties for state and the commit API method:

actions: {
  increment (context) {
   // context.state
   // context.commit(...)
  }
}

It’s common, though, that you don’t need the state property in an action, and only the commit API. By using a destructuring assignment in the function profile, you can create a commit parameter for use in the body:

actions: {
  increment ({ commit }) {
    commit(...);
  }
}

Spread syntax

Spreading allows us to expand an object into a place where multiple key/value pairs are expected. Pre-2015, to copy information from one object to another we’d have to do it like this:

let myObj = {
  prop1: 'Hello',
  prop2: 'World'
};

let newObject = {
  name: 'George',
  prop1: myObj.prop1,
  prop2: myObj.prop2
};

console.log(newObject.prop1); // Hello

Using the spread operator (...) we can do this much more succinctly:

let newObject = {
  name: 'George',
  ...myObj
};

console.log(newObject.prop1); // Hello

Taking an example from Vuex again, we often want to use our Vuex state properties inside a component. Pre-ES2015, we’d have to replicate each one manually. For example:

store.js

new Vuex.Store({
  state: {
    prop1: ...,
    prop2: ...,
    prop3: ...
  }
});

To use these state properties as computed properties:

Vue.component('myComponent', {
  computed: {
    prop1() {
      return store.state.prop1;
    },
    prop2() {
      return store.state.prop2;
    }
    ...
  }
});

Vuex provides the mapState fuction which returns an object with all the Vuex state properties that you specify by providing their keys:

import { mapState } from 'vuex';

var state = mapState(['prop1', 'prop2', 'prop3']);
console.log(state.prop1) // { ... }

Combining this with the spread operator, we can combine local computed properties with those from Vuex in a very succinct way:

import { mapState } from 'vuex';

Vue.component('myComponent', {
  computed: {
    someLocalProp() { ... },
    ...mapState(['prop1', 'prop2', 'prop3'])
  }
});

That’s cool! What else?

There are, of course, many other ES2015 features that are useful in Vue.js programming. If you want to keep learning from here, I’d suggest these two as your next topics:

  1. Promises. These help with asynchronous programming and can be used in conjection with Async Components, as well as Vuex actions.
  2. Object.assign. This is not something you’ll directly need very often, but it will help you understand how Vue’s reactivity system works. Vue.js 3.x will likely use the new Proxies feature, so check that out too!

Source link


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Close