Categories
Vue Best Practices

Vue Best Practices — Most Important Changes

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 async Function for Computed Properties

The functions we use for computed properties should be synchronous.

If we use async functions, unexpected behavior may occur.

If we ned computed properties to be async, then we can use plugins to use them.

For instance, we should write:

<template>
  <div id="app"></div>
</template>
<script>
export default {
  name: "App",
  computed: {
    reversedMsg() {
      return this.msg
        .split("")
        .reverse()
        .join("");
    }
  },
  data() {
    return { msg: "foo" };
  }
};
</script>

No Duplicate Keys in Field Names

We shouldn’t have duplicate field names in our component object.

This applies to the whole object. So we shouldn’t have the same name in methods or data for example.

Instead of writing:

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

We should write:

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

No Duplicate Attributes

We shouldn’t have duplicate attributes in our templates.

For instance, instead of writing:

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

We write:

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

Don’t Overwrite Reserved Keys

We shouldn’t write keys that have the same names as reserved keys.

For instance, we shouldn’t write:

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

We have an $el prop, which is a reserved key.

We shouldn’t have that so we won’t get unexpected results.

No Shared Component State

The data property should have a function instead of the object as its value.

If we have an object, then the state will be shared.

Therefore, instead of writing:

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

We should write:

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

No Side Effects in Computed Properties

We shouldn’t have side effects inside computed property functions.

It makes the code hard to understand and unpredictable.

For instance, instead of writing:

<template>
  <div id="app"></div>
</template>
<script>
export default {
  name: "App",
  computed: {
    foo() {
      window.foo = `foo ${this.baz}`;
      return `foo ${this.baz}`;
    }
  },
  data() {
    return {
      baz: "bar"
    };
  }
};
</script>

We should write:

<template>
  <div id="app"></div>
</template>
<script>
export default {
  name: "App",
  computed: {
    foo() {
      return `foo ${this.baz}`;
    }
  },
  data() {
    return {
      baz: "bar"
    };
  }
};
</script>

All we do is return something based on the fields in data .

No key Attribute in template

The template element shouldn’t have the key attribute.

For instance, instead of writing:

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

We write:

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

No Mustache in textarea

We should never put a mustache expression between the textarea tags.

Instead, we should use the v-model directive.

This way, get a 2-way binding between our model field and the input value.

For instance, instead of writing:

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

We should write:

<template >
  <div id="app">
    <textarea v-model="message">{</textarea>
  </div>
</template>
<script>
export default {
  name: "App",
  data() {
    return {
      message: "foo"
    };
  }
};
</script>

Conclusion

There are many ways to make mistakes when writing Vue apps.

We should never commit side effects in computed properties.

Also, our component should never expose its state to the outside.

Reserved keys should also never be keys of anything in our component object.

We should use v-model with textarea elements to get a 2-way binding between our model field and the input value.

Categories
Vuetify

Vuetify — Transition, Alert, and Scrolling

Vuetify is a popular UI framework for Vue apps.

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

Custom Transition

We can create our own transition by using the createSimpleTransition function to create our transition.

First, we define the component in vuetify.js

import Vue from 'vue';
import Vuetify from 'vuetify/lib';
import { createSimpleTransition } from 'vuetify/lib/components/transitions/createTransition'

const fadeTransition = createSimpleTransition('v-fade-transition')
Vue.component('v-fade-transition', fadeTransition)
Vue.use(Vuetify);

export default new Vuetify({
});

Then we write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-btn class="ma-2" color="primary" @click="expand = !expand">Expand Transition</v-btn>

        <v-fade-transition>
          <v-card v-show="expand" height="100" width="100" class="mx-auto"></v-card>
        </v-fade-transition>
      </v-col>
    </v-row>
  </v-container>
</template>

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

<style scoped>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
  opacity: 0;
}
</style>

We defined the v-fade-transition component with:

const fadeTransition = createSimpleTransition('v-fade-transition')
Vue.component('v-fade-transition', fadeTransition)

Then we defined the classes for it with:

<style scoped>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
  opacity: 0;
}
</style>

The prefix fade should be the same one as the word between v- and -transition so that the transition styles will be applied.

Programmatic Scrolling

We can scroll our page programmatically with Vuetify.

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-btn ref="button" block color="primary" @click="$vuetify.goTo('#num-100')">scroll</v-btn>

        <p v-for='n in 100' :key='n' :id="`num-${n}`">{{n}}</p>
      </v-col>
    </v-row>
  </v-container>
</template>

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

We have the p elements with some IDs.

And we call $vuetify.goTo to scroll to the element with the given selector.

goTo also takes a second argument with some options.

The option object can have the duration , offset , and easing properties.

We can set the options by writing:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-btn ref="button" block color="primary" @click="$vuetify.goTo('#num-100', options)">scroll</v-btn>

        <p v-for="n in 100" :key="n" :id="`num-${n}`">{{n}}</p>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",
  data: () => ({
    options: {
      duration: 1300,
      offset: 0,
      easing: "easeInOutCubic",
    },
  }),
};
</script>

And we set the option for scrolling.

Alerts

We can add an alert with the v-alert component.

It comes with 4 default styles, which are success , info , warning , and error .

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-alert type="success">success alert.</v-alert>

        <v-alert type="info">info alert.</v-alert>

        <v-alert type="warning">warning alert.</v-alert>

        <v-alert type="error">error alert.</v-alert>
      </v-col>
    </v-row>
  </v-container>
</template>

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

We have the v-alert component with the alerts.

Conclusion

We can scroll programmatically and add alerts with Vuetify.

Also, we can create our own transition components with one function.

Categories
Vuetify

Vuetify — Alert Styles

Vuetify is a popular UI framework for Vue apps.

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

Alerts

We create an alert with v-alert component.

To do that, we write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-alert type="success">success alert.</v-alert>

<v-alert type="info">info alert.</v-alert>

<v-alert type="warning">warning alert.</v-alert>

<v-alert type="error">error alert.</v-alert>
      </v-col>
    </v-row>
  </v-container>
</template>

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

We can add a border with:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-alert border="top" color="red lighten-2" dark>red border</v-alert>
      </v-col>
    </v-row>
  </v-container>
</template>

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

We set the color to red to make a red border.

border is set to top to add the border to the top.

Colored Border

We can set the colored-border prop to add a colored border:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-alert border="left" colored-border color="deep-purple accent-4" elevation="2">lorem ipsum</v-alert>
      </v-col>
    </v-row>
  </v-container>
</template>

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

Dense Alert

We can make the alert box smaller with the dense prop.

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-alert dense type="info">dense alert</v-alert>
      </v-col>
    </v-row>
  </v-container>
</template>

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

to make it denser with the dense prop.

Icon

We can add an icon to it with the icon prop:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-alert color="#2A3B4D" dark icon="mdi-firework" dense>icon alert</v-alert>
      </v-col>
    </v-row>
  </v-container>
</template>

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

We add a firework icon to the left with the icon prop.

Outlined

We can make the alert displayed as an outline version with:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-alert outlined color="purple">
          <div class="title">Lorem Ipsum</div>
          <div>outlined alert.</div>
        </v-alert>
      </v-col>
    </v-row>
  </v-container>
</template>

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

Then outlined prop makes the outline.

Prominent

The prominent prop provides a more pronounced alert by increasing the height and adding a halo to the icon:”

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-alert
          color="blue-grey"
          dark
          dense
          icon="mdi-school"
          prominent
        >Sed augue ipsum, egestas nec</v-alert>
      </v-col>
    </v-row>
  </v-container>
</template>

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

We added the prominent prop and everything else will be applied automatically.

Text

We can add the text prop to create a simple alert variant with only text.

It can be combined with the dense , prominent and outlined props:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-alert text outlined color="deep-orange" icon="mdi-fire">Nullam tincidunt adipiscing enim</v-alert>
      </v-col>
    </v-row>
  </v-container>
</template>

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

We only have text in our alert.

Conclusion

We can create alerts with various styles provided by Vuetify.

Categories
Vuetify

Vuetify — Visibility and Layout

Vuetify is a popular UI framework for Vue apps.

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

Visibility

Vuetify provides us with some visibility classes.

They include:

  • Hidden on all .d-none
  • Hidden only on xs .d-none .d-sm-flex
  • Hidden only on sm .d-sm-none .d-md-flex
  • Hidden only on md .d-md-none .d-lg-flex
  • Hidden only on lg .d-lg-none .d-xl-flex
  • Hidden only on xl .d-xl-none
  • Visible on all Visible only on xs .d-flex .d-sm-none
  • Visible only on sm .d-none .d-sm-flex .d-md-none
  • Visible only on md .d-none .d-md-flex .d-lg-none
  • Visible only on lg .d-none .d-lg-flex .d-xl-none
  • Visible only on xl .d-none .d-xl-flex

Display in Print

Vuetify also provides classes for display stuff in print. They are:

  • .d-print-none
  • .d-print-inline
  • .d-print-inline-block
  • .d-print-block
  • .d-print-table
  • .d-print-table-row
  • .d-print-table-cell
  • .d-print-flex
  • .d-print-inline-flex

Elevation Helpers

We can change the depth of an element with the elevation helpers.

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col cols="12">
        <v-card :elevation="10" height="100" width="100">
          <v-row class="fill-height" align="center" justify="center" v-text="'foo'"></v-row>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",

  data: () => ({}),
};
</script>

We have the v-card component with the elevation prop to set the elevation.

Now we’ll see a shadow in an element.

Flexbox

Vuetify supports flexbox for layout.

To use it, we can use the classes that it provides.

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col cols="12">
        <v-card class="d-flex pa-2" outlined tile>
          <div>flexbox</div>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",

  data: () => ({}),
};
</script>

We added the v-card with the d-flex class to make the card have a flex layout.

Flexbox classes include:

  • .d-flex
  • .d-inline-flex
  • .d-sm-flex
  • .d-sm-inline-flex
  • .d-md-flex
  • .d-md-inline-flex
  • .d-lg-flex
  • .d-lg-inline-flex
  • .d-xl-flex
  • .d-xl-inline-flex

Flex Direction

We can change the flex-direction with the provides classes.

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col cols="12">
        <v-card class="d-flex flex-row mb-6" color="grey lighten-2" flat tile>
          <v-card v-for="n in 3" :key="n" class="pa-2" outlined tile>item {{ n }}</v-card>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",

  data: () => ({}),
};
</script>

We have the flex-row class to show the divs in a row.

Vuetify also provides the flex-column-reverse classes to change the orientation of the flexbox container.

Conclusion

We can change the visibility and layout of elements with Vuetify.

Categories
Vuetify

Vuetify — Transitions

Vuetify is a popular UI framework for Vue apps.

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

Transitions

Vuetify provides us with transition effective we van add.

We can add transition with the transition prop.

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-menu transition="slide-x-transition">
          <template v-slot:activator="{ on, attrs }">
            <v-btn color="primary" class="ma-2" v-bind="attrs" v-on="on">Slide X Transition</v-btn>
          </template>
          <v-list>
            <v-list-item v-for="n in 3" :key="n" link>
              <v-list-item-title v-text="`Item ${n}`"></v-list-item-title>
            </v-list-item>
          </v-list>
        </v-menu>

        <div class="mx-4 hidden-sm-and-down"></div>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

The slide-x-transition provides us with a horizontal transition applied when displaying the menu.

We can reverse the direction of the transition with slide-x-reverse-transition .

Slide Y Transitions

We have the slide-y-transition to slide elements vertically.

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-menu transition="slide-y-transition">
          <template v-slot:activator="{ on, attrs }">
            <v-btn color="primary" class="ma-2" v-bind="attrs" v-on="on">Slide Y Transition</v-btn>
          </template>
          <v-list>
            <v-list-item v-for="n in 3" :key="n" link>
              <v-list-item-title v-text="`Item ${n}`"></v-list-item-title>
            </v-list-item>
          </v-list>
        </v-menu>

        <div class="mx-4 hidden-sm-and-down"></div>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

Now we have vertical transition instead of horizontal.

Also, we have the slide-y-reverse-transition to apply the transition effect in the reverse direction.

Scroll Y Transitions

We can add scroll y transition with:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-menu transition="scroll-y-transition">
          <template v-slot:activator="{ on, attrs }">
            <v-btn color="primary" class="ma-2" v-bind="attrs" v-on="on">Scroll Y Transition</v-btn>
          </template>
          <v-list>
            <v-list-item v-for="n in 5" :key="n" link>
              <v-list-item-title v-text="`item ${n}`"></v-list-item-title>
            </v-list-item>
          </v-list>
        </v-menu>

        <div class="mx-4 hidden-sm-and-down"></div>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

We just set “scroll-y-transition” as the value of transition .

Fab Transition

We can add a rotating transition with fab-transition :

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-menu transition="fab-transition">
          <template v-slot:activator="{ on, attrs }">
            <v-btn color="primary" class="ma-2" v-bind="attrs" v-on="on">Fab Transition</v-btn>
          </template>
          <v-list>
            <v-list-item v-for="n in 5" :key="n" link>
              <v-list-item-title v-text="`item ${n}`"></v-list-item-title>
            </v-list-item>
          </v-list>
        </v-menu>

        <div class="mx-4 hidden-sm-and-down"></div>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
};
</script>

Expand Transition

The v-expand-transition component lets us add an expand transition effect.

v-expand-x-transition is the horizontal version.

For example, we can write:

<template>
  <v-container>
    <v-row class="text-center">
      <v-col col="12">
        <v-btn class="ma-2" color="primary" @click="expand = !expand">Expand Transition</v-btn>

        <v-expand-transition>
          <v-card v-show="expand" height="100" width="100" class="mx-auto"></v-card>
        </v-expand-transition>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    expand: false
  }),
};
</script>

Now when we toggle the card, we see a transition effect applied to it.

Conclusion

We can add various transition effects with Vuetify.