LoginSignup
1
2

More than 1 year has passed since last update.

ViteでVue3+TypeScript+TailwindCSS+axiosの雛形アプリを作ってみる

Posted at

目的

Viteでvue3とTailwind.cssの導入をやってみます。

Tailwind CSS with Vite
の導入そのままですが、TypeScriptにしているのと、実際に生成すると一部は追記するような形になります。

それだけだと、つまらないので以前Nuxt3でHeadlessCMSという記事で書いたHeadlessCMSのAPIを呼び出して表示してみます。

導入

npm create vite@latest my-vue-app -- --template vue-ts
cd my-vue-app
npm install
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
tailwind.config.cjs
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./index.html",
    "./src/**/*.{vue,js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
style.css
@tailwind base;
@tailwind components;
@tailwind utilities;

// ...以降元のCSS
App.vue
<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
  <div>
    <a href="https://vitejs.dev" target="_blank">
      <img src="/vite.svg" class="logo" alt="Vite logo" />
    </a>
    <a href="https://vuejs.org/" target="_blank">
      <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
    </a>
  </div>
  <HelloWorld msg="Vite + Vue" />
<!-- ↓↓↓↓↓↓↓↓↓↓追加分↓↓↓↓↓↓↓↓↓↓ -->
  <h1 class="text-3xl font-bold underline">
    Hello world!
  </h1>
<!-- ↑↑↑↑↑↑↑↑↑↑追加分↑↑↑↑↑↑↑↑↑↑ -->
</template>

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

npm run dev

これでTailwindCSSを利用したサンプルが表示されます。

HeadlessCMS

HeadlessCMSを使ってブログの一覧を表示するコンポーネントを作っていきます。

まずは通信するライブラリaxiosを読み込みます。

npm install axios

モデルや通信部分を作成していいきます。

models/Blog.ts
import { Content } from "./Content";

export interface Blog {
    contents: Content[],
    totalCount: number,
    offset: number,
    limit: number,
}
models/Content.ts
import { Category } from "./Category";
import { Eyecatch } from "./Eyecatch";

export interface Content {
    id: string,
    createdAt: string,
    updatedAt: string,
    publishedAt: string,
    revisedAt: string,
    title: string,
    content: string,
    eyecatch: Eyecatch,
    category: Category,
}
models/Category.ts
export interface Category {
    id: string,
    createdAt: string,
    updatedAt: string,
    publishedAt: string,
    revisedAt: string,
    name: string,
}
models/Eyecatch.ts
export interface Eyecatch {
    url: string,
    height: number,
    width: number,
}
services/BlogService.ts
import axios from "axios";
import { Blog } from "../models/Blog";

class BlogService {
    private URL = "https://xxxxx.microcms.io/api/v1/blogs"

    public async getBlog(): Promise<Blog> {
        const res  = await axios.get<Blog>(this.URL, {headers: {
            "X-MICROCMS-API-KEY": "xxxxxxxxxx"
        }})
        return res.data
    }
}

export default new BlogService()

タイトルを表示するコンポーネント

components/BlogView.vue
<script lang="ts">
import { defineComponent } from 'vue'
import blogService from '../services/BlogService'

export default defineComponent({
  name: 'BlogView',
  async setup(props) {
    const blog = await blogService.getBlog()
    return {
      blog,
    }
  }
})
</script>

<template>
  <h1>{{ blog.totalCount }}</h1>
  <ol>
    <li v-for="item in blog.contents" :key="item.id">{{item.title}}</li>
  </ol>
</template>

コンポーネントを組み込みました。追加したのはSuspenseのタグの部分です。

App.vue
<script setup lang="ts">
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
import BlogView from './components/BlogView.vue';
</script>

<template>
  <div>
    <a href="https://vitejs.dev" target="_blank">
      <img src="/vite.svg" class="logo" alt="Vite logo" />
    </a>
    <a href="https://vuejs.org/" target="_blank">
      <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
    </a>
  </div>
  <HelloWorld msg="Vite + Vue" />
  <h1 class="text-3xl font-bold underline">
    Hello world!
  </h1>
  <Suspense>
    <template #default>
      <BlogView/>
    </template>
    <template #fallback>
      Loading...
    </template>
  </Suspense>
</template>

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

まとめ

ほら簡単でしょ、といいたいところですがmodelsのinterfaceを書くところが面倒くさかったです。本家がそれっぽいライブラリを用意しているっぽいのでそっちを使った方が良いでしょう。

また、最初はSuspenseを使わないで表示しようとしていたら、まったく表示されなくって悩みました。理解できれば、驚くほど便利な機能だと思いました。

これでちょっとしたサイトを作るのに、導入のテンプレートとして利用できそうです。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2