Categories
Vue 3

Getting Started with Vuex 4 with Vue 3

Vuex 4 is in beta and it’s subject to change.

Vuex is a popular state management library for Vue.

Vuex 4 is the version that’s made to work with Vue 3.

In this article, we’ll look at how to use Vuex 4 with Vue 3.

Installation

We can install it from CDN.

To do that, we add the script tag for Vuex.

Then we can use that to create the app by writing:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="https://unpkg.com/vuex@4.0.0-beta.4/dist/vuex.global.js"></script>
    <title>App</title>
  </head>
  <body>
    <div id="app">
      <button @click="increment">increment</button>
      <p>{{count}}</p>
    </div>
    <script>
      const store = new Vuex.Store({
        state: {
          count: 0
        },
        mutations: {
          increment(state) {
            state.count++;
          }
        }
      });

      const app = Vue.createApp({
        methods: {
          increment() {
            this.$store.commit("increment");
          }
        },
        computed: {
          count() {
            return this.$store.state.count;
          }
        }
      });
      app.use(store);
      app.mount("#app");
    </script>
  </body>
</html>

We included the global version of Vuex so that we can use it with HTML script tags.

In the code above, we created a store with the Vuex.Store constructor.

The state has the store’s states.

We have the count state with the count.

mutations has the store mutations.

It has the inctrement mutation method to increment the count state.

Then in our root Vue instance, we have the increment method that calls the this.$store.commit method to increment the count state.

And we have the computed count property to return the count state from the store.

The store state is accessible with the this.$store.state property.

We call the increment method when we click on the increment button.

Then we see the count state updated and displayed in the template via the computed property.

We have th remember to add:

app.use(store);

so that the store can be used with our Vue 3 app.

The changes are reactive, so whenever the store’s state changes, we’ll get the latest changes in our components.

Getters

We can add getters to make getting states easier.

Instead of computed properties, we can use getters to get the latest value of our state.

To add a getter, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="https://unpkg.com/vuex@4.0.0-beta.4/dist/vuex.global.js"></script>
    <title>App</title>
  </head>
  <body>
    <div id="app">
      <div>
        <p v-for="d of doneTodos" :key="d.id">{{d.text}}</p>
      </div>
    </div>
    <script>
      const store = new Vuex.Store({
        state: {
          todos: [
            { id: 1, text: "eat", done: true },
            { id: 2, text: "sleep", done: false }
          ]
        },
        getters: {
          doneTodos: (state) => {
            return state.todos.filter((todo) => todo.done);
          }
        }
      });

      const app = Vue.createApp({
        computed: {
          ...Vuex.mapGetters(["doneTodos"])
        }
      });
      app.use(store);
      app.mount("#app");
    </script>
  </body>
</html>

to create a doneTodos getter in our store and use it in our Vue instance with the Vuex.mapGetters method.

The argument is an array of strings with the name of the getters.

We spread the computed properties into the computed object so that we can access the in our component.

In the template, we render the items from the getter.

The doneTodos method has the state parameter with the state.

It can also receive other getters as a second argument.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="https://unpkg.com/vuex@4.0.0-beta.4/dist/vuex.global.js"></script>
    <title>App</title>
  </head>
  <body>
    <div id="app">
      <div>
        <p v-for="d of doneTodos" :key="d.id">{{d.text}}</p>
        <p>{{doneTodosCount}} done</p>
      </div>
    </div>
    <script>
      const store = new Vuex.Store({
        state: {
          todos: [
            { id: 1, text: "eat", done: true },
            { id: 2, text: "sleep", done: false }
          ]
        },
        getters: {
          doneTodos: (state) => {
            return state.todos.filter((todo) => todo.done);
          },
          doneTodosCount: (state, getters) => {
            return getters.doneTodos.length;
          }
        }
      });

      const app = Vue.createApp({
        computed: {
          ...Vuex.mapGetters(["doneTodos", "doneTodosCount"])
        }
      });
      app.use(store);
      app.mount("#app");
    </script>
  </body>
</html>

We have the doneTodosCount getter with the getters object that has our getters.

We used it to access the doneTodos getter with it and used mapGetters to display to make it accessible in our component.

Then we should see the todos that have done set to true and get 1 done in our component displayed.

Conclusion

We can create a simple Vue 3 app with Vuex 4 with a simple store and getters.

Categories
Vue 3

Vue Router 4–Async Scrolling, Lazy-Loading, and Navigation Errors

Vue Router 4 is in beta and it’s subject to change.

To build a single page app easily, we got to add routing so that URLs will be mapped to components that are rendered.

In this article, we’ll look at how to use Vue Router 4 with Vue 3.

Async Scrolling Behavior

We can change the scrolling behavior to be async.

To do that, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="https://unpkg.com/vue-router@4.0.0-beta.7/dist/vue-router.global.js"></script>
    <title>App</title>
  </head>
  <body>
    <div id="app">
      <p>
        <router-link to="/foo">foo</router-link>
        <router-link to="/bar">bar</router-link>
      </p>
      <router-view></router-view>
    </div>
    <script>
      const Foo = {
        template: `<div>
          <p v-for='n in 100'>{{n}}</p>
        </div>`
      };
      const Bar = {
        template: `<div>
          <p v-for='n in 100'>{{n}}</p>
        </div>`
      };
      const routes = [
        {
          path: "/foo",
          component: Foo
        },
        {
          path: "/bar",
          component: Bar
        }
      ];
      const router = VueRouter.createRouter({
        history: VueRouter.createWebHistory(),
        routes,
        scrollBehavior(to, from, savedPosition) {
          return new Promise((resolve, reject) => {
            setTimeout(() => {
              resolve({ left: 0, top: 500 });
            }, 500);
          });
        }
      });
      const app = Vue.createApp({});
      app.use(router);
      app.mount("#app");
    </script>
  </body>
</html>

We have the scrollBehavior method that returns a promise that resolves to an object with the scroll position.

The left and top properties are the new properties for the x and y coordinates.

They replace the x and y properties in Vue Router 3.

Lazy Loading Routes

We can lazy load routes in our app.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="[https://unpkg.com/vue@next](https://unpkg.com/vue@next)"></script>
    <script src="[https://unpkg.com/vue-router@4.0.0-beta.7/dist/vue-router.global.js](https://unpkg.com/vue-router@4.0.0-beta.7/dist/vue-router.global.js)"></script>
    <title>App</title>
  </head>
  <body>
    <div id="app">
      <p>
        <router-link to="/foo">foo</router-link>
        <router-link to="/bar">bar</router-link>
      </p>
      <router-view></router-view>
    </div>
    <script>
      const Foo = () =>
        Promise.resolve({
          template: `<div>foo</div>`
        });

      const Bar = () =>
        Promise.resolve({
          template: `<div>bar</div>`
        });

      const routes = [
        {
          path: "/foo",
          component: Foo
        },
        {
          path: "/bar",
          component: Bar
        }
      ];
      const router = VueRouter.createRouter({
        history: VueRouter.createWebHistory(),
        routes
      });
      const app = Vue.createApp({});
      app.use(router);
      app.mount("#app");
    </script>
  </body>
</html>

We have the Foo and Bar components.

They are defined by creating a promise that resolves to the component definition.

With Webpack, we can also use the import function to import our component.

For example, we can write:

import('./Foo.vue')

import returns a promise that resolves to the component, and it works the same way as the promise definition above.

Grouping Components in the Same Chunk

We can group components in the same chunk bu creating components with functions:

const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')

We have comments with webpackChunkName with the chunk name.

Navigation Failures

We can handle navigation errors with programmatic navigation.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="https://unpkg.com/vue-router@4.0.0-beta.7/dist/vue-router.global.js"></script>
    <title>App</title>
  </head>
  <body>
    <div id="app">
      <p>
        <router-link to="/foo">foo</router-link>
        <a href="#" [@click](http://twitter.com/click "Twitter profile for @click").stop="go">bar</a>
      </p>
      <router-view></router-view>
    </div>
    <script>
      const Foo = {
        template: `<div>foo</div>`
      };

      const Bar = {
        template: `<div>bar</div>`,
        beforeRouteEnter(to, from, next) {
          next(new Error());
        }
      };

      const routes = [
        {
          path: "/foo",
          component: Foo
        },
        {
          path: "/bar",
          component: Bar
        }
      ];
      const router = VueRouter.createRouter({
        history: VueRouter.createWebHistory(),
        routes
      });
      const app = Vue.createApp({
        methods: {
          go() {
            this.$router.push("/bar").catch((failure) => {
              console.log(failure);
            });
          }
        }
      });
      app.use(router);
      app.mount("#app");
    </script>
  </body>
</html>

to handle navigation errors.

We a beforeRouterEnter method in the Bar component.

It calls next with an Error instance within the method.

This will cause the Error instance to be shown in the console.

In the root Vue instance, we have the go method that tries to go to the /bar route with the push method.

The catch method’s callback has the failure parameter that has the Error instance that’s thrown.

Conclusion

We can change scrolling behavior to be async.

Also, components can be grouped into chunks and lazy-loaded.

Finally, we can handle errors that are raised from programmatic navigation.

Categories
Vue 3

Vue Router 4–Scroll Behavior

Vue Router 4 is in beta and it’s subject to change.

To build a single page app easily, we got to add routing so that URLs will be mapped to components that are rendered.

In this article, we’ll look at how to use Vue Router 4 with Vue 3.

Scroll Behavior

We can change the scroll behavior with the Vue Router.

To do that, we add the scrollBehavior method to the object that we pass into the createRouter method.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="https://unpkg.com/vue-router@4.0.0-beta.7/dist/vue-router.global.js"></script>
    <title>App</title>
  </head>
  <body>
    <div id="app">
      <router-view></router-view>
      <p>
        <router-link to="/foo">foo</router-link>
        <router-link to="/bar">bar</router-link>
      </p>
    </div>
    <script>
      const Foo = {
        template: `<div>
          <p v-for='n in 100'>{{n}}</p>
        </div>`
      };
      const Bar = {
        template: "<div>bar</div>"
      };
      const routes = [
        {
          path: "/foo",
          component: Foo
        },
        {
          path: "/bar",
          component: Bar
        }
      ];
      const router = VueRouter.createRouter({
        history: VueRouter.createWebHistory(),
        routes,
        scrollBehavior(to, from, savedPosition) {
          return { left: 0, top: 500 };
        }
      });
      const app = Vue.createApp({});
      app.use(router);
      app.mount("#app");
    </script>
  </body>
</html>

We return an object with the left and top properties.

left is the x coordinate and top is the y coordinate we want to scroll to when the route changes.

to has the route object of the route we’re moving to.

And from has the route object we’re moving from.

Now when we click on the router links, we move to somewhere near the top of the page.

savedPosition has the position that we scrolled in the previous route.

We can use the savedPosition object as follows:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/vue@next"></script>
    <script src="https://unpkg.com/vue-router@4.0.0-beta.7/dist/vue-router.global.js"></script>
    <title>App</title>
  </head>
  <body>
    <div id="app">
      <router-view></router-view>
      <p>
        <router-link to="/foo">foo</router-link>
        <router-link to="/bar">bar</router-link>
      </p>
    </div>
    <script>
      const Foo = {
        template: `<div>
          <p v-for='n in 100'>{{n}}</p>
        </div>`
      };
      const Bar = {
        template: `<div>
          <p v-for='n in 150'>{{n}}</p>
        </div>`
      };
      const routes = [
        {
          path: "/foo",
          component: Foo
        },
        {
          path: "/bar",
          component: Bar
        }
      ];
      const router = VueRouter.createRouter({
        history: VueRouter.createWebHistory(),
        routes,
        scrollBehavior(to, from, savedPosition) {
          if (savedPosition) {
            return savedPosition;
          } else {
            return { left: 0, top: 0 };
          }
        }
      });
      const app = Vue.createApp({});
      app.use(router);
      app.mount("#app");
    </script>
  </body>
</html>

When the savedPosition object is defined, we return it.

Otherwise, we scroll to the top when we click on the router links.

Now when we scroll to the links, we’ll stay at the bottom of the page.

Conclusion

We can scroll to a given position on the page with Vue Router 4 with the scrollBehavior method.

Categories
JavaScript

Handy NPM Packages You May Have Missed

NPM packages are used by both browser and Node.js apps alike. NPM is the biggest repository of JavaScript libraries.

In this article, we’ll look at the popular JavaScript packages on NPM.

colors

We can use this library to display text with colors with little effort.

We can use it to set colors in various colors. The background color can also be changed.

With this, we can choose between bright and normal background colors.

It can also make text bold, italic, and apply other text styles.

dotenv

Dotenv is a useful library for letting us read environment variables from .env files.

It’s also useful for reading environment variables directly from the operating system.

Therefore, it’s great for back end apps.

We can control how .env files are read, including whether we want to include whitespace or # into our app.

jquery

The once-popular jQuery library for DOM manipulation is also available as a Node package.

It provides lots of DOM manipulation functionality like manipulating class names, changing styles on the fly, and many more things.

Also, it has many utility functions like the ajax function for making HTTP requests and much more.

typescript

The TypeScript package lets us add TypeScript support into our project.

Using TypeScript has many benefits. It adds many capabilities into JavaScript, like data type annotations, data type checking, while retaining the flexibility of the JavaScript type system.

Therefore, we can make many data types with it like union types, intersection types, nullable types, literal types, generic types, and much more.

minimist

The minimist library lets us parse command-line arguments into a format that we can use easily.

We can call the function that comes with the package and then it returns a JavaScript object that we can use in our program.

aws-sdk

This is the official AWS SDK for Node apps. It lets us use their services within our Node app.

AWS has many services including file storage, cloud hosting, image recognition, and much more.

@types/node

This package lets us add TypeScript type annotation for built-in Node modules.

We can use this to help us with development by providing autocomplete for standard Node modules.

semver

semver is a semantic version parse for Node apps.

We can parse semantic version names into strings with it.

Also, we can use them to compare versions and get the minimum versions given a version string.

redux

Redux is a state management library. It’s often paired with React-Redux to create a state management solution for React apps.

We need centralized state management because there’s no easier way to share data between components of a complex front end app.

eslint

ESLint is a linter for JavaScript. It checks for syntax errors and bad coding practices for JavaScript projects.

By default, it has many rules built-in and we can add plugins to expand the sets of rules that it provides.

It supports the latest JavaScript syntax and is aware of deprecated and bad syntax so it’s very handy too to have when developing any JavaScript project.

winston

Winston is a logger that lets us log data in Node.js apps.

It can be used for simple logging and it also has many formatting features to format our log file the way we want.

We can filter data and change the logging level to be the level that we want.

node-fetch

This library brings the Fetch API to Node.js. The Fetch API is an HTTP client that’s standard in browsers.

It’s a replacement of the XMLHttpRequest constructor that we were using before.

Fetch API is promise-based, and supports making many more kinds of requests and can process responses automatically unlike the old XMLHttpRequest constructor.

With this package, we can use it in Node apps.

css-loader

css-loader is a module for adding CSS importing capabilities into Webpack.

With it, we can import CSS files in our JavaScript code files as a string and use them the way we like.

Conclusion

ESLint is one of the most popular linter for checking for syntax and code styling issues with Node.js.

Winston is a popular logger for Node.js apps.

We also have libraries for showing colors in the command line, command-line argument parser, and more.

Categories
JavaScript

Popular NPM Packages You May Have Missed

NPM packages are used by both browser and Node.js apps alike. NPM is the biggest repository of JavaScript libraries.

In this article, we’ll look at the popular JavaScript packages on NPM.

bluebird

Bluebird is a popular promise library for making promises. It’s popular before promises are built into ES6 or later.

Now that JavaScript has promises as a native feature, we probably don’t need this as much.

vue

Vue is a popular framework for building front end apps.

It’s full-featured so it includes many things like templating, filters for formatting template content, directives for manipulating the DOM, and the use of components all in one package.

Vue is getting more popular every day, and making simple apps with it is easy

There are many libraries made for it to make our lives easier.

Therefore. we can use it to make apps. With Vuex and Vue Router, we have state management and routing solution to make a standalone front end app with it.

uuid

Thi library lets us create various kinds of unique IDs that we can use for things like unique identifier for database entries and more.

classnames

We can use the classnames library to join class names together conditionally so that we can apply styles dynamically to a web page.

It’s framework agnostic so it can be used in almost any project. However, since there’s a class name manipulation feature in frameworks like Vue and Angular, we shouldn’t use this with those frameworks.

But this library does work great with React, since there’s no easy way to manipulate class names dynamically out of the box.

underscore

Underscore is another popular JavaScript helper library with various methods or manipulating arrays and objects.

Its feature set is smaller than Lodash, some of its methods have plain JavaScript equivalents, so it’s not as useful as it is before.

core-js

Core-js has a set of polyfill that we can add to support browsers that don’t have the libraries built into the browser.

They include the latest arrays and string methods, and also new constructors like Map and Set .

Also, the Promise constructor is included so that we can use native promises instead of 3rd party solutions.

Whatever has been introduced with ES6 or later, this library has them all.

inquirer

Inquirer is a library that lets us build command-line user interfaces with ease.

It has methods for letting us prompt answers and take user input.

We can format questions and answers in the way we like to and we can even use it to create react user interfaces hat listen for answers.

yargs

Is a library that helps us build command-line interfaces by helping us process command line arguments without hassle.

It parses options that are passed in with the command that starts our program so we can use them without parsing them ourselves.

webpack

Webpack is a popular package for letting us bundle modules into packages that can be used in browsers.

It supports many options and are used by the CLIs of popular frameworks like Angular, React, and Vue.

mkdirp

mkdirp lets us create directories recursively in our Node programs.

The fs module doesn’t have a function that lets us create directories recursively, so we’ve to use this library to do that.

It has both a synchronous and asynchronous version built-in.

rxjs

Rxjs is a popular for library for reactive programming.

It lets us create objects for emitting data, which can be subscribed to other objects.

Also, we can use it to adjust the ways that data is emitted with built-in methods.

glob

Glob lets us search for files from within a Node.js program. We can pass in any path pattern as a string and we get back the results of the paths that match the pattern that we pass in.

By default, the search is done asynchronously, but we can also do it synchronously.

body-parser

This is a package that lets us parse request bodies in our Express apps. It’s available as an Express middleware, so it can be used to parse JSON request bodies.

Since there’s no built-in way to parse JSON request bodies in Express, we have to use this.

Conclusion

Some of these libraries let us build command-line interfaces easily.

We also have Underscore to let us do array and object operations that don’t have plain JavaScript equivalents and are not easy to do.