Categories
Vue

Getting Started with vue-chartjs

The vue-chartjs library lets us add charts to a Vue app easily.

In this article, we’ll look at how to add charts to a Vue app with vue-chart.js

Installation

We can install the package with chart.js by running:

yarn add vue-chartjs chart.js

or:

npm install vue-chartjs chart.js --save

chart.js is a required dependency.

Creating our first Chart

Now we can create our first chart by creating a new component.

For example, we can write:

components/LineChart.vue

<script>
import { Line, mixins } from "vue-chartjs";
const { reactiveProp } = mixins;

export default {
  extends: Line,
  mixins: [reactiveProp],
  props: ["chartData", "options"],
  mounted() {
    this.renderChart(this.chartData, this.options);
  }
};
</script>

App.vue :

<template>
  <div>
    <line-chart :chart-data="data" :options="options"></line-chart>
  </div>
</template>

<script>
import LineChart from "./components/LineChart.vue";

export default {
  components: {
    LineChart
  },
  data() {
    return {
      data: {
        labels: ["Monday", "Tuesday", "Wednesday"],
        datasets: [
          {
            label: "# of Votes",
            data: [12, 19, 3],
            borderWidth: 1
          }
        ]
      },
      options: {
        responsive: true,
        maintainAspectRatio: false
      }
    };
  },
  methods: {}
};
</script>

We created the LineChart component to display a line chart.

It takes the chartData prop with the chart data.

And it takes an options prop with the chart options.

The extends property is set to Line so that we can display a line chart.

Then we can call this.renderChart to display the chart with the data and options.

In App.vue , we get the line-chart component that we created and use it to display our chart.

We pass in the data to the chart-data prop and the options to the options prop.

responsive makes the chart responsive.

And maintainAspectRatio keeps the aspect ratio of the chart the same regardless of screen size.

The label has the label for the chart.

labels has the x-axis labels.

backgroundColor is the background color for the fill between the line and the x-axis.

data has the y-axis values.

The reactiveProp mixin lets our chart responds to prop changes.

Now we should see a line chart displayed.

Events

The chart emits various emits. They include:

  • chart:render – emitted if the mixin performs a complete rerender
  • chart:destroy – emitted if the mixin deletes the chart object instance
  • chart:update – emitted if the mixin performs an update instead of a re-render
  • labels:update – emitted if new labels were set
  • xlabels:update emitted if new x-axis labels were set
  • ylabels:update – emitted if new y-axis labels were set

Own Watcher

We can add our own watcher with and call the this.$data._chart.update() method to update the chart when the chart data updates.

For example, we can write:

<script>
import { Line } from "vue-chartjs";

export default {
  extends: Line,
  props: ["chartData", "options"],
  mounted() {
    this.renderChart(this.chartData, this.options);
  },
  watch: {
    chartData() {
      this.$data._chart.update();
    }
  }
};
</script>

then we watch for changes to the chartData prop and update the chart accordingly.

This is useful is we want to transform the line chart in the line chart component.

Conclusion

We can add charts to a Vue app easily with the vue-chartjs component.

Categories
TypeScript

What’s New in TypeScript 4.0?

TypeScript 4.0 comes with lots of new features to make JavaScript development easier.

In this article, we’ll look at the best features of TypeScript 4.

Variadic Tuples

TypeScript 4.0 comes with data types for tuples with a variable number of elements.

We can use the spread operator to create a type with the elements we want in our tuple.

For example, we write:

type Strings = [string, string];
type Numbers = number[];

type Unbounded = [...Strings, ...Numbers, boolean];

to create an Unbounded data type to add a tuple type with strings, numbers, and booleans.

The inference process is also automatic so that if we have 2 strings, numbers, and a boolean in the same order, TypeScript will infer the tuple as having the Unbounded type.

Labeled Tuple Elements

We can label tuple elements.

For example, we can write:

type Range = [start: number, end: number];

to restrict args to have a string and a number.

We can also write:

type Foo = [first: number, second?: string, ...rest: any[]];

to have rest entries in our tuple.

If our tuple has type Foo , then the tuple starts with a number and a string.

Then the rest of the entries can be anything.

Labels don’t require us to name our variables differently when destructuring.

For example, if we have:

function foo(x: [first: string, second: number]) {
  const [a, b] = x;
}

then we can name then destructured variables anything we want.

Class Property Inference from Constructors

TypeScript 4.0 can infer class properties’ types from the constructor.

For example, if we have:

class Square {
  area;
  length;

  constructor(length: number) {
    this.length = length;
    this.area = length ** 2;
  }
}

then TypeScript 4.0 knows that this.length and this.area are numbers automatically.

If there’s a chance that the value of them are undefined , then the TypeScript compiler will notify us of that.

So if we have:

class Square {
  length;

  constructor(length: number) {
    if (Math.random()) {
      this.length = length;
    }
  }

  get area() {
    return this.length  ** 2;
  }
}

then we’ll know that this.length may be undefined .

We would need a type assertion even if we know that it’s always defined.

For example, we can write:

class Square {
  length!: number;

  constructor(length: number) {
    this.initialize(length);
  }

  initialize(length: number) {
    this.length = length;
  }

  get area() {
    return this.length ** 2;
  }
}

We set length to be non-null with the ! symbol and set its type explicitly to number to make sure this.length is always a number.

Short-Circuiting Assignment Operators

TypeScript 4.0 has new assignment operator shorthands.

Now we write the logical AND, logical OR, and bullish coalescing operators with shorthands.

For example, instead of writing:

a = a && b;
a = a || b;
a = a ?? b;

We write:

a &&= b;
a ||= b;
a ??= b;

unknown on catch Clause Bindings

We can specify the binding variable of the catch clause to have an unknown type instead of an any type.

With the unknown type, we have to cast the exception object explicitly before we can do things with it.

For example, we can write:

try {
  // ...
} catch (e: unknown) {
  if (typeof e === "string") {
    console.log(e.toUpperCase());
  }
}

Then we check if e is a string before we call toUpperCase on it.

Conclusion

TypeScript 4.0 comes with many new language features that we can use to check for types.

Type inference is also improved.

Categories
TypeScript

TypeScript 4.0 — Breaking Changes

TypeScript 4.0 comes with lots of new features to make JavaScript development easier.

In this article, we’ll look at the best features of TypeScript 4.

Custom JSX Factories

TypeScript 4.0 lets us customize the fragment factory with the jsxFragmentFactory option.

We can set the settings in tsconfig.json by writing:

{
  compilerOptions: {
    target: "esnext",
    module: "commonjs",
    jsx: "react",
    jsxFactory: "h",
    jsxFragmentFactory: "Fragment",
  },
}

Also, we can set the factories in a per-file basis:

/** @jsx h */
/** @jsxFrag Fragment */

jsxFactory is the function to render JSX into JavaScript.

And jsxFragmentFactory lets us render JSX fragments to JavaScript.

Speed Improvements in build mode with --noEmitOnError

The noEmitError option lets us compile incrementally by caching data in a .tsbuildinfo file.

This will give us a performance when building with the --incremental flag.

--incremental with --noEmit

The --noEmit flag can now be used with the --incremental flag to speed up incremental builds.

Editor Improvements

With TypeScript 4.0, Visual Studio Code and Visual Studio becomes smarter.

One thing it can do is shrink long chains of undefined checks into the optional chaining or nullish coaslescing expressions.

For example, if can shrink:

a && a.b && a.b.c

into:

a?.b?.c

It also adds support for the /** @deprecated */ flag to mark code as being deprecated.

Then the code will appeared as being crossed out.

Partial Semantic Mode at Startup

Partial semantic mode speeds up the startup time of Visual Studio Code and Visual Studio by partially parsing the code instead of parsing everything during startup.

Now the startup delay should only be a few seconds because of that.

This means that we’ll get the rich experience of the editors immediately.

Smarter Auto-Imports

Auto-imports is now smarter since it works with packages that ships with its own types.

TypeScript 4.0 can search for the packages listed in package.json for types so that it can find the types and let us do auto-import on those packages.

We set the typescript.preferences.includePackageJsonAutoImports to true to let us do the auto-imports.

Properties Overriding Accessors (and vice versa) is an Error

Properties that override accessors and vice versa is an error with TypeScript 4.0.

For example, if we have:

class Base {
  get foo() {
    return 100;
  }
  set foo(value) {
    // ...
  }
}

class Derived extends Base {
  foo = 10;
}

then we’ll get an error since we set this.foo to a new value.

Operands for delete must be optional

Operands for delete must be optional since they can be removed.

So if we have something like:

interface Thing {
  prop: string;
}

function f(x: Thing) {
  delete x.prop;
}

then we get an error because props is required with Thing .

Conclusion

There are some breaking changes that comes with TypeScript 4.0.

Also, it has more features for setting JSX factories and converting syntax automatically.

Categories
Vue

Add a Markdown Editor to our Vue App

We can add a Markdown editor to our Vue app easily.

With it, users can enter formatted text easily since it can easily be converted to HTML.

In this article, we’ll look at how to add a Markdown editor to our Vue app.

Mavon Editor

The Mavon editor package is an easy to use package for adding a Markdown editor.

We can install it by using NPM with:

npm install mavon-editor --save

Then we can use it by writing:

main.js

import Vue from "vue";
import App from "./App.vue";
import mavonEditor from "mavon-editor";
import "mavon-editor/dist/css/index.css";

Vue.use(mavonEditor);

Vue.config.productionTip = false;
new Vue({
  render: (h) => h(App)
}).$mount("#app");

App.vue

<template>
  <div class="mavonEditor">
    <no-ssr>
      <mavon-editor :toolbars="markdownOption" v-model="handbook"/>
    </no-ssr>
  </div>
</template>

<script>
export default {
  data() {
    return {
      markdownOption: {
        bold: true
      },
      handbook: "#### how to use mavonEditor in nuxt.js"
    };
  }
};
</script>

We add the mavonEditor plugin into the main.js so that we can use it our components.

The CSS is also required so that we can see correct styling.

It binds to a state property with the v-model directive so that we can use the entered text to do something else.

The editor is on the left side and the preview of the Markdown output is on the right side.

Options

It comes with various props that we can set to change the options.

value sets the initial value.

language sets the language for the editor. It can be:

  • zh-CN for simplified Chinese
  • zh-TW for traditional Chinese
  • en for English
  • fr for French
  • pt-BR for Brazilian Portugese
  • ru for Russian
  • de for German
  • ja for Japanese

fontSize sets the font size.

scrollStyle lets us scroll with the mouse wheel.

boxShadow lets us enable the box shadow for the editor.

boxShadowStyle sets the style for the box shadow.

teransition is a boolean to let is enable or disable transition effects.

previewBackground lets us set the preview pane’s background.

placeholder lets us set the placeholder.

editable lets us set whether the Markdown editor is editable.

imageFilter is a function for filtering for image files.

imageClick is a function that’s run when we click on an image.

toolbars lets us add a toolbar with an object.

For example, we can write:

<template>
  <div class="mavonEditor">
    <mavon-editor :toolbars="toolbars" v-model="handbook"/>
  </div>
</template>

<script>
export default {
  data() {
    return {
      toolbars: {
        bold: true,
        italic: true,
        header: true,
        underline: true,
        strikethrough: true,
        mark: true,
        superscript: true,
        subscript: true,
        quote: true,
        ol: true,
        ul: true,
        link: true,
        imagelink: true,
        code: true,
        table: true,
        fullscreen: true,
        readmodel: true,
        htmlcode: true,
        help: true,
        undo: true,
        redo: true,
        trash: true,
        save: true,
        navigation: true,
        alignleft: true,
        aligncenter: true,
        alignright: true,
        subfield: true,
        preview: true
      },
      handbook: "#### how to use mavonEditor in nuxt.js"
    };
  }
};
</script>

to add the toolbar icons.

We can do many things with it like any word processor.

Conclusion

Mavon editor is a useful Markdown editor that we can add to our Vue app.

Categories
Vue

Ways to Optimize Our Vue Apps

Users will feel happier if the app we make loads faster.

This can be done with a few tricks with Vue apps.

In this article, we’ll look at what we can do to speed up our Vue apps.

Lazy Load Route Components

We can make our Vue route components load only when it’s needed.

To do that, we can use the JavaScript import function to import ou component.

For example, we can write:

import Vue from 'vue'
import Router from 'vue-router'

const Home = () => import('./routes/Home.vue');
const Settings = () => import('./routes/Settings.vue');

Vue.use(Router)

export default new Router({
  routes: [
    { path: '/', component: Home },
    { path: '/settings', component: Settings }
  ]
})

We have functions that returns promises for the component modules via the import function.

Since it’s not imported at build time, it’ll only be loaded when it’s needed.

Users have to download less code at the beginning so the loading speed will be faster.

The chunks can be controlled by adding the webpackChunkName comment.

For example, we can write:

const Profile = () => import(/* webpackChunkName: "profile" */'./routes/Profile.vue');
const ProfileSettings = () => import(/* webpackChunkName: "profile" */'./routes/ProfileSettings.vue');

We bundle the profile chunk with the webpackChunkName comment.

Minimize the Use of External Libraries

Reducing the number of libraries also reduce the bundle size, so the loading speed of our app will also be faster.

We can do a lot with JavaScript’s standard libraries.

For example, we can use native array methods instead of Lodash’s array methods.

Compress and Optimize Images

Images can be compressed a lot, so we should do that to reduce load time.

Also, we can load images from CDN so that we can serve them from a high-capacity server.

Lazy Load Images

Lazy loading images means that we load them only when we need to see them.

This can be done easily with the vue-lazyload package.

To install it, we run:

npm i vue-lazyload

Then in main.js , we add:

import Vue from 'vue'
import VueLazyload from 'vue-lazyload'

Vue.use(VueLazyload)

to register the plugin.

Then we can add:

<img v-lazy="image.src" >

in our template to use it. The v-lazy directive is made available from the plugin.

Reuse Functionalities Across Our App

Reusing functionality makes our app easier to change since we only have to change one place.

Also, we write less code so that the bundle is smaller.

Therefore, it’s faster to write and to faster to load for the user.

For example, with the VueNotifications library, we can write:

import VueNotifications from 'vue-notifications'
import miniToastr from 'mini-toastr'

miniToastr.init()

function toast ({title, message, type, timeout, cb}) {
  return miniToastr[type](message, title, timeout, cb)
}

const options = {
  success: toast,
  error: toast,
  info: toast,
  warn: toast
}

Vue.use(VueNotifications, options)

to create a toast function and then use it to display all kinds of toasts with it.

mini-toastr is a small notification library we can use to display notifications.

Conclusion

We can optimize the speed of our Vue app easily with some easy tricks.