Categories
Vuetify

Vuetify — Badges and Banners

Vuetify is a popular UI framework for Vue apps.

In this article, we’ll look at how to work with the Vuetify framework.

Badges

The v-badge component lets us add an avatar-like icon or text onto the component to highlight information to the user.

They appear as superscripts or subscripts.

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-toolbar>
          <v-tabs dark background-color="primary" grow>
            <v-tab>
              <v-badge color="pink" dot>One</v-badge>
            </v-tab>

            <v-tab>
              <v-badge color="green" content="6">Two</v-badge>
            </v-tab>

            <v-tab>
              <v-badge color="deep-purple accent-4" icon="mdi-vuetify">Three</v-badge>
            </v-tab>
          </v-tabs>
        </v-toolbar>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",
  data: () => ({
    alert: false,
  }),
};
</script>

We add badges to tab links with the v-tab component.

The color can be changed with the color prop.

icon lets us change the icon.

Show Badge on Hover

We can make a badge shows on hover with the v-hover component.

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-badge
          :value="hover"
          color="deep-purple accent-4"
          content="1000"
          left
          transition="slide-x-transition"
        >
          <v-hover v-model="hover">
            <v-icon color="grey lighten-1" large>mdi-account-circle</v-icon>
          </v-hover>
        </v-badge>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",
  data: () => ({
    hover: undefined,
  }),
};
</script>

to add a badge that shows on hover.

The hover state is controlled by the hover state.

v-model son the v-hover component sets the hover state.

Dynamic Notifications

We can create dynamic notifications with badges.

The content can be controlled with the content prop.

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <div>
          <v-btn class="mx-1" color="primary" @click="messages++">Send Message</v-btn>

          <v-btn class="mx-1" color="error" @click="messages = 0">Clear Notifications</v-btn>
        </div>

        <v-badge :content="messages" :value="messages" color="green" overlap>
          <v-icon large>mdi-email</v-icon>
        </v-badge>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",
  data: () => ({
    messages: 0,
  }),
};
</script>

We have the Send Message button that increments the message state.

This causes the content to update with the latest message value.

Banners

The v-banner component is used as a message for users with 1 to 2 actions.

It can have a single line or multiple lines.

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-banner single-line :sticky="sticky">
          Hello world.
          <template v-slot:actions>
            <v-btn text color="deep-purple accent-4">Get Online</v-btn>
          </template>
        </v-banner>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",
  data: () => ({
    sticky: true
  }),
};
</script>

We have the v-banner component with the single-line prop to display a single line banner.

The sticky controls whether the banner is sticky or not.

Two-Line Banner

We can add a 2 line banner to store more data.

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-banner>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent cursus nec sem id malesuada.
          Curabitur lacinia sem et turpis euismod, eget elementum ex pretium.
          <template
            v-slot:actions
          >
            <v-btn text color="primary">Dismiss</v-btn>
            <v-btn text color="primary">Retry</v-btn>
          </template>
        </v-banner>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

to add a longer message.

The actions slot has the action buttons.

Conclusion

We can add badges and banners to our app with Vuetify.

Categories
JavaScript Best Practices

JavaScript Best Practices — DOM Performance

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some best practices we should follow when writing JavaScript code.

Too Many Interactions with the Host

We shouldn’t interact too much with any DOM objects.

They render slowly and we should reduce the number of interactions that are done.

Too Many Dependencies

If we have too many dependencies, then we should reduce them.

Over the years, many things are added to the JavaScript standard library.

So we don’t have to use 3rd party dependencies to do the same thing.

For instance, Lodash array methods can be replaced with built-in array methods.

3rd party HTTP clients can be replaced with the Fetch API.

Poor Event Handling

To improve performance of event handling, we should use them properly.

We should remove unnecessary loops and unbind unused event handlers with jQuery unbind or plain JavaScript’s removeEventListener to remove them.

Unorganized Code

To make our lives easier, we should organize our code into coherent chunks.

This way, we can find the code later.

Use HTTP/2

HTTP/2 is the latest version of JavaScript and provides many enhancements over the original version.

We’ll see speed improvements if we switch to HTTP/2 server for hosting our site.

Use Pointer References

We should catch our DOM objects in a variable so that we don’t have to get them again from the DOM if we need it later.

We just take the variable and use that.

For instance, we can write:

const fooEl = document.querySelector('.foo');

to get the element with the class foo .

Trim our HTML

We can reduce the number of items that needed to be loaded by reducing the elements on our page.

The fewer we have, the less we need to load, and the faster our page will be.

Use document.getElementById()

We can use getElementById .

Getting things by ID is faster since there’s only one element with a given ID on a page.

This means our browser doesn’t have to check all the nodes to find all the items.

For example, we can write:

const button = document.getElementById('window-minimize-button');

Use document.querySelector()

If we only want to get one element with the given selector, we can use querySelector to get the DOM node with the given selector.

The browser stops looking after the first node with the given selector is found, which makes the lookup faster.

For example, we can write:

`const button = document.`querySelector`('#window-minimize-button');`

Batch our DOM Changes

We should batch our DOM changes so that we won’t rerender multiple times.

This way, our web page would feel faster for the user.

Buffer our DOM

If we have scrollable divs, we can use a buffer to remove items from the DOM that aren’t currently visible in the viewport.

This will save memory usage and DOM traversal.

There are many libraries to help us with this like React Virtualized for React apps.

Conclusion

We can apply various techniques to speed up DOM manipulation.

These can make a big difference in performance.

Categories
JavaScript Best Practices

JavaScript Best Practices — Readability

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some best practices we should follow when writing JavaScript code.

Don’t Use Logical Operators as Statements

We shouldn’t write clever but hard to read code.

For example, something like:

a() || b.foo.bar(); m && c() ? d() : l || m.baz[bee](3);

is impossible to read.

And therefore this should be avoided.

Always Declaring Variables at the Top of Their Scope

We can put variables at the top of their scope:

function calculate() {
  let width, height, length;
  // ...
}

This way, they’re easy to see and we can work with them anywhere.

Repeatedly Used Inline Object Literals

If we have object literals that are repeatedly used with some variation, we can put them in a function.

For example, we can write:

function prepareRequest(mode, updateId, value) {
  const req = {
    mode,
    updateId,
    value,
    uid: genUID()
  };
  //...
}

This way, we can call prepareRequest and use it anywhere.

Complex Inline Regex

Complex inline regex is impossible to read.

For example, if we have:

if (/^((\[^<>()[]\.,;:\s@"\]+(\.\[^<>()[]\.,;:\s@"\]+)\*)|(".+"))@(([\[0-9\]{1,3}\.\[0-9\]{1,3}\.\[0-9\]{1,3}\.\[0-9\]{1,3}\])|((\[a-zA-Z\-0-9\]+\.)+\[a-zA-Z\]{2,}))$/.test(str)) {
  // ...
}

We have no idea what it’s checking.

Instead, we can assign it to variable and then use it like:

const emailRegex = /^((\[^<>()[]\.,;:\s@"\]+(\.\[^<>()[]\.,;:\s@"\]+)\*)|(".+"))@(([\[0-9\]{1,3}\.\[0-9\]{1,3}\.\[0-9\]{1,3}\.\[0-9\]{1,3}\])|((\[a-zA-Z\-0-9\]+\.)+\[a-zA-Z\]{2,}))$/

if (emailRegex.test(str)) {
  // ...
}

Now we know the regex is actually used for checking for a valid email address.

Strict Equality Everywhere

Strict equality just helps us with avoiding issues with automatic data type coercion.

The rules for data type conversion is complex with the == or != operators.

So we should instead use the === and !== operators to check for equality and inequality respectively.

For example, we can write:

if (typeof x === 'string' && x === 'abc') {
  // ...
}

to compare their type and value.

Assuming Truthiness Equals Presence

We shouldn’t assume truthiness means something ins present in an object.

To check if a key is in an object, we should use hasOwnProperty or the in operator.

Instead of writing:

if (!cache[key]) {
  cache[key] = value;
}

We should write:

if (!cache.hasOwnProperty(key)) {
  cache[key] = value;
}

or:

if (!(key in cache)) {
  cache[key] = value;
}

The in operator also checks the prototype for a property.

Commenting Nothing or Commenting Every Little Thing

No comments and commenting on everything are both bad.

Sometimes there are things that need an explanation that isn’t in the code.

However, it’s also bad to make comments on things that are already covered by the code.

Write Something Reliable without Unit Tests

It’s just hard to write something reliable without unit tests.

They definitely give us peace of mind when we’re changing code.

Using Long Names and Being Overly Specific

We shouldn’t have names that are too long and are overly specific.

Names like:

function generateNewtIDForANewRequestCacheItem() {...}
function deleteRequestCacheItemsThatDoNotEqual(value) {...}

They are definitely too long and too specific.

We should definitely find ways to reduce the length of them.

They have lots of extra information we don’t need.

Conclusion

We should take note of some practices to make our code easier to read.

We may go overboard with some good practices as well.

Categories
JavaScript Best Practices

JavaScript Best Practices — Arrays and Exceptions

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some best practices we should follow when writing JavaScript code.

Avoid Using for-in Loop for Arrays

We should avoid using for-in loop for arrays.

For instance, instead of writing:

let sum = 0;
for (let i in arrayNumbers) {
  sum += arrayNumbers[i];
}

We can use a for loop or a for-of loop:

let sum = 0;
for (let a of arrayNumbers) {
  sum += a;
}

or:

let sum = 0;
for (let i = 0, len = arrayNumbers.length; i < len; i++) {
  sum += arrayNumbers[i];
}

A for-in loop is used for iterating through regular objects rather than arrays.

Pass Functions, not Strings, to setTimeout() and setInterval()

We should always pass functions to setTimeout and setInterval .

For example, instead of writing:

setInterval('doSomething()', 1000);
setTimeout('doSomething()', 5000);

We write:

setInterval(doSomething, 1000);
setTimeout(doSomething, 5000);

Use a switch/case Statement Instead of a Series of if/else

switch and case are shorter than a series of if and else .

For example, we can write;

switch (val) {
  case 1:
    //...
    break;
  case 2:
    //...
    break;
  case 3:
    //...
    break;
  case 4:
    //...
    break;
  default:
    //...
}

This is better organized than:

if (val === 1) {
  //...
}
else if (val === 2) {
  //...
}
else if (val === 3) {
  //...
}
else if (val === 4) {
  //...
}
else {
  //...
}

If we have more than 10 cases, we should avoid a series of if and else s.

Use switch/case Statement with Numeric Ranges

We can use switch and case with numeric ranges.

To do that, we can write:

switch (true) {
  case isNaN(age):
    category = "not an age";
    break;
  case (age >= 50):
    category = "old";
    break;
  case (age <= 20):
    category = "kid";
    break;
  default:
    category = "young";
    break;
};

Instead of passing a variable switch , we pass in true .

Also, the case has expressions instead of a value.

Create an Object Whose Prototype is a Given Object

We can create an object whose prototype is the gin object with he Object.create method.

For example, we can write:

const obj = Object.create(proto);

where proto is the prototype object for obj .

An HTML Escaper Function

We can escape HTML with some regex.

For example, we can write:

function escapeHTML(text) {
  const replacements = {
    "<": "&lt;",
    ">": "&gt;",
    "&": "&amp;",
    """: "&quot"
  };
  return text.replace(/[<>&"]/g, (character) => {
    return replacements[character];
  });
}

We search for the brackets, ampersands, and quotes with the regex and then we get the replacement character from the replacements object.

Avoid Using try-catch-finally Inside a Loop

try-catch-finally creates a new variable in the current scope at runtime each time the catch clause is run.

So instead of writing:

let arr = ['foo', 'bar'], i;
for (i = 0, len = arr.length; i < len; i++) {
  try {
    // ...
  } catch (e) {
    // ...
  }
}

We write:

let arr = ['foo', 'bar'],  i;
try {
  for (i = 0, len = arr.length; i < len; i++) {
    // ...
  }
} catch (e) {
  // ...
}

Now the catch clause can only be run once with the 2nd example.

So variables in there can only be created once.

Conclusion

We shouldn’t use for-in loops with arrays.

Also, we can create objects with a prototype with Object.create .

There’re also many things to watch out for with arrays.

Categories
JavaScript Best Practices

Robust JavaScript Best Practices

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some best practices we should follow when writing JavaScript code.

Consider Using try/catch When Using JSON.parse

There’s always a chance that we encounter invalid JSON strings.

So to prevent that from crashing our app when we parse JSON, we should wrap try/catch around our JSON.parse call.

For example, we can write:

try {
  JSON.parse(str);
}
catch(ex) {
  console.error(ex);
}

This way, we won’t crash our app when we try to parse invalid JSON.

Using Classes

Classes are just syntactic sugar above prototypes.

However, it looks more familiar to most people.

And it’s easier to understand than prototypes.

For example, instead of writing:

function Dog(name) {
  this.name = name;
}

Dog.prototype.speak = function() {
  console.log(this.name);
}

We write:

class Dog {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(this.name);
  }
}

They do the same thing, but the 2nd example makes more sense.

We can definitely consider them when we create constructors.

Using Arrow Functions

Arrow functions are useful because they don’t bind to their own this and it’s shorter.

This means it’s handy for arrow functions.

If we don’t need its own this inside the function, we should use arrow functions.

For instance, we can write:

const foo = (msg) => {
  console.log(msg);
};

or:

const init = (msg) => console.log(msg);

to write them.

This makes dealing with JavaScript functions much easier.

Concatenating Strings and Templating

Tenplate strings are great alternatives to concatenation.

We can interpolate expressions in a string without having complex concatenation expressions.

For instance, instead of writing:

const msg = 'I said, "hello' + firstName + ' ' + lastName + '" to the world.';

We can write:

const msg = `I said, "hello ${firstName} ${lastName}" to the world.`;

It’s much cleaner and it’s also a bit shorter.

Destructuring Arrays and Objects

The destructuring syntax it’s another great JavaSctipt feature.

Before the destructuring syntax existed, destructuring array entries to variables is a lot harder.

We’ve to write:

const arr = [1, 2, 3, 4];
const a = arr[0];
const b = arr[1];
const c = arr[2];
const d = arr[3];

to assign each entry to its own variable.

With the destructuring syntax, it’s much shorter:

const [a, b, c, d] = [1, 2, 3, 4];

With objects, instead of writing:

const obj = { foo: 1, bar: 2, baz: 3 };
const foo = obj.foo;
const bar = obj.bar;
const baz = obj.baz;

We write:

const { foo, bar, baz } = { foo: 1, bar: 2, baz: 3 };

It’s much simpler.

Componentizing Our Code

We can organize our code into modules.

To do that, we just create JavaSctipt files that has export statements.

For example, we can write:

bar.js

export const foo = 66;

Then we can import it by writing:

import { foo } from 'bar';

It’s much easier than using scripts with a bunch of global variables, which can easily be overwritten.

It’s a basic building block of JavaScript apps.

Conclusion

We can use modern JavaScipt constructs like the class syntax, modules, and destructuring to make our lives easier.