Categories
JavaScript Vue

Using a For Loop with Vuejs

We can render lists by using a for loop with Vuejs.

The for loop equivalent in Vuejs is the v-for directive.

To use it, we can write;

<ul id="example">
  <li v-for="item in items" :key="item.name ">
    {{ item.name }}
  </li>
</ul>

and:

const example = new Vue({
  el: '#example',
  data: {
    items: [
      { name: 'Foo' },
      { name: 'Bar' }
    ]
  }
})

We have an items array with the list items to render

Then we use v-for with the items array to render them items.

We need the key prop with a unique value for each entry for Vuejs to identify the entries properly.

We can also add the index by changing our v-for for loop.

For instance, we can write:

<ul id="example">
  <li v-for="(item, index) in items">
    {{ index }} - {{ item.name }}
  </li>
</ul>

and:

const example = new Vue({
  el: '#example',
  data: {
    parentMessage: 'Parent',
    items: [
      { name: 'Foo' },
      { name: 'Bar' }
    ]
  }
})

index has the index of the array.

We can also loop through objects.

For instance, we can write:

<ul id="v-for-object">
  <li v-for="value in object">
    {{ value }}
  </li>
</ul>

and

new Vue({
  el: '#v-for-object',
  data: {
    object: {
      name: 'james'.
      age: 20,
      gender: 'male'
    }
  }
})

We loop through the keys of the object in our Vuejs app with the same for loop.

value has the property value.

We can also add the property name and index to the loop.

For instance, we can write:

<div v-for="(value, name) in object">
  {{ name }}: {{ value }}
</div>

value is the property value and name is the property name.

We can also add the index to our Vuejs for loop by writing:

<div v-for="(value, name, index) in object">
  {{ index }}. {{ name }}: {{ value }}
</div>

We can create a Vuejs for loop that display numbers by writing a number after the in instead of an array or object.

For instance, we can write:

<div>
  <span v-for="n in 100">{{ n }} </span>
</div>

We can v-for with a `template component to render multiple items.

For instance, we can write:

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li><hr /></li>
  </template>
</ul>

to render multiple items in each iteration of the v-for Vuejs for loop.

The Vuejs equivalent of a for loop is the v-for directive.

We can use it to render objects and array entries on the screen.

Also, we can use it to loop through a range of numbers and display them.

Categories
JavaScript JavaScript Best Practices

More JavaScript Habits we can Follow

To make code easy to read and maintain, we should follow some best practices.

In this article, we’ll look at some best practices we should follow to make everyone’s lives easier.

No Reassigning Exceptions in catch clauses

We shouldn’t reassign the error object in the catch clause.

Instead, we should assign it to a new variable to ensure that we don’t lose any information.

For instance, instead of writing:

try {
  // ..
} catch (e) {
  e = 10;
}

We write:

try {
  // ...
} catch (e) {
  const foo = 10;
}

No Unnecessary Boolean Casts

If we already have a boolean variable, then e don’t need to cast it again.

For instance, instead of writing:

var foo = !!!bar;

var foo = !!bar ? baz : bat;

var foo = Boolean(!!bar);

var foo = new Boolean(!!bar);

We write:

var foo = !bar;

var foo = bar ? baz : bat;

var foo = Boolean(bar);

var foo = new Boolean(bar);

Boolean and !! already does the casting so we don’t have to do it again.

No Innecessary Parentheses

We shouldn’t have extra parentheses in our code.

For instance, instead of writing:

a = (b * c);

(a * b) + c;

We write:

a = b * c;

a * b + c;

We skip them to save some typing and make them easier to read.

No Unnecessary Semicolons

We shouldn’t have more semicolons than it’s necessary.

For example, instead of writing:

var x = 10;;

function foo() {
  // code
};

We write:

var x = 10;

function foo() {
    // code
}

No Reassigning Function Declarations

We shouldn’t reassign function declarations.

Instead, we assign whatever we want to assign to a new variable.

For instance instead of writing:

function foo() {}
foo = bar;

We write:

var foo = function () {}
foo = bar;

If we create a function, then keep it a function.

No Assignment to Imported Bindings

If we have imported bindings, then we should use it directly or as to rename it.

Otherwise, we assign what we have to a new variable and then work with it.

For instance, we write:

import mod from "./mod"

mod.prop = 1;

And not:

import mod from "./mod"

mod = 1;

No Variable or Function Declarations in Nested Blocks

We shouldn’t have function declarations in nested blocks.

It’s invalid syntax even though it’s accepted.

For instance, instead of writing:

if (test) {
    function doWork () { }
}

We write:

function doWork () { }

We can also write nested declarations:

function doSomething() {
  function doAnotherThing() {}
}

Conclusion

We shouldn’t use invalid syntax.

Also, redundant code is bad.

Extra parentheses should be removed to save us typing and space.

Categories
JavaScript JavaScript Best Practices

Removing Useless Expressions – JavaScript Best Practices

To make code easy to read and maintain, we should follow some best practices.

In this article, we’ll look at some best practices we should follow to make everyone’s lives easier.

No Constant Expressions in Conditions

We shouldn’t have constant expressions in conditions.

They either always run or never run if they’re present.

For instance, don’t write:

if (false) {
   foo();
}

Instead, write:

if (x === 1) {
   foo();
}

No Control Characters in Regex

We shouldn’t have control characters in a regex.

They are rarely used and it’s probably a mistake to check for them.

Instead of writing:

const pattern = /\x1f/;

or:

const pattern = new RegExp("\x1f");

We write:

const pattern1 = /\x20/;
const pattern2 = new RegExp("\x20");

instead.

Don’t Use debugger

debugger sets a breakpoint in our JavaScript code so we can inspect the variables.

This shouldn’t be in our production code.

So instead of writing:

const isTruthy = (x) => {
  debugger;
  return Boolean(x);
}

We write:

const isTruthy = (x) => {
  return Boolean(x);
}

No Duplicate Arguments in Function Definitions

Duplicate argument names isn’t valid syntax.

It’ll throw an error if strict mode is on.

Instead of writing:

function foo(a, b, a) {
  console.log(a);
}

We write:

function foo(a, b) {
  console.log(a);
}

No Duplicate if-else-if Conditions

We shouldn’t have duplicate conditions in our if statements.

The duplicate is useless and causes confusion.

So instead of writing:

if (isSomething(x)) {
  foo();
} else if (isSomething(x)) {
  bar();
}

We write:

if (isSomething(x)) {
  foo();
}

No Duplicate Keys in Object Literals

Duplicate keys are confusing and useless.

So we shouldn’t write:

const foo = {
   bar: "baz",
   bar: "qux"
};

Instead, we write:

const foo = {
   bar: "qux"
};

No Duplicate case Label

switch statements shouldn’t have more than one case label.

As with other duplicates, they cause confusion and are redundant.

So instead of writing:

switch (a) {
  case 1:
    break;
  case 2:
    break;
  case 1:
    break;
  default:
    break;
}

We write:

switch (a) {
  case 1:
    break;
  case 2:
    break;
  default:
    break;
}

No Empty Block Statements

Empty blocks are useless. So we should remove them.

Instead of writing:

if (foo) {
}

or

while (foo) {
}

or

switch(foo) {
}

We write:

if (foo) {
  bar();
}

or

while (foo) {
  bar();
}

or:

switch(foo) {
  case 1:
    //...
    break;
}

Conclusion

We shouldn’t have duplicates of most things.

Also, we should remove control characters from regexes and debugger.

Categories
JavaScript JavaScript Best Practices

Basic JavaScript Best Practices

To make code easy to read and maintain, we should follow some best practices.

In this article, we’ll look at some best practices we should follow to make everyone’s lives easier.

Having the Correct for Loop Direction

We should make sure that we update the index variable in the right direction so that we don’t get infinite loops.

For instance, the following is probably wrong:

for (var i = 0; i < 10; i--) {
}

The loop never ends since i is being decremented in each iteration.

Instead, we should write:

for (var i = 0; i < 10; i++) {
}

so that the i variable gets to 10.

Return Statement should be Present in Property getters

If we define a getter, then we should return something.

Otherwise, the getter is useless.

For instance, instead of writing:

const obj = {
  get name() {
    
  }
};

We write:

const obj = {
  get name() {
    return 'james'  
  }
};

or:

 Object.defineProperty(person, "age", {
   get() {
     return 17;
   }
 });

No async Function as a Promise Executor

We shouldn’t have async functions in our Promise constructor.

This is because async functions already returns promises, so it’s redundant.

For instance, we shouldn’t write;

const result = new Promise(async (resolve, reject) => {
  resolve(await foo);
});

or:

const foo = new Promise(async (resolve, reject) => {
  readFile('bar.txt', (err, result) => {
    if (err) {
      reject(err);
    } else {
      resolve(result);
    }
  });
});

It’s completely redundant to have them.

Instead, we write:

const foo = new Promise((resolve, reject) => {
  readFile('bar.txt', (err, result) => {
    if (err) {
      reject(err);
    } else {
      resolve(result);
    }
  });
});

or:

const result = Promise.resolve(1);

No await Inside Loops

We should move await outside of promises that can run in parallel.

So instead of writing:

copnst foo = async (things) => {
  const results = [];
  for (const thing of things) {
    results.push(await bar(thing));
  }
  return baz(results);
}

We write:

const foo = async (things) => {
  const results = things.map(thing =>bar(thing));
  return baz(await Promise.all(results));
}

We map the things entries to promises.

Then we use Promise.all to run all the promises in parallel.

No Comparison Against -0

Comparing against -0 won’t work as intended.

Instead, we compare an expression with 0.

So instead of writing:

if (x === -0) {
  //...
}

We write:

if (x === 0) {
  //...
}

We can use Object.is to compare against -0:

if (Object.is(x, -0)) {
  // ...
}

Object.is distinguishes between +0 and -0.

No Assignment Operators in Conditional Statements

Assinging things in operators is probably a mistake if we don’t compare it against something.

For instance:

if (user.title = "employee") {
  //...
}

isn’t comparing user.title to 'employee'.

Instead, we write:

if (x === 0) {
   b = 1;
}

to make sure we’re comparing against an expression.

Remove console from Production Code

We shouldn’t run console.log when our code goes to production.

Therefore, we should remove them.

It’s good for debugging but we should remove them before we check in our code.

Conclusion

We should take note of some basic best practices when writing JavaScript code.

Don’t use async and await with the Promise constructor.

Don’t write infinite loops unintentionally.

And return things in getters.

Also, don’t assign variables unintentionally in our if statements.

Categories
JavaScript Vue

Vue Components — Dynamic and Async Components

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at how to define and use dynamic and async components.

keep-alive with Dynamic Components

We sometimes want to maintain the state or avoid re-rendering for performance reasons when we switch between components dynamically.

For example, we can use it as follows to keep the states of components when switching between them:

src/index.html :

Vue.component("post", {  
  data() {  
    return {  
      showDetails: false  
    };  
  },  
  template: `  
    <div>  
      <h1>Title</h1>  
      <button @click='showDetails = !showDetails'>  
        Toggle Details  
      </button>  
      <div v-if='showDetails'>  
        Lorem ipsum dolor sit amet.  
      </div>  
    </div>  
  `  
});

Vue.component("archive", {  
  data() {  
    return {  
      showDetails: false  
    };  
  },  
  template: `  
    <div>  
      <h1>Archive</h1>  
    </div>  
  `  
});

new Vue({  
  el: "#app",  
  data: {  
    tabName: "post"  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <button @click'tabName = "post"'>Post</button>  
      <button @click='tabName = "archive"'>Archive</button>  
      <keep-alive>  
        <component v-bind:is="tabName"></component>  
      </keep-alive>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then when we click Toggle Detail to show the text in the Post tab, we’ll see that it’ll still be shown after switching to the Archive tab and back.

This is because we wrapped keep-alive around our component element.

keep-alive requires that the components being switched between to all have names.

Async Components

We can create components that are loaded from the server only when it’s needed with async components.

To do this, instead of passing in an object as the second argument, we pass in a function that returns a promise instead. For example, we can write the following:

src/index.js :

Vue.component("async-component", (resolve, reject) => {  
  setTimeout(() => {  
    resolve({  
      template: "<div>Async component</div>"  
    });  
  }, 1000);  
});

new Vue({  
  el: "#app"  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <async-component></async-component>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then we should see ‘Async component’ shown on the screen after 1 second.

We see that the function above takes a resolve function from the parameter and calls it when we want to retrieve the definition from the server.

To indicate loading has failed, we can call reject(reason) to do that.

Another example would be using it with Webpack code-splitting as follows:

Vue.component('async-webpack', function (resolve) {  
  require(['./async-component'], resolve)  
})

We can also use the import function to import a component as follows:

Vue.component(  
  'async-webpack',  
  () => import('./async-component')  
)

If we want to register a component locally, we can write:

new Vue({  
  // ...  
  components: {  
    'component': () => import('./async-component')  
  }  
})

Handling Loading State

We can return a promise that has an object to referencing components for loading and error.

For example, we can use it with an app that’s generated by the Vue CLI by running npx vue create app where app is the app name. Then we can select the default choices within the wizard.

Then we write the code as follows:

App.vue :

<template>  
  <div id="app">  
    <AsyncComponent/>  
  </div>  
</template>

<script>  
import Loading from "./components/Loading";  
import Error from "./components/Error";  
import HelloWord from "./components/HelloWorld";

const AsyncComponent = () => ({  
  component: new Promise(resolve => {  
    setTimeout(() => {  
      resolve(HelloWord);  
    }, 1000);  
  }),  
  loading: Loading,  
  error: Error,  
  delay: 0,  
  timeout: 3000  
});

export default {  
  name: "App",  
  components: {  
    AsyncComponent  
  }  
};  
</script>

<style>  
</style>

components/HelloWorld.vue :

<template>  
  <div>Hello</div>  
</template>

components/Error.vue :

<template>  
  <div>Error</div>  
</template>

component/Loading.vue :

<template>  
  <div>Loading</div>  
</template>

In App.vue , the following code:

component: new Promise(resolve => {  
    setTimeout(() => {  
      resolve(HelloWord);  
    }, 1000);  
  })

delays loading of the HelloWorld component for a second. delay is the number of milliseconds before the loading component is shown.

timeout is the number of milliseconds until Vue stops trying to load the component.

Therefore, we’ll see Loading from the Loading component as the HelloWorld component is loading.

This kind of component definition is available since Vue 2.3.0. Vue Router 2.4.0 should be used if we want to use the above syntax for route components.

Conclusion

We can use keep-alive to keep the current state of the component as it’s being rendered dynamically with the component element.

We can define async components with Vue.component by passing in a function that returns a promise.

In Vue 2.3.0 or later, we can define an async component by creating a function that returns an object that has the promise that resolves to the component as the component that’s rendered.

We can also specify the Loading and Error components in addition to the delay for loading the Loading component and timeout until Vue stops trying to load the component.