Получение постов с WordPress в Nuxt3

В данной статье расскажем как получать посты с сайта на WordPress используя фреймворк NuxtJS. Мы будем работать с Rest API…

Напишите нам, мы онлайнОтветим в течении 5 минут

В данной статье расскажем как получать посты с сайта на WordPress используя фреймворк NuxtJS.

Мы будем работать с Rest API WordPress-а.

Для начала создадим страницы для постов в нашем nuxt приложении. Структура папок и файлов сделаем такую:

pages
-blog
--index.vue
--[slug].vue

Еще нам необходимо создать компонент самого поста в папке components. Создадим файл PostItem.vue

Преступим к написанию компонента:

<script setup>
    const props = defineProps({
        title: String,
        permalink: String,
        preview: String,
        text: String,
        date: String,
    });
</script>
<template>
    <div class="post-item">
        <div class="post-item__preview">
            <img :src="preview" :title="title" alt="">
        </div>
        <div class="post-item__date"><span>{{ date }}</span></div>
        <div class="post-item__title">
            <NuxtLink :to="permalink">
                <span v-html="title"></span>
            </NuxtLink>
        </div>
        <div class="post-item__text" v-html="text"></div>
    </div>
</template>
<style>
    .post-item {
        width: 100%;
        margin-bottom: 25px;
    }
    .post-item .post-item__preview {
        position: relative;
        width: 100%;
        height: 350px;
        margin-bottom: 15px;
    }
    .post-item .post-item__date {
        font-size: 12px;
        margin-bottom: 10px;
    }
    .post-item .post-item__preview img {
        width: 100%;
        height: 100%;
        position: absolute;
        left: 0;
        top: 0;
        object-fit: cover;
    }
    .post-item .post-item__title {
        font-size: 16px;
        margin-bottom: 15px;
    }
    .post-item .post-item__title a {
        color: #051f4f;
        font-size: 21px;
        font-weight: 600;
        text-decoration: none;
    }
    .post-item .post-item__text {
        font-size: 14px;
    }
</style>

Теперь перейдем к самим страницам наших постов:

Файл index.vue — в нём мы будем выводить все посты

<script setup>
    let posts = ref([]);
    let url = 'https://вашсайт.ru/wp-json/wp/v2/posts';
    const { data: post, refresh } = await useFetch(url, {
        method: 'GET',
        server: true,
        refetch: true,
        onResponseError({ request, response, options }) {
            console.log('Ошибка запроса');
        }
    });
    posts.value = post.value;
</script>
<template>
    <div class="posts">
        <PostItem v-for="post in posts" :title="post.title.rendered" :permalink="`/blog/${post.slug}/`" :date="post.date_time" :text="post.excerpt.rendered" :preview="post.featured_image_thumbnail_url"/>
    </div>
</template>
<style>
    .posts {
        width: 700px;
        margin: 0 auto;
    }
</style>

Файл [slug].vue — будет у нас для отображение полного поста

<script setup>
    const route = useRoute();
    let slug = route.params.slug;
    let url = `https://вашсайт.ru/wp-json/wp/v2/posts`;
    const {data: post, error, refresh} = await useFetch(url, {
        method: 'GET',
        refetch: true,
        params: {
            slug: slug
        },
        server: true,
        onResponseError({ request, response, options }) {
            console.log('Ошибка запроса')
        },
    });
    const postContent = await post.value?.[0];
    if(post.value.length == 0) {
        throw createError({
            statusCode: 404,
            message: 'Публикация не найдена',
            fatal: true
        })
    }
    useHead({
        title: `${postContent.title.rendered}`,
        meta: [
            {
                property: 'og:title',
                content: `${postContent.title.rendered}`
            }
        ]
    });
</script>
<template>
    <div class="post-inner">
        <div class="post-inner__title"><h1 v-html="postContent.title.rendered"></h1></div>
        <div class="post-inner__preview">
            <img :src="postContent.featured_image_thumbnail_url" :title="postContent.title.rendered" alt="">
        </div>
        <div class="post-inner__date"><span v-text="post.date_time"></span></div>
        <div class="post-inner__text" v-html="postContent.content.rendered"></div>
    </div>
</template>
<style>
    .post-inner {
        width: 700px;
        margin: 0 auto;
    }
    .post-inner img {
        width: 100%;
        height: auto;
        display: block;
    }
</style>

Теперь нам нужно добавить свои поля в REST WordPress-а. Открываем файл темы functions.php и добавляем туда следующий код:

function preview_rest( $data, $post, $request ) {
    $_data = $data->data;
    $thumbnail_id = get_post_thumbnail_id( $post->ID );
    $thumbnail = wp_get_attachment_image_src( $thumbnail_id, 'large' );
    $_data['featured_image_thumbnail_url'] = $thumbnail[0];
    unset($_data['featured_image']);
    $data->data = $_data;
    return $data;
}
function post_date_rest( $data, $post, $request ) {
    $_data = $data->data;
    $_data['date_time'] = get_the_date('j F Y', $post->ID);
    $data->data = $_data;
    return $data;
}
add_filter( 'rest_prepare_post', 'preview_rest', 10, 3 );
add_filter( 'rest_prepare_post', 'post_date_rest', 10, 3 );

Данные поля нужны нам для вывода превью, и вывода даты поста в своем формате

Заходим на страницу /blog/ видим посты:

Теперь на страницу поста:

Вот таким не сложным способом можно взаимодействовать с REST API WordPress-а и выводить посты в ваше приложение на NuxtJS