Categories
Vue Best Practices

Vue Best Practices— Props, Spacing, and Naming

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 some best practices for props, spacing, and naming.

Proo Name Casing

In Vue apps, props should be named in a consistent way.

They should be valid JavaScript identifier names in camelCase.

For instance, we should write:

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

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String
  }
};
</script>

The prop name is msg which is a valid JavaScript identifier name.

Default Props

Having default props is a good idea.

This way, if we forget to pass in a prop, then we still have a default value set for our prop.

For instance, we can write:

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

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: {
      type: String,
      default: "hello"
    }
  }
};
</script>

We added a default field to our prop object.

Now if we don’t have anything passed in for the msg prop then it’s set to the 'hello' prop.

Prop Types

We can add prop types to our Vue component prop so that we won’t have props with the wrong type passed in.

For instance, we can write:

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

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String
  }
};
</script>

Then the msg prop would always be a string.

If it’s not, we’ll get an error.

Put HTML Element Content in a New Line

If we have HTML elements content, then we can put them in a new line.

For instance, we can write:

<template>
  <tr>
    <td>{{ foo }}</td>
    <td>{{ bar }}</td>
  </tr>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      foo: 1,
      bar: 2
    };
  }
};
</script>

Then we have 2 td elements in their own line.

It’s easier to read to have them in their own line.

v-bind Directive Style

We can use : instead of v-bind to save us some typing.

For example, we can write:

<template>
  <HelloWorld :msg="msg"/>
</template>

<script>
import HelloWorld from "./components/HelloWorld";

export default {
  name: "App",
  components: {
    HelloWorld
  },
  data() {
    return {
      msg: "hi"
    };
  }
};
</script>

We have :msg which is short for v-bind .

We save typing by using the shorthand.

v-on Style

We can use @ instead of v-on . For instance, we can write:

<template>
  <button @click="onClick">click me</button>
</template>

<script>
export default {
  name: "App",
  methods: {
    onClick() {
      alert('hello')
    }
  }
};
</script>

@ is short for v-on:click .

We save typing by using the shorthand.

Use of v-html

We should be careful when we use v-html so that we don’t let attacks execute cross-site scripting attacks.

We should avoid it as much as possible and escape anything that may have code in it.

this in Template

this is Vue templates shouldn’t be used. It’s probably added as a mistake from copy and pasting in most cases.

For instance, instead of writing:

<a :href="this.url">link</a>

We should write:

<a :href="url">link</a>

Array Brackets Spacing

In our Vue apps, we should have array brackets spacing so that they’re easy to read.

For instance, we can write:

const arr = ['foo', 'bar'];

Arrow Spacing

Arrow functions should have consistent spacing.

For instance, we should write:

const fn = () => {
  //...
}

We have one space before and after the arrow.

Block Spacing

Block spacing should be consistent so that we can write:

const fn = () => {
  //...
}

We have 2 spaces for indentation.

Brace Style

We should put the opening brace on the same line as the declaration.

For instance, we should write:

if (foo) {
  baz();
} else {
  bar();
}

We have the opening brace after the closing parentheses for the if and else for the else block.

camelCase

camelCase should be used for declaring variables.

This is a commonly accepted convention so we should use it for consistency.

For instance, we write:

let fooBar = 1;

Conclusion

We should use camelCase for prop names and variables.

Spacing should be consistent throughout our code.

Default props and prop type validation are also good things to add to prevent errors.

Categories
Vue Best Practices

Vue Best Practices — Recommended Syntax

Vue is an easy front end framework to work with. It lets us create apps easily.

However, there are still many things that we should look out for when we write apps with them.

In this article, we’ll look at the best practices for using the recommended syntax.

Attribute Hyphenation

We can hyphenate our attributes so that it’s consistent with HTML attributes.

For instance, we can write:

<FooComponent foo-prop="prop" />

instead of:

<FooComponent fooProp="prop" />

Component Name Casing

Names for components should be PascalCase or kebab case.

Vue can translate between either case.

For instance, we can write:

<FooComponent />

or:

<foo-component />

Closing HTML Brackets in a New Line

Having closing HTML brackets in a new line makes it easier to change and read.

Therefore, we may consider putting them on a new line.

For instance, we can write:

<div  
  id="foo"  
  class="bar"  
>   
  <!-- //... -->  
</div>

instead of writing:

<div  
  id="foo"  
  class="bar">   
  <!-- //... -->  
</div>

No Space Before Closing Bracket Tags

We shouldn’t have space before closing bracket tags.

For instance, we shouldn’t have:

<div ></div>

Instead, we write:

<div></div>

HTML End Tags

We should have end tags for non-self-closing tags.

For instance, we should write:

<div></div>

instead of:

<div>

Indentation

We should have some indentation in our HTML.

It makes the code easier to read and change.

For instance, we can write:

<div class="bar">  
  Hello.  
</div>

Quotes

Quotes should be added to HTML attribute values.

For instance, we can write:

<img src="./photo.png">

or:

<img src='./photo.png'>

Single or double quotes are both fine.

This way, we won’t have syntax errors when we’re passing props instead of setting HTML attribute values.

Self-Closing Tags

If a component doesn’t have any content, it can either be self-closing or not.

The self-closing syntax isn’t supported in HTML spec, so we shouldn’t use it when we’re writing Vue code without a build step.

For instance, we can write:

<BarComponent></BarComponent>

which isn’t self-closing or:

<BarComponent />

which is self-closing.

Maximum Number of Attributes Per Line

We don’t want to have so many attributes in a line that people have to scroll horizontally to read everything.

Therefore, we may want to limit the attributes in one line.

For instance, we may want to have one attribute per line, so we write:

<FooComponent  
  foo="1"  
  bar="2"  
  baz="3"  
/>

HTML Content Newline

HTML content should be in its own line in between the tags.

This way, we know where the content exactly is without looking too hard.

For instance, we can write:

<div>  
  multiline  
  content  
</div>

Mustache Interpolating Spacing

We should have some space between the mustache and the expression that’s inside it.

It’s easier to read if we have one space character before and after the expression.

For instance, we can write:

<div>{{ msg }}</div>

This way, the expressions are easy to find.

No Multiple Spaces

Having a bit of space is good, but we shouldn’t have too many spaces since it’s just a waste of screen real estate.

For instance, the following is good”

<i  
  :class="{  
    'fa-angle-up': isExpanded,  
    'fa-angle-down': !isExpanded,  
  }"  
/>

There’s one space after the colon, which is enough to make the keys and value easy to read.

No Spaces Around Equal Signs in Attribute

HTML5 allows space around equal signs, but it’s easier to read without the spaces and they’re grouped better without the spaces.

Therefore, we write:

<div class="foo"></div>

instead of:

<div class = "foo"></div>

No Template Variable Shadowing

We shouldn’t have variable declarations in a nested element or component that’s identical to the variable declaration in the outer element or component.

For instance, we shouldn’t have something like the following:

<div>  
  <div v-for="x in 5">  
    <div v-for="x in 10"></div>  
    <div slot-scope="{ x }"></div>  
  </div>  
</div>

We have x that’s both declared in the outer v-for and the inner one.

That will just confuse Vue and ourselves.

We should name them differently and reduce nesting whenever possible.

So we should write:

<div>  
  <div v-for="a in 5"></div>  
  <div v-for="b in 10"></div>  
</div>

Conclusion

There are lots of syntax errors that we should avoid in templates.

Also, the formatting of the attributes can be better by sticking to spacing and indentation conventions.

Categories
Vue Best Practices

Vue Best Practices — Directives

Vue is an easy front end framework to work with. It lets us create apps easily.

However, there are still many things that we should look out for when we write apps with them.

In this article, we’ll look at the best practices for using directives.

Make Sure v-html is Valid

When we use the v-html directive, we shouldn’t have any modifiers added to it.

And we should have an argument with the expression that stores the HTML code as a string.

For instance, we can write:

<div v-html="foo"/>

where foo is a variable.

Make Sure that v-if is used Properly

v-if shouldn’t have modifiers.

But it should have an argument with the expression to check whether to display anything.

For instance, instead of writing:

<div v-if:abc="foo"/>

or:

<div v-if/>

We write:

<div v-if="foo"/>

Make Sure v-model is Used Properly

v-model may have some modifiers.

The argument is also required so that it binds to the variable indicated in the argument.

Also, they should be added to input controls.

For instance, we can write:

<input v-model="foo">

or:

<input v-model.lazy="foo">

Make Sure that we use v-on Properly

v-on should be used properly to bind to variables.

It can have arguments to run an event handler when an event is triggered.

Also, it can have no arguments to pass events from a child to a parent.

For instance, we can write:

<div v-on="foo"/>

or:

<div v-on:click="foo"/>

@ is short for v-on , so we can write:

<div @click="foo"/>

or:

<div @click.right="foo"/>

where foo is the event handler to run.

Make Sure that v-once is used Properly

v-once indicates that a component or element should only be rendered once.

It takes no arguments or modifiers.

The element or component will be treated as static elements on subsequent rendered.

For instance, we use it by writing:

<div v-once/>

Using v-pre Properly

v-pre is another directive that doesn’t take any argument or modifiers.

It’s used to skip compilation for the element with this directive and all its children.

Therefore, we can use it to display raw Vue or other kinds of code.

We use it by writing:

<span v-pre>{{ raw code }}</span>

Make Sure we use v-show Properly

v-show is used to display something conditionally by showing or hiding it with CSS.

It takes an argument with the boolean expression that’s checked for displaying something if it returns true .

For instance, we use it by writing:

<div v-show="foo"/>

Using v-text Properly

The v-text is equivalent to the mustache for interpolating expression within an element.

It takes an argument for the expression return value to display.

For instance, we can write:

<span v-text="msg"></span>

Which is the same as:

<span>{{msg}}</span>

No Custom Modifiers on v-model

v-model only takes a few modifiers.

It can take a few modifiers like trim to trim leading and trailing whitespaces.

lazy for lazy evaluation.

And number to convert the inputted value to a number.

However, it doesn’t accept any custom modifiers.

So to use v-model properly, we write:

<input v-model="foo" />

or:

<input v-model.trim="foo" />

or:

<input v-model.lazy="foo" />

or:

<input v-model.number="foo" />

No Multiple Template Root

Our template should only have one root element.

Otherwise, Vue will throw an error.

For instance, we can write:

<template>foo bar</template>

But we can’t write something like:

<template>
  <div v-for="todo in todos"/>
</template>

since it renders multiple items.

Instead, we write:

<template>
  <div>
    <div v-for="todo in todos"/>
  </div>
</template>

v-bind.sync should be Used Properly

v-bind.sync needs to be used properly.

v-bind.sync doesn’t need a value prop in the child.

It uses the same prop as we have in the parent.

For instance, we can use it as follows:

App.vue

<template>
  <div id="app">
    <Input :msg.sync="msg"/>
    <p>{{msg}}</p>
  </div>
</template>

<script>
import Input from "./components/Input";

export default {
  name: "App",
  components: {
    Input
  },
  data() {
    return {
      msg: "Hello Vue!"
    };
  }
};
</script>

Input.vue

<template>
  <input :value="msg" @input="$emit('update:msg', $event.target.value)">
</template>

<script>
export default {
  name: "Input",
  props: {
    msg: String
  }
};
</script>

:msg.sync passes the value of msg to the child and allows it to emit some with update: name.

We have the value prop set to the msg prop value passed from the parent in Input.vue .

Then we emit an update:msg event to emit msg back to the parent.

Now when we type on the screen, we’ll see what we typed displayed.

Conclusion

Making sure that we use Vue directives properly is a big part of writing Vue apps that don’t have bugs.

We should make sure that the syntax is correct and no typos in our modifiers or arguments if they’re included.

Categories
Vue Best Practices

Vue Best Practices — Props and Computed Properties

Vue is an easy front end framework to work with. It lets us create apps easily.

However, there are still many things that we should look out for when we write apps with them.

In this article, we’ll look at some essential rules that we should follow when we’re building our Vue apps.

Require Valid Default Prop

We should have a default prop value for our props to prevent issues that arise if we forgot to pass in a prop.

Also, we should make sure that the default prop type matches the type of the prop specified.

For instance, instead of writing:

<template >  
  <div id="app"></div>  
</template>  
<script>  
export default {  
  name: "App",  
  props: {  
    propA: {  
      type: String,  
      default: {}  
    }  
  }  
};  
</script>

We write:

<template >  
  <div id="app"></div>  
</template>  
<script>  
export default {  
  name: "App",  
  props: {  
    propA: {  
      type: String,  
      default: "foo"  
    }  
  }  
};  
</script>

A Computed Property Should Return Something

Computed property functions should always return something.

For instance, instead of writing:

<template >  
  <div id="app"></div>  
</template>  
<script>  
export default {  
  name: "App",  
 computed: {  
   foo(){  
     if (Math.random() < 0.5){  
       return 'foo'  
     }  
   }  
 }  
};  
</script>

We should write:

<template >  
  <div id="app"></div>  
</template>  
<script>  
export default {  
  name: "App",  
  computed: {  
    foo() {  
      return "foo";  
    }  
  }  
};  
</script>

Add the exact Modifier on v-on When There are Multiple v-on Directives

If there’s another v-on handler in our component or element, then we should add the exact modifier to the directive so that only the given event is handled.

For instance, instead of writing:

<template >  
  <div id="app">  
    <button v-on:click="onClick" v-on:click.ctrl="onClick"></button>  
  </div>  
</template>  
<script>  
export default {  
  name: "App",  
  methods: {  
    onClick() {  
      //...  
    }  
  }  
};  
</script>

We write:

<template >  
  <div id="app">  
    <button v-on:click.exact="onClick" v-on:click.ctrl="onClick"></button>  
  </div>  
</template>  
<script>  
export default {  
  name: "App",  
  methods: {  
    onClick() {  
      //...  
    }  
  }  
};  
</script>

Template Should be the Root of the Component Template

We should make sure that we don’t have extra things in our template element.

For instance, instead of writing:

<template v-if'foo'>  
  <div id="app"></div>  
</template>  
<script>  
export default {  
  name: "App"  
};  
</script>

We wrote:

<template>  
  <div id="app"></div>  
</template>  
<script>  
export default {  
  name: "App"  
};  
</script>

Make Sure the v-bind is Valid

v-bind is valid if it has an attribute and has no invalid modifiers.

For instance, we shouldn’t have:

<div v-bind/>

or:

<div v-bind:cc.bbb="foo"/>

Instead, we write:

<div v-bind="foo"/>

or:

<div :aaa="foo"/>

or:

<div v-bind:aaa="foo"/>

assuming that aaa exists.

Make Sure that v-cloak is Valid

A valid v-cloak directive doesn’t have arguments or modifiers.

So we should write:

<div v-cloak/>

Anything else isn’t valid.

Make Sure that v-else-if is Valid

A valid v-else-if can’t have modifiers.

Also, it must have an attribute value.

It must go after an element with v-if as its sibling.

For instance, instead of writing:

<div v-else-if/>

or:

<div v-else-if:aaa="bar"/>

We write:

<div v-if="foo"/>     
<div v-else-if="bar"/>

Make Sure that v-else is Valid

v-else shouldn’t have any arguments or modifiers.

It must go after an element with v-if or v-else-if as its sibling.

For instance, we should write:

<div v-if="bar"/>     
<div v-else/>

instead of:

<div v-else:aaa/>     
<div v-else.bbb/>

Make Sure Our v-for Directive is Valid

A v-for directive should have an argument, but no modifiers.

Also, we need to add the key prop to elements rendered by v-for .

For instance, instead of writing:

<div v-for/>

or:

<div v-for.c="todo in todos"/>

We write:

<div       
  v-for="todo in todos"       
  :key="todo.id"     
/>

The :key prop or v-bind:key directive is required.

Conclusion

We should make sure that our directives are used properly.

If they need modifiers or arguments, then we add them. Otherwise, we don’t.

If we have multiple v-click directives, then we need the exact modifier on the broader one so that the other one can pick up the specified user events.

v-for directives shouldn’t have modifiers but it should have arguments.

Categories
Vue Best Practices

Vue Best Practices — Templates and Variables

Vue is an easy front end framework to work with. It lets us create apps easily.

However, there are still many things that we should look out for when we write apps with them.

In this article, we’ll look at some essential rules that we should follow when we’re building our Vue apps.

No Unused Components

We shouldn’t have unused components lying around in our project.

So instead of writing:

<template >
  <div id="app"></div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
  name: "App",
  components: {
    HelloWorld
  }
};
</script>

We should write:

<template >
  <div id="app">
    <HelloWorld/>
  </div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
  name: "App",
  components: {
    HelloWorld
  }
};
</script>

No Unused Variable Definitions in v-for

When we define a v-for loop, we should use all the variables that are defined.

For instance, instead of writing:

<template >
  <div id="app">
    <ol v-for="i in 5">
      <li>foo</li>
    </ol>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

We should write:

<template >
  <div id="app">
    <ol v-for="i in 5">
      <li>{{ i }}</li>
    </ol>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Don’t Use v-if and v-for Together

v-for and v-if shouldn’t be used together since it’s slower than using computed properties.

We should use competed properties to render fewer items rather than using v-if to check if each item should be rendered.

For instance, instead of writing:

<template >
  <div id="app">
    <ul v-for="a in arr" v-if="a % 2 === 0" :key="a">
      <li>{{ a }}</li>
    </ul>
  </div>
</template>
<script>
export default {
  name: "App",
  data() {
    return {
      arr: [1, 2, 3, 4, 5]
    };
  }
};
</script>

We write:

<template>
  <div id="app">
    <ul v-for="a in evenNums" :key="a">
      <li>{{ a }}</li>
    </ul>
  </div>
</template>
<script>
export default {
  name: "App",
  computed: {
    evenNums() {
      return this.arr.filter(a => a % 2 === 0);
    }
  },
  data() {
    return {
      arr: [1, 2, 3, 4, 5]
    };
  }
};
</script>

Add the is Prop to the Component component

To display components dynamically, we’ve to use the component component to display items.

The is prop sets the name of the com[onent to display.

For instance, instead of writing:

<template >
  <div id="app">
    <component/>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

We write:

<template >
  <div id="app">
    <component :is="name"></component>
  </div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
  components: {
    HelloWorld
  },
  name: "App",
  data() {
    return {
      name: "HelloWorld"
    };
  }
};
</script>

Prop Types Should be a Constructor

We should put constructors as the values of the props property to make sure that they’re an instance of some constructor.

For instance, instead of writing:

<template >
  <div id="app"></div>
</template>
<script>
export default {
  name: "App",
  props: {
    name: "String"
  }
};
</script>

We should write:

<template >
  <div id="app"></div>
</template>
<script>
export default {
  name: "App",
  props: {
    name: String
  }
};
</script>

It can also be an array if our prop can more than one type:

<template >
  <div id="app"></div>
</template>
<script>
export default {
  name: "App",
  props: {
    name: [String]
  }
};
</script>

A Render Function Should Return Something

A render function should return something that we want to render.

For instance, instead of writing:

Vue.component("hello", {
  render(createElement) {
    if (Math.random() < 0.5) {
      return createElement("div", "hello");
    }
  }
});

We should write:

Vue.component("hello", {
  render(createElement) {
    return createElement("div", "hello");
  }
});

We make sure that a render function always returns something.

Add a key Prop to Items Rendered by v-for

We need the key prop to anything that’s rendered by v-for so that Vue can keep track of it properly.

For instance, we should write:

<template >
  <div id="app">
    <div v-for="a in 5">{{a}}</div>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

We write:

<template >
  <div id="app">
    <div v-for="a in 5" :key="a">{{a}}</div>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Now Vue can keep track of the rendered items properly.

Conclusion

We should make sure that we have a key prop added to whatever is rendered by v-for .

Unused components should be removed from our code.

Render functions should always return something to render.

And prop types should be a constructor. Otherwise, the prop type check won’t work.