iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
📝

Introduction to Vue.js and Nuxt.js for Backend Engineers

に公開

I will explain the basic content of Vue.js and Nuxt.js, which are JavaScript frameworks, for backend engineers.

What is Vue.js

  • A JavaScript framework for building user interfaces.
  • You can declaratively describe HTML output using a template syntax that extends standard HTML.
  • It automatically tracks changes in JavaScript state and efficiently updates the DOM when changes occur.
    • It also tracks user input (two-way binding).

Single File Components (SFC)

  • When developing screens, it is desirable to divide the development into component units (the reason is described later).
  • To achieve this, Vue.js has a mechanism called Single File Components (SFC).
  • In an SFC, the template (HTML), script (JS), and style (CSS) related to a single component are combined into one .vue file.
ButtonCounter.vue
<template>
  <button @click="count++">Count is: {{ count }}</button>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  data: () => ({
    count: 0,
  }),
});
</script>

<style scoped>
button {
  font-weight: bold;
}
</style>

↑ Quoted from https://vuejs.org/guide/introduction.html#single-file-components (partially modified)

  • <template> ~ </template>: Describe HTML
  • <script> ~ </script>: Describe JS
    • lang="ts": Declaration for writing in TS instead of JS
  • <style> ~ </style>: Describe CSS
    • scoped: Possible to limit the scope of CSS application to this component

Importing other components (import) is also easy, as shown below.

ButtonCounterWrapper.vue
<template>
  <h1>Here is a child component!</h1>
  <ButtonCounter />
</template>

<script lang="ts">
import { defineComponent } from "vue";
import ButtonCounter from "./ButtonCounter.vue";

export default defineComponent({
  components: {
    ButtonCounter,
  },
});
</script>

↑ Quoted from https://vuejs.org/guide/essentials/component-basics.html#using-a-component (partially modified)

  • In the past, when splitting files, it was common to split by HTML, JS, and CSS.
  • On the other hand, Vue.js splits files by component units. This is for the following reasons:
    • "Separation of concerns" is not the same as "separation of file types."
      • With SFC, a set of source code (template, logic, style) included in the concern of a "button" can be written in a single file.
      • As a result, the consistency and maintainability of the component are improved.

Options API and Composition API

In Vue.js, there are two API styles due to historical reasons.

Options API

A style where component logic is defined using a single object consisting of various options such as data, methods, and mounted.

ButtonCounter.vue (Options API)
<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  // Properties returned by data() become reactive state,
  // and can be accessed via `this`.
  data: () => ({
    count: 0,
  }),

  // Lifecycle hooks are called at specific stages
  // of the component's lifecycle.
  // The following function is called when the component is "mounted."
  mounted() {
    console.log(`The initial count is ${this.count}.`);
  },

  // The content of the methods are functions that change state and trigger updates.
  // Each method can be bound to event handlers within the template.
  methods: {
    increment() {
      this.count++;
    },
  },
});
</script>

Composition API

A style where component logic is defined using various imported API functions.

The following is a rewrite of the above sample code using the Composition API.

ButtonCounter.vue (Composition API)
<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

<script setup lang="ts">
import { ref, onMounted } from "vue";

// Reactive state
const count = ref(0);

// Function that changes state and triggers updates.
function increment() {
  count.value++;
}

// Lifecycle hook
onMounted(() => {
  console.log(`The initial count is ${count.value}.`);
});
</script>

Please refer to the following for details (sample code is also quoted from here).
https://ja.vuejs.org/guide/introduction.html#api-styles

Basic Syntax

The official tutorial is quite comprehensive, so I recommend trying it out.

https://vuejs.org/tutorial

Vue Router

In a Single Page Application (SPA), a client-side router is required.

  • In the case of a Multi-Page Application (MPA)
    • Click a link
    • Route on the server side and retrieve all data
    • Screen transition
  • In the case of a Single Page Application (SPA)
    • Click a link
    • Route on the client side and call APIs only for necessary data
    • Screen update

Vue Router is the router for Vue.js. Its usage is quite simple, as shown in the official guide below.

https://router.vuejs.org/guide/#JavaScript

In Nuxt.js, routing is automatically registered just by placing .vue files in the pages directory.

https://nuxt.com/docs/getting-started/routing

Vuex

What is Vuex?

  • A state management pattern + library for Vue.js applications.
    • Heavily influenced by Flux as a state management pattern (described later).
  • Guarantees rules that state changes only occur in predictable ways.
    • If state can be changed anywhere in the application, it becomes difficult to track where changes occurred, making debugging hard.
  • Acts as a centralized store for all components in the application.
    • Allows sharing state between multiple components.
    • However, from another perspective, it can be seen as a "global variable," so it is not desirable to share everything.

https://vuex.vuejs.org/

What is Flux?

  • Data flows in a single direction.
    • Makes it easier to track state changes.
  • Action: An object representing an operation from the user.
  • Dispatcher: Receives an Action and passes it to the Store.
  • Store: A place to hold data. It receives an Action, changes the data, and notifies of the change.
  • View: Displays the data from the Store.


↑ Quoted from https://github.com/facebookarchive/flux/tree/main/examples/flux-concepts

In Vuex...

  • Action: An object representing an operation from the user. It executes data processing such as calling APIs.
  • Mutations: The only way to change the state. It can be executed by being committed from an Action.
  • State: The place where data is held. It notifies of changes.
  • Vue Components: These display the data from the State and dispatch Actions.


↑ Quoted from https://vuex.vuejs.org/

Since concepts alone can be difficult to understand, here are some code examples.
I'll explain using a simple counter.

store.ts
import { createStore } from 'vuex';

createStore({
  // Data managed in the store.
  state: () => ({
    counter: 0,
  }),
  // Methods called by dispatch.
  actions: {
    increment({ commit }) {
      commit("INCREMENT");
    },
  },
  // Methods that change the state.
  mutations: {
    INCREMENT(state) {
      state.counter++;
    },
  },
});
ButtonCounter.vue
<template>
  <button @click="increment">{{ counter }}</button>
</template>

<script>
import { defineComponent } from "vue";

export default defineComponent({
  computed: {
    // Retrieve the counter from the store.
    // The retrieved value can be used in the template.
    counter() {
      return this.$store.state.counter;
    },
  },
  methods: {
    // When the button is clicked,
    // dispatch "increment" to the store.
    increment() {
      this.$store.dispatch("increment");
    },
  },
});
</script>

In practice, it is often used by dividing it into modules.
In Nuxt 2, it can be easily utilized by using the store directory.

https://v2.nuxt.com/docs/directory-structure/store

Also, while Vuex was built into Nuxt 2, it is no longer included in Nuxt 3. When using a state management library, Pinia is recommended, and you need to follow a simple introduction procedure separately.

https://nuxt.com/docs/getting-started/state-management

What is Nuxt.js

  • A framework for building Vue.js applications.
  • It absorbs challenges such as difficult environment preparation and confusing directory structures.
  • By using Nuxt.js, you get a de-facto standard configuration for building applications with Vue.js.

Nuxt.js includes the following elements plus various settings for utilizing them.

Category Nuxt 2 Nuxt 3
Vue Vue 2 Vue 3
Routing Vue Router 3 Vue Router 4
State Management Vuex None (Choose from useState, Pinia, etc.)
SSR vue-server-renderer vue/server-renderer
Meta Tag Management vue-meta @unhead/vue
Bundler Webpack 4 + Babel Vite or Webpack 5
Server Express nitro, h3
Testing Jest Vitest

In development with Nuxt.js, you can basically use your Vue.js knowledge as is.
Additionally, there are directory structures and functions unique to Nuxt, so those need to be learned separately as needed.

https://nuxt.com/docs/getting-started

GitHubで編集を提案

Discussion