みなさんこんにちは!
イザナギです。
さて!前回に引き続き、Nuxt3でブログを作っていた時の話を書いていきたいと思います。
私はヘッドレスCMSとして、microcmsを利用しているのですが、vueファイル内でuseFeachを利用して、ブログデータを取得しようとしていました。
しかし、ブラウザで確認してみるとCORSエラーが炸裂!
何!?表示できないだと...
対応策を調べてみると、サクッと見つかりました。(同じような事象に悩んでいた先人がいらっしゃいました。)
https://qiita.com/tikaranimaru/items/bbbd1f972dc238121d03
なるほど!こういう時に「server」フォルダを使うのですね。
import type { IncomingMessage, ServerResponse } from "http";
import axios from 'axios'
import config from '#config'
let url: string = `https://${config.MICRO_CMS_SERVICE_DOMAIN}.microcms.io/api/v1/blog`
const API_HEAD = {
headers: {
"X-MICROCMS-API-KEY": config.MICRO_CMS_API_KEY,
}
}
export default async (req: IncomingMessage, res: ServerResponse) => {
if (req.method != 'GET') {
console.log(req.method)
res.statusCode = 500
res.end()
}
let data: Array
await axios.get(
`${url}`,
API_HEAD
).then(res => {
data = res.data;
});
const json = JSON.stringify(data)
res.statusCode = 200
res.setHeader('Content-Type', 'application/json')
res.end(json)
}
上記のように「server/api/microcms.ts」というファイルを作成すると、「localhost:3000/api/microcms」にmicrocmsのjsonデータが出力されるようになりました!(上記コードは「rc.12」までは使用できましたが、「rc.13」から使えなくなっていました...。使えるように修正したコードは、ページ下「追記(2022/10/19):」を参照ください!)
なるほど。
こっからuseFeachしてくれば良いということね!
早速、vueファイル内に以下を記述し実行してみます。(Swiperと組み合わせてみました。)
<template>
<v-container id="blog_caloucel_box" class="mx-auto">
<h2 class="text-center text-h2">Latest Article</h2>
<swiper
:modules="modules"
:slides-per-view="views"
:autoplay="{ disableOnInteraction: false, }"
>
<swiper-slide v-for="content in data['contents']" :key="content.id">
<a :href="`/blog/articles/${content.id}`">
<picture>
<source :srcset="`${content.thumbnail.url}?fm=webp&h=${imageWidth}`" />
<img :src="`${content.thumbnail.url}?h=${imageWidth}`" />
</picture>
<p>{{ content.title }}</p>
</a>
</swiper-slide>
</swiper>
</v-container>
</template>
<script>
// import Swiper core and required modules
import { A11y, Autoplay } from 'swiper';
// Import Swiper Vue.js components
import { Swiper, SwiperSlide } from 'swiper/vue';
// Import Swiper styles
import 'swiper/css';
// Import Swiper styles
export default {
components: {
Swiper,
SwiperSlide,
},
setup() {
let views = ref(0);
let { data } = useFetch("/api/microcms")
const imageWidth = ref(300);
const calculateWindowWidth = () => {
let windowWidth = window.innerWidth
views.value = Math.floor(windowWidth / imageWidth.value)
}
onMounted(() => {
calculateWindowWidth();
window.addEventListener('resize', calculateWindowWidth)
})
onBeforeUnmount(() => {
window.addEventListener('resize', calculateWindowWidth)
})
return {
modules: [A11y, Autoplay],
data,
views,
imageWidth,
};
},
};
</script>
<style lang="scss" scoped>
img {
width: 100%;
height: 200px;
position: relative;
}
p {
position: absolute;
color: white;
top: 75%;
width: 100%;
margin: 0;
padding: 0;
height: 22%;
background-color: rgba(129, 212, 250, 0.5);
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
@media screen and (max-width: 600px) {
p {
top: 85%;
-webkit-line-clamp: 1;
}
}
h2 {
margin-bottom: 10vw;
font-family: Great Vibes !important;
}
#blog_caloucel_box {
// max-width: 80%;
// margin: 0 auto;
padding: 0 10px;
margin-bottom: 100px;
margin-top: 20vw;
}
</style>
うまく表示できてますね!
そしてちゃっかり、Swiper8も使えることも確認!
さてどんどんブログの作成進めていきますか〜
追記(2022/10/19):
rc.12にアップデートした際に、「defineEventHandler」を代わりに使ってね!みたいなエラーが発生したので、
「server」フォルダ配下に作成したmicrocmsの記事取得用のコードを以下のように修正。
※「defineEventHandler」を使う以外にも多少改造してます。
const config = useRuntimeConfig();
let url: string = `https://${config.MICRO_CMS_SERVICE_DOMAIN}.microcms.io/api/v1/blog`
export default defineEventHandler(async (event) => {
const q = getQuery(event);
const post_id: string = !!q.id ? "/" + q.id : "";
const post_offset = !!q.offset ? q.offset : "";
const post_limit = !!q.limit ? q.limit : "10";
const post_order = !!q.order ? q.order : "";
const post_fields = !!q.fields ? q.fields : "";
const filter = q.filter ? `${q.filterKeyName}[contains]${q.filter}` : "";
const query = !!q.query ? q.query : "";
const parameters: string = `${post_id}?fields=${post_fields}&filters=${filter}&limit=${post_limit}&offset=${post_offset}&orders=${post_order}&q=${query}`;
const ENDPOINT: string = url + encodeURI(parameters);
let data: unknown;
await $fetch(`${ENDPOINT}`, {
method: "GET",
headers: {
"X-MICROCMS-API-KEY": config.MICRO_CMS_API_KEY,
'Content-Type': 'application/json',
'Accept-Encoding': 'gzip',
'Accept-Charset': 'utf-8',
'Content-Encoding': 'gzip',
}
}
).then((response) => {
data = response
})
const json = data
return json;
})