初めてのVue⑧Viteを使ってみよう

初めてのVue⑧Viteを使ってみよう

Vueについて基本を学んだところで、今回からViteを使っていきましょう。ViteはVueのフレームワークでより簡単にUIを作ることができます。書き方が変わるので戸惑うかもしれませんが、慣れてきたら作業が捗るので覚えていきましょう。

この記事の対象者
  • Vueをもっと効率よく書きたい
  • Viteってなに?
  • Viteの環境構築がしたい

Viteを使ってみよう

まずはターミナルでVueのパッケージのインストールを行います。

npm init vue@latest

色々聞かれますが、下記のような感じで答えていきます。

Need to install the following packages:
  create-vue@3.9.1
Ok to proceed? (y) y

Vue.js - The Progressive JavaScript Framework

✔ Project name: … my-first-vue-project
✔ Add TypeScript? … No / Yes (NO)
✔ Add JSX Support? … No / Yes (NO)
✔ Add Vue Router for Single Page Application development? … No / Yes (Yes)
✔ Add Pinia for state management? … No / Yes (NO)
✔ Add Vitest for Unit Testing? … No / Yes (NO)
✔ Add an End-to-End Testing Solution? › No
✔ Add ESLint for code quality? … No / Yes (Yes)
✔ Add Prettier for code formatting? … No / Yes (Yes)

最後に下記のようなメッセージが出るのでcd以降を実行していきます。

まとめてコピペで大丈夫です。

Done. Now run:

  cd my-first-vue-project(Viteのインストール先のフォルダの名前です。)
  npm install
  npm run format
  npm run dev

最後のnpm run devで下記のようなメッセージが出れば成功です。

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

ブラウザで確認していきます。

ファイルも見ていきましょう。

たくさんあってどれから手をつけていけばいいのか分からなくなりますね。

まずはindex.htmlです。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

main.jsからappを持ってきてるだけですね。

では、main.jsを見てみます。

import './assets/main.css' //cssの設定

import { createApp } from 'vue' //createAppをインポート
import App from './App.vue' //App.vueをインポート
import router from './router' //routerの設定

const app = createApp(App)

app.use(router)

app.mount('#app')

やっていることはApp.vueとrouterの設定ですね。

まずはApp.vueから見ていきましょう。

<script setup>
import { RouterLink, RouterView } from 'vue-router'
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
  <header>
    <img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />

    <div class="wrapper">
      <HelloWorld msg="You did it!" />

      <nav>
        <RouterLink to="/">Home</RouterLink>
        <RouterLink to="/about">About</RouterLink>
      </nav>
    </div>
  </header>

  <RouterView />
</template>

<style scoped>
//省略
</style>

やっとブラウザで確認した時のコードが出てきましたね。

もし、コードがエディタでうまく認識されない場合は下記が参考になります。(SublimeText使っている人向けです。)

https://qiita.com/ta_morimoto/items/16461c99bb339f1c8d13

では、次にrouterのindex.jsを見てみましょう。

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeView
    },
    {
      path: '/about',
      name: 'about',
      component: () => import('../views/AboutView.vue')
    },
  ]
})

export default router

渡ってきたパスからどのファイルを表示するかを設定している場所です。

今使われているのはHomeView.vueとAboutView.vueであることがわかります。

App.vueの中にどちらもありましたね。

新しくページを作ってみよう

では、ここにContactviewを作っていきましょう。

まずはAboutView.vueを複製してContactView.vueとし、aboutとなっている箇所をcontactにします。

<template>
  <div class="contact">
    <h1>This is an contact page</h1>
  </div>
</template>

<style>
@media (min-width: 1024px) {
  .contact {
    min-height: 100vh;
    display: flex;
    align-items: center;
  }
}
</style>

次にApp.vueにContactViewにアクセスするためのタブを追加しましょう。

<nav>
  <RouterLink to="/">Home</RouterLink>
  <RouterLink to="/about">About</RouterLink>
  <RouterLink to="/contact">Contact</RouterLink> //追加
</nav>

最後にrouterを修正します。

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
//追加
import ContactView from '../views/ContactView.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeView
    },
    {
      path: '/about',
      name: 'about',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('../views/AboutView.vue')
    },
//追加
    {
      path: '/contact',
      name: 'contact',
      component: ContactView
    }
  ]
})

export default router

ではブラウザで確認します。

Contactにアクセスするとこんな画面になると思います。

ちなみに、App.vueに出てきた下記のタブはページの再読み込みをすることなく、RouterViewを変更できます。

<RouterLink to="/">Home</RouterLink>
<RouterView />

もちろん、フレームワークのおかげですが、aタブとは別の使い方ができるので覚えておきましょう。

HomeViewを見てみよう

続いて、HomeView.vueについても簡単に紹介します。

まずはブラウザで確認します。

この右側がHomeViewのコードです。

ではコードを確認しましょう。

<script setup>
import TheWelcome from '../components/TheWelcome.vue'
</script>

<template>
  <main>
    <TheWelcome />
  </main>
</template>

TheWelcomeを使っているのが分かります。

余談ですが、the-welcomeもTheWelcomeと同じように認識されます。

ただし、TheWelcome(パスカルケースと呼ばれる書き方)で書いたほうがHTML要素と見分けがつきやすいため、お勧めされています。

では、TheWelcomeを見ていきましょう。

<script setup>
import WelcomeItem from './WelcomeItem.vue'
import DocumentationIcon from './icons/IconDocumentation.vue'
import ToolingIcon from './icons/IconTooling.vue'
import EcosystemIcon from './icons/IconEcosystem.vue'
import CommunityIcon from './icons/IconCommunity.vue'
import SupportIcon from './icons/IconSupport.vue'
</script>

<template>
  <WelcomeItem>
    <template #icon>
      <DocumentationIcon />
    </template>
    <template #heading>Documentation</template>

    Vue’s
    <a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
    provides you with all information you need to get started.
  </WelcomeItem>

  <WelcomeItem>
    <template #icon>
      <ToolingIcon />
    </template>
    <template #heading>Tooling</template>

    This project is served and bundled with
    <a href="https://vitejs.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
    recommended IDE setup is
    <a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a> +
    <a href="https://github.com/johnsoncodehk/volar" target="_blank" rel="noopener">Volar</a>. If
    you need to test your components and web pages, check out
    <a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a> and
    <a href="https://on.cypress.io/component" target="_blank" rel="noopener"
      >Cypress Component Testing</a
    >.

    <br />

    More instructions are available in <code>README.md</code>.
  </WelcomeItem>

  <WelcomeItem>
    <template #icon>
      <EcosystemIcon />
    </template>
    <template #heading>Ecosystem</template>

    Get official tools and libraries for your project:
    <a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
    <a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
    <a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
    <a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
    you need more resources, we suggest paying
    <a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
    a visit.
  </WelcomeItem>

  <WelcomeItem>
    <template #icon>
      <CommunityIcon />
    </template>
    <template #heading>Community</template>

    Got stuck? Ask your question on
    <a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>, our official
    Discord server, or
    <a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
      >StackOverflow</a
    >. You should also subscribe to
    <a href="https://news.vuejs.org" target="_blank" rel="noopener">our mailing list</a> and follow
    the official
    <a href="https://twitter.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
    twitter account for latest news in the Vue world.
  </WelcomeItem>

  <WelcomeItem>
    <template #icon>
      <SupportIcon />
    </template>
    <template #heading>Support Vue</template>

    As an independent project, Vue relies on community backing for its sustainability. You can help
    us by
    <a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
  </WelcomeItem>
</template>

長いですが、ブラウザで確認した時のコードが出てきましたね。

WelcomeItemというタブがよく使われているのが分かるのでWelcomeItem.vueも確認していきましょう。

<template>
  <div class="item">
    <i>
      <slot name="icon"></slot>
    </i>
    <div class="details">
      <h3>
        <slot name="heading"></slot>
      </h3>
      <slot></slot>
    </div>
  </div>
</template>

<style scoped>
//省略
</style>

slotが多く使われテンプレートになっているのが分かります。

これで少しはファイルの基本的な構成が頭の中に入ったと思います。

Setupとは?

続いて、Setupについて解説します。

今まで気になってたかも知れませんが、下記のような記載がありました。

<script setup>

このSetupってなんでしょう?

HomeView.vueで解説しようと思います。

<script>
import TheWelcome from '../components/TheWelcome.vue'

//追加
export default{
  components: {TheWelcome},

//messageという変数を設定
  data(){
    return{
      message: "Hello",
    };
  },
//ページを読み込んだときにアラートを出す
  mounted(){
    alert("mounted");
  },
};
</script>

<template>
  <main>
    <TheWelcome />
//追加
    <p>{{message}}</p>
  </main>
</template>

Setupを使わない親しみのある書き方でコードを追加しました。

ブラウザで確認します。

良いですね、アラートが出てきて、下にHelloが出てました。

次にScript setupではなくsetup関数を使って書いてみます。コードも少し足します。

<script>
import TheWelcome from '../components/TheWelcome.vue';
//追加
import {onMounted, ref} from "vue";

export default{
  components:{TheWelcome},

//追加とSetupの中で使うように変更
  setup(){

//MountedからonMountedに変更
    onMounted(()=>{
      alert("mounted");
    });

//dataからletに変更,refで囲うことでリアクティブに動くようになる
    let message = ref("Hello");

//messageを使えるようにreturn
    return{
       message,
     };
   }
//refを使うとアクセスするときに.valueが必要になるため、message.valueとなっています。
    setTimeout(()=>{
      message.value = "Changed";
    },3000)
}
</script>

<template>
  <main>
    <TheWelcome />

    <p>{{message}}</p>
//追加
    <input type="text" v-model="message">
  </main>
</template>

ブラウザで確認します。

最初はHelloで3秒経つとChangedに変わりました。

setup関数を使うことでComposition API を使うことができるようになります。

Composition API というのは下記のように説明されています。

とりあえずは、便利なAPIぐらいに思っておいてください。

Composition API を使うことでmounted関数がonMounted関数になり、data関数がletとreturnになりました。

ただし、setup関数を使うぐらいならscriptタグにsetupを加えることが推奨されており、下記のコードに変換できます。

<script setup>
import TheWelcome from '../components/TheWelcome.vue';
import {onMounted, ref} from "vue";

  onMounted(()=>{
    alert("mounted");
  });

  let message = ref("Hello");

  setTimeout(()=>{
    message.value = "Changed";
  },3000);
</script>

<template>
  <main>
    <TheWelcome />

    <p>{{message}}</p>
    <input type="text" v-model="message">
  </main>
</template>

今までのexport defaultがなくなり、setupもなくなったのでスッキリしましたね。

ブラウザはさっきと変わらない動きです。

変数も定義すればreturnすることなく使用できます。

setupのメリットをあまり感じないかも知れませんが、慣れれば便利に感じると思います。

関連記事