Vue、GraphQL、およびApolloクライアントを使用してブログを構築する方法
序章
この記事では、GraphQLサーバーを利用するブログを作成します。 ApolloクライアントとVueを使用してブログアプリを構築します。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- Node.jsはローカルにインストールされます。これは、Node.jsのインストール方法とローカル開発環境の作成に従って実行できます。
- MySQLがローカルにインストールされ、実行されています。これは、MySQLのインストール方法に従って実行できます。
このチュートリアルは、JavaScriptの知識と、VueおよびGraphQLにある程度精通していることを前提としています。
このチュートリアルは、ノードv14.4.0、npm
v6.14.5、MySQL v14.14、@adonisjs/cli
v4.0.12、@vue/cli
v4.4.6、[X120X ] v2.5.2、graphql
v15.1.0、およびapollo-client
v2.6.10。
GraphQLサーバーの作成
GraphQLサーバーを入手して、チュートリアルを進めることができます。
リポジトリのクローンを作成したら、GraphQLサーバーのプロジェクトディレクトリに移動します。
cd adonis-graphql-server
必要なパッケージをインストールします。
npm install
.env.example
を.env
にコピーします。
cp .env.example .env
必要に応じて.env
ファイルを編集して、データベース情報が実行中のMySQLデータベースの適切な資格情報を提供するようにします。 DB_USER
とDB_PASSWORD
の変更が必要になる場合があります。
アドニスのキーを生成します。
npx @adonisjs/cli key:generate
データベース構成を移行します。
npx @adonisjs/cli migration:run
CORSの有効化
GraphQLサーバーはAdonisJSで構築されました。 AdonisJSは、APIでクロスオリジンリソースシェアリング(CORS)を処理するために使用できるパッケージを提供します。 AdonisJSではデフォルトでCORSがオフになっているため、有効にする必要があります。
AdonisJSアプリでCORSを有効にするには、config/cors.js
でorigin
をtrue
に次のように設定します。
config / cors.js
origin: true
クローン化されたGraphQLサーバーではCORSがすでに有効になっていますが、言及する価値があります。
GraphQLサーバーの起動
ブログアプリはGraphQLサーバーを利用するため、サーバーを起動して、チュートリアルの残りの部分でサーバーを実行し続ける必要があります。
開始するには、GraphQLサーバーのプロジェクトディレクトリにいることを確認し、以下のコマンドを実行します。
npx @adonisjs/cli serve --dev
これにより、GraphQLサーバーが起動し、実行を継続します。
チュートリアルの残りの部分では、GraphQLサーバーが既に起動されており、実行されていることを前提としています。
それが済んだら、ブログアプリの作成を始めましょう。
ステップ1—Vueアプリを作成する
まず、VueCLIを使用して新しいVueアプリを作成します。
npx -p @vue/cli -p @vue/cli-init vue init webpack graphql-blog-app
注:最新のVueプロジェクトは以下を利用できます:
npx @vue/cli create graphql-blog-app
プロジェクトに関する質問が表示されます。 行われた選択のいくつかを次に示します。 このチュートリアルでは、vue-router
をインストールすることが重要になります。
? Project name graphql-blog-app ? Project description A Vue.js project ? Vue build standalone ? Install vue-router? Yes ? Use ESLint to lint your code? Yes ? Pick an ESLint preset Standard ? Set up unit tests No ? Setup e2e tests with Nightwatch? No ? Should we run `npm install` for you after the project has been created? (recommended) npm
これにより、graphql-blog-app
という名前の新しいVueアプリが作成され、その依存関係がインストールされます。
新しく作成されたディレクトリに移動します。
cd graphql-blog-app
アプリケーションは、端末で次のコマンドを実行することにより、いつでもブラウザで実行および表示できます。
npm start
ステップ2—パッケージのインストール
アプリを作成したら、GraphQLブログアプリの構築に必要なパッケージのインストールに進むことができます。
npm install --save vue-apollo graphql apollo-client apollo-link apollo-link-context apollo-link-http apollo-cache-inmemory graphql-tag
各パッケージを簡単に見ていきましょう。
vue-apollo
:VueJS用のApollo/GraphQL統合。 プラグインの最新バージョンをインストールして、Apolloクライアント2.0に付属するすべての優れた機能を使用できるようにします。graphql
:JavaScript用のGraphQLのリファレンス実装。apollo-client
:すべてのサーバーまたはUIフレームワーク用のフル機能の本番環境対応のキャッシングGraphQLクライアント。apollo-link
:GraphQLリクエストの制御フローを変更し、GraphQL結果をフェッチするための標準インターフェース。apollo-link-context
:操作のコンテキストを設定するために使用されます。これは、チェーンのさらに下流にある他のリンクによって使用されます。apollo-link-http
:HTTPフェッチを使用してネットワーク経由でGraphQLの結果を取得するために使用されます。apollo-cache-inmemory
:ApolloClient2.0のキャッシュ実装。graphql-tag
:GraphQLクエリを解析するJavaScriptテンプレートリテラルタグ。
ステップ3—VueApolloを設定する
次に、使用するパッケージを配置しましょう。 まず、ApolloClient
インスタンスを作成し、VueApollo
プラグインをインストールします。 src/main.js
を開き、以下のコードを追加します。
src / main.js
// ... import { ApolloClient } from 'apollo-client' import { HttpLink } from 'apollo-link-http' import { InMemoryCache } from 'apollo-cache-inmemory' import VueApollo from 'vue-apollo' const httpLink = new HttpLink({ // URL to graphql server, you should use an absolute URL here uri: 'http://localhost:3333/graphql' }) // create the apollo client const apolloClient = new ApolloClient({ link: httpLink, cache: new InMemoryCache() }) // install the vue plugin Vue.use(VueApollo)
GraphQLサーバーのURL(http://localhost:3333/graphql
)を使用して、httpLink
の新しいインスタンスを作成します。 次に、上記で作成したhttpLink
を使用してApolloクライアントを作成し、メモリ内キャッシュが必要であることを指定します。 最後に、VueApolloプラグインをインストールします。
次に、ルートコンポーネントで指定するapolloProvider
オブジェクトを作成しましょう。
src / main.js
// ... const apolloProvider = new VueApollo({ defaultClient: apolloClient }) // update Vue instance by adding `apolloProvider` /* eslint-disable no-new */ new Vue({ el: '#app', router, apolloProvider, template: '<App/>', components: { App } })
デフォルトのクライアントとして作成されたapolloClient
を使用して、VueApolloプラグインの新しいインスタンスを作成します。 最後に、apolloProvider
オブジェクトをVueインスタンスに追加することで利用します。これは、Vueルーターを使用する場合と同じ方法です。
ステップ4—ブルマを追加する
このチュートリアルでは、 BullmaCSSを使用します。 それでは、に追加しましょう。 index.html
を開き、以下のように更新します。
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>GraphQL Blog App</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.1/css/bulma.min.css"> </head> <body> <div id="app"></div> <!-- built files will be auto injected --> </body> </html>
このコンテンツ配信ネットワーク(CDN)でBulmaを参照します。
ステップ5—未使用のコードを削除する
このチュートリアルでは使用しないVueアプリを作成したときに、いくつかのファイルとコードが付属していました。 それらがアプリに干渉しないように、それらを削除しましょう。
HelloWorld
コンポーネントを削除し、そのすべての参照をsrc/router/index.js
から削除します。
ステップ6—プライマリレイアウトを作成する
ブログは、ページ全体で一般的なレイアウトを使用します。 その場合、すべてのページが使用するレイアウトを定義しましょう。 これを行うには、src/App.vue
を開き、以下のように更新します。
src / App.vue
<template> <div id="app"> <nav class="navbar is-primary" role="navigation" aria-label="main navigation"> <div class="container"> <div class="navbar-brand"> <router-link class="navbar-item" to="/">Blog App</router-link> <button class="button navbar-burger"> <span></span> <span></span> <span></span> </button> </div> </div> </nav> <router-view/> </div> </template> <script> export default { name: 'app' } </script>
すべてのページが使用するヘッダーを追加します。
ステップ7—ユーザーサインアップページの作成
ユーザーはブログアプリにサインアップできるはずです。 それを処理するSignUp
コンポーネントを作成します。 したがって、src/components
内に新しいAdmin
フォルダーを作成します。 管理者関連のすべてのコンポーネントは、このフォルダー内に作成されます。
SignUp
コンポーネントを作成する前に、すべてのGraphQLクエリとミューテーションを保持する専用ファイルを作成しましょう。 このファイルはsrc
内に直接作成します。 src
内にgraphql.js
ファイルを作成し、以下のコードを貼り付けます。
src /graphql.js
import gql from 'graphql-tag' export const SIGNUP_MUTATION = gql` mutation SignupMutation($username: String!, $email: String!, $password: String!) { createUser( username: $username, email: $email, password: $password ) { id username email } } `
これは、GraphQLサーバーでの新しいユーザーの作成を処理するGraphQLミューテーションです。 ユーザーのユーザー名、電子メール、およびパスワードを受け取ります。 これらの変数は、SignUp
コンポーネントから渡されます。
次に、SignUp
コンポーネントを作成しましょう。 Admin
フォルダー内に、SignUp.vue
ファイルを作成し、以下のコードを貼り付けます。
src / components / Admin / SignUp.vue
<template> <section class="section"> <div class="columns"> <div class="column is-4 is-offset-4"> <h2 class="title has-text-centered">Signup</h2> <form method="POST" @submit.prevent="signup"> <div class="field"> <label class="label">Username</label> <p class="control"> <input type="text" class="input" v-model="username" /> </p> </div> <div class="field"> <label class="label">E-Mail Address</label> <p class="control"> <input type="email" class="input" v-model="email" /> </p> </div> <div class="field"> <label class="label">Password</label> <p class="control"> <input type="password" class="input" v-model="password" /> </p> </div> <p class="control"> <button class="button is-primary is-fullwidth is-uppercase">SignUp</button> </p> </form> </div> </div> </section> </template> <script> import { SIGNUP_MUTATION } from '@/graphql' export default { name: 'SignUp', data () { return { username: '', email: '', password: '' } }, methods: { signup () { this.$apollo .mutate({ mutation: SIGNUP_MUTATION, variables: { username: this.username, email: this.email, password: this.password } }) .then(response => { // redirect to login page this.$router.replace('/login') }) } } } </script>
このコンポーネントは、ユーザーがサインアップするためのフォームをレンダリングします。 フォームが送信されると、signup
メソッドが呼び出されます。 signup
メソッド内では、this.$apollo
(Vue Apolloプラグインから)で使用可能なmutate
メソッドを使用します。 以前に作成したSIGNUP_MUTATION
ミューテーションを使用し、必要な変数を渡します。 サインアッププロセスが成功すると(つまり、ユーザーが作成されると)、ユーザーをログインページ(まもなく作成します)にリダイレクトします。
サインアップルートの追加
src/router/index.js
を開き、以下のコードを追加します。
src / router / index.js
// ... import SignUp from '@/components/Admin/SignUp' // ... export default new Router({ routes: [ // add these inside the `routes` array { path: '/signup', name: 'SignUp', component: SignUp } ] })
/signup
ルートにアクセスすると、次の画像のようなサインアップフォームが表示されます。
ステップ8—ユーザーログインページの作成
ユーザーがログインする機能を追加しましょう。 ユーザーのサインアップで行ったのと同じように、最初にGraphQLミューテーションを作成しましょう。 以下のコードをsrc/graphql.js
に追加します。
src /graphql.js
export const LOGIN_MUTATION = gql` mutation LoginMutation($email: String!, $password: String!) { login( email: $email, password: $password ) } `
このGraphQLミューテーションは、GraphQLサーバーへのユーザーログインを処理します。 ユーザーのメールアドレスとパスワードを受け取ります。
次に、Admin
フォルダー内に、LogIn.vue
ファイルを作成し、以下のコードを貼り付けます。
src / components / Admin / LogIn.vue
<template> <section class="section"> <div class="columns"> <div class="column is-4 is-offset-4"> <h2 class="title has-text-centered">Login</h2> <form method="POST" @submit.prevent="login"> <div class="field"> <label class="label">E-Mail Address</label> <p class="control"> <input type="email" class="input" v-model="email" /> </p> </div> <div class="field"> <label class="label">Password</label> <p class="control"> <input type="password" class="input" v-model="password" /> </p> </div> <p class="control"> <button class="button is-primary is-fullwidth is-uppercase">Login</button> </p> </form> </div> </div> </section> </template> <script> import { LOGIN_MUTATION } from '@/graphql' export default { name: 'LogIn', data () { return { email: '', password: '' } }, methods: { login () { this.$apollo .mutate({ mutation: LOGIN_MUTATION, variables: { email: this.email, password: this.password } }) .then(response => { // save user token to localstorage localStorage.setItem('blog-app-token', response.data.login) // redirect user this.$router.replace('/admin/posts') }) } } } </script>
このコンポーネントは、ユーザーがログインするための簡単なフォームをレンダリングします。 フォームが送信されると、login
メソッドが呼び出されます。 login
メソッドでは、mutate
メソッドを使用します。 以前に作成したLOGIN_MUTATION
ミューテーションを使用し、必要な変数を渡します。 ログインプロセスが成功したら、GraphQLサーバーから取得したトークンをlocalStorageに保存し、ユーザーをリダイレクトします。
ログインルートの追加
src/router/index.js
を開き、以下のコードを追加します。
src / router / index.js
// ... import LogIn from '@/components/Admin/LogIn' // ... export default new Router({ routes: [ // ... // add these inside the `routes` array { path: '/login', name: 'LogIn', component: LogIn } ] })
/login
ルートにアクセスすると、次の画像のようなログインフォームが表示されます。
ステップ9—メニューコンポーネントの作成
ブログの管理者向けの部分を具体化する前に、サイドバーのナビゲーションメニューとして機能するMenu
コンポーネントを作成しましょう。 Admin
フォルダー内に、Menu.vue
ファイルを作成し、以下のコードを貼り付けます。
src / components / Admin / Menu.vue
<template> <aside class="menu"> <p class="menu-label">Post</p> <ul class="menu-list"> <li> <router-link to="/admin/posts/new">New Post</router-link> </li> <li> <router-link to="/admin/posts">Posts</router-link> </li> </ul> <p class="menu-label">User</p> <ul class="menu-list"> <li> <router-link to="/admin/users">Users</router-link> </li> </ul> </aside> </template>
これにより、ブログアプリの一部の管理セクションへのリンクがレンダリングされます。
ステップ10—ユーザーリストページの作成
管理セクションでは、作成されたユーザーのリストを表示できるようにする必要があります。 そのために、Users
コンポーネントを作成しました。 しかし、最初に、作成されたすべてのユーザーをフェッチするGraphQLクエリを作成しましょう。 以下のコードをsrc/graphql.js
に追加します。
src /graphql.js
export const ALL_USERS_QUERY = gql` query AllUsersQuery { allUsers { id username email } } `
このGraphQLクエリは、GraphQLサーバーからすべてのユーザーをフェッチします。
次に、Users
コンポーネントを作成しましょう。 Admin
フォルダー内に、Users.vue
ファイルを作成し、以下のコードを貼り付けます。
src / components / Admin / Users.vue
<template> <section class="section"> <div class="container"> <div class="columns"> <div class="column is-3"> <Menu/> </div> <div class="column is-9"> <h2 class="title">Users</h2> <table class="table is-striped is-narrow is-hoverable is-fullwidth"> <thead> <tr> <th>Username</th> <th>Email</th> <th></th> </tr> </thead> <tbody> <tr v-for="user in allUsers" :key="user.id"> <td>{{ user.username }}</td> <td>{{ user.email }}</td> <td> <router-link :to="`/admin/users/${user.id}`">View</router-link> </td> </tr> </tbody> </table> </div> </div> </div> </section> </template> <script> import Menu from '@/components/Admin/Menu' import { ALL_USERS_QUERY } from '@/graphql' export default { name: 'Users', components: { Menu }, data () { return { allUsers: [] } }, apollo: { // fetch all users allUsers: { query: ALL_USERS_QUERY } } } </script>
以前に作成したMenu
コンポーネントを使用します。 次に、GraphQLサーバーからデータを取得したときに入力されるデータを定義します。 apollo
オブジェクト内に、すべてのユーザーをフェッチするためのGraphQLクエリを追加します。 これは、上記で作成したALL_USERS_QUERY
を利用します。 データの名前(この場合はallUsers
)は、GraphQLクエリで使用されている名前(この場合はallUsers
)と同じである必要があることに注意してください。 allUsers
にGraphQLサーバーからのデータが入力されると、ユーザーの配列をループして、テーブルにユーザーを表示します。 また、各ユーザーの詳細を表示するためのリンクを追加します。
ユーザールートの追加
src/router/index.js
を開き、以下のコードを追加します。
src / router / index.js
// ... import Users from '@/components/Admin/Users' // ... export default new Router({ routes: [ // ... // add these inside the `routes` array { path: '/admin/users', name: 'Users', component: Users } ] })
/admin/users
ルートにアクセスすると、次の画像のようにユーザーのリストが表示されます。
ステップ11—ユーザー詳細ページの作成
最後のセクションでは、ユーザーの詳細を表示するためのリンクを追加します。 それでは、実装しましょう。 以下のコードをsrc/graphql.js
に追加します。
src /graphql.js
export const USER_QUERY = gql` query UserQuery($id: Int!) { user(id: $id) { id username email posts { id } } } `
このGraphQLクエリは、GraphQLサーバーからIDでユーザーをフェッチします。 ユーザーのIDを引数として取ります。 ユーザーIDは、UserDetails
コンポーネントから渡されます。
次に、UserDetails
コンポーネントを作成しましょう。 Admin
フォルダー内に、UserDetails.vue
ファイルを作成し、以下のコードを貼り付けます。
src / components / Admin / UserDetails.vue
<template> <section class="section"> <div class="container"> <div class="columns"> <div class="column is-3"> <Menu/> </div> <div class="column is-9"> <h2 class="title">User Details</h2> <div class="field is-horizontal"> <div class="field-label is-normal"> <label class="label">Username</label> </div> <div class="field-body"> <div class="field"> <p class="control"> <input class="input is-static" :value="user.username" readonly /> </p> </div> </div> </div> <div class="field is-horizontal"> <div class="field-label is-normal"> <label class="label">Email Address</label> </div> <div class="field-body"> <div class="field"> <p class="control"> <input class="input is-static" :value="user.email" readonly /> </p> </div> </div> </div> <div class="field is-horizontal"> <div class="field-label is-normal"> <label class="label">Number of posts</label> </div> <div class="field-body"> <div class="field"> <p class="control"> <input class="input is-static" :value="user.posts.length" readonly /> </p> </div> </div> </div> </div> </div> </div> </section> </template> <script> import Menu from '@/components/Admin/Menu' import { USER_QUERY } from '@/graphql' export default { name: 'UserDetails', components: { Menu }, data () { return { user: '', id: this.$route.params.id } }, apollo: { // fetch user by ID user: { query: USER_QUERY, variables () { return { id: this.id } } } } } </script>
指定したユーザーのユーザー名、メールアドレス、作成された投稿数を表示します。 USER_QUERY
は、詳細を表示するユーザーのIDを受け入れます。 ユーザーIDは、ルートパラメータから取得されます。 つまり、/admin/users/12
の場合、12は特定のユーザーのIDです。 このIDをクエリに渡す方法が必要です。 これを行うには、ユーザーIDを含むオブジェクトを返すvariables
関数を定義することにより、リアクティブパラメーターを利用します。
ユーザー詳細ルートの追加
src/router/index.js
を開き、以下のコードを追加します。 このルートは、以前のすべてのルートより下にある必要があります。
src / router / index.js
// ... import UserDetails from '@/components/Admin/UserDetails' // ... export default new Router({ routes: [ // ... // add these inside the `routes` array { path: '/admin/users/:id', name: 'UserDetails', component: UserDetails, props: true } ] })
これで、特定のユーザーの詳細を表示できるようになります。
ステップ12—ユーザーの承認
認証されたユーザーのみが新しい投稿を追加できます。 したがって、ユーザーが実際に新しい投稿を追加できることを示す新しい投稿を追加するリクエストとともに、Authorization
ヘッダーをユーザートークンとともに渡す方法が必要です。 apollo-link-context
を使用すると、これを簡単に行うことができます。 src/main.js
を開き、以下のコードを追加します。
src / main.js
// ... import { setContext } from 'apollo-link-context' // ... const authLink = setContext((_, { headers }) => { // get the authentication token from localstorage if it exists const token = localStorage.getItem('blog-app-token') // return the headers to the context so httpLink can read them return { headers: { ...headers, authorization: token ? `Bearer ${token}` : null } } }) // ... // update apollo client as below const apolloClient = new ApolloClient({ link: authLink.concat(httpLink), cache: new InMemoryCache() })
まず、apollo-link-context
をインポートします。 次に、それを利用して、ローカルストレージからユーザートークンを取得し、Authorizationヘッダーを含むヘッダーを返すauthLink
を作成します。 最後に、ApolloクライアントでauthLink
を使用します。
これで、Authorizationヘッダーが、GraphQLサーバーに対して行われたすべてのリクエストとともに送信されます。
ステップ13—新しい投稿ページを作成する
投稿はブログの中心です。 ユーザーは新しい投稿を追加できるはずです。 繰り返しになりますが、最初にブログに新しい投稿を追加するためのGraphQLミューテーションを作成します。 以下のコードをsrc/graphql.js
に追加します。
src /graphql.js
export const ADD_POST_MUTATION = gql` mutation AddPostMutation($title: String!, $content: String!) { addPost( title: $title, content: $content ) { id slug title content user { id username email } } } `
このミューテーションは、GraphQLサーバーに追加する投稿のタイトルとコンテンツを取得します。
次に、Admin
フォルダー内にAddPost
コンポーネントを作成し、以下のコードをその中に貼り付けます。
src / components / Admin / AddPost.vue
<template> <section class="section"> <div class="container"> <div class="columns"> <div class="column is-3"> <Menu/> </div> <div class="column is-9"> <h2 class="title">Add Post</h2> <form method="post" @submit.prevent="addPost"> <div class="field"> <label class="label">Title</label> <p class="control"> <input class="input" v-model="title" placeholder="Post title" /> </p> </div> <div class="field"> <label class="label">Content</label> <p class="control"> <textarea class="textarea" rows="10" v-model="content" placeholder="Post content" ></textarea> </p> </div> <p class="control"> <button class="button is-primary">Add Post</button> </p> </form> </div> </div> </div> </section> </template> <script> import Menu from '@/components/Admin/Menu' import { ADD_POST_MUTATION, ALL_POSTS_QUERY } from '@/graphql' export default { name: 'AddPost', components: { Menu }, data () { return { title: '', content: '' } }, methods: { addPost () { this.$apollo .mutate({ mutation: ADD_POST_MUTATION, variables: { title: this.title, content: this.content }, update: (store, { data: { addPost } }) => { // read data from cache for this query const data = store.readQuery({ query: ALL_POSTS_QUERY }) // add new post from the mutation to existing posts data.allPosts.push(addPost) // write data back to the cache store.writeQuery({ query: ALL_POSTS_QUERY, data }) } }) .then(response => { // redirect to all posts this.$router.replace('/admin/posts') }) } } } </script>
このコンポーネントは、新しい投稿を追加するためのフォームをレンダリングします。 ADD_POST_MUTATION
を使用して、必要な変数を渡します。 Apolloクライアントは(この場合はメモリ内に)クエリを実行するため、ミューテーションアクションを実行するたびにキャッシュを更新する方法が必要です。 新しく追加された投稿をキャッシュに追加してストアを更新するために使用するupdate
関数があることに注意してください。 まず、クエリ(ALL_POSTS_QUERY
)に一致するキャッシュからデータをフェッチし、次に新しい投稿をallPosts
配列に追加します。 最後に、新しいデータをキャッシュに書き戻します。 投稿が正常に追加されると、投稿のリストにリダイレクトされます(これはまもなく作成されます)。
投稿ルートの追加
src/router/index.js
を開き、以下のコードを追加します。
src / router / index.js
// ... import AddPost from '@/components/Admin/AddPost' // ... export default new Router({ routes: [ // ... // add these inside the `routes` array { path: '/admin/posts/new', name: 'AddPost', component: AddPost } ] })
ユーザーは今すぐ新しい投稿を追加できるはずです:
ステップ14—すべての投稿を表示する
まず、以下のコードをsrc/graphql.js
に追加して、GraphQLクエリを作成します。
src /graphql.js
export const ALL_POSTS_QUERY = gql` query AllPostsQuery { allPosts { id title slug user { username } } } `
このGraphQLクエリは、GraphQLサーバーからすべての投稿をフェッチします。
次に、Admin
フォルダー内にPosts
コンポーネントを作成し、以下のコードをその中に貼り付けます。
src / components / Admin / Posts.vue
<template> <section class="section"> <div class="container"> <div class="columns"> <div class="column is-3"> <Menu/> </div> <div class="column is-9"> <h2 class="title">Posts</h2> <table class="table is-striped is-narrow is-hoverable is-fullwidth"> <thead> <tr> <th>Title</th> <th>User</th> <th></th> </tr> </thead> <tbody> <tr v-for="post in allPosts" :key="post.id" > <td>{{ post.title }}</td> <td>{{ post.user.username }}</td> </tr> </tbody> </table> </div> </div> </div> </section> </template> <script> import Menu from '@/components/Admin/Menu' import { ALL_POSTS_QUERY } from '@/graphql' export default { name: 'Posts', components: { Menu }, data () { return { allPosts: [] } }, apollo: { // fetch all posts allPosts: { query: ALL_POSTS_QUERY } } } </script>
以前に作成したMenu
コンポーネントを使用します。 次に、GraphQLサーバーからデータを取得したときに入力されるデータを定義します。 apollo
オブジェクト内に、すべてのユーザーをフェッチするためのGraphQLクエリを追加します。 これは、上記で作成したALL_USERS_QUERY
を利用します。 データの名前(この場合はallUsers
)は、GraphQLクエリで使用されている名前(この場合はallUsers
)と同じである必要があることに注意してください。 allUsers
にGraphQLサーバーからのデータが入力されると、ユーザーの配列をループして、テーブルにユーザーを表示します。 また、各ユーザーの詳細を表示するためのリンクを追加します。
投稿ルートの追加
src/router/index.js
を開き、以下のコードを追加します。
src / router / index.js
// ... import Posts from '@/components/Admin/Posts' // ... export default new Router({ routes: [ // ... // add these inside the `routes` array { path: '/admin/posts', name: 'Posts', component: Posts } ] })
/admin/posts
ルートにアクセスすると、次の画像のような投稿のリストが表示されます。
ステップ15—ブログホームページの作成
ブログのホームページには、投稿の表示セクションと同じように作成されたすべての投稿のリストが表示されます。 実際、ホームページは投稿の表示に使用されるものとまったく同じGraphQLを使用します。 異なるのはホームページのマークアップのみです。 src/components
内にHome
コンポーネントを作成し、以下のコードを追加します。
src / components / Home.vue
<template> <section class="section"> <div class="columns"> <div class="column is-6 is-offset-3"> <h1 class="title">Latest Posts</h1> <h3 v-for="post in allPosts" :key="post.id" class="title is-5" > <router-link :to="post.slug"> {{ post.title }} </router-link> </h3> </div> </div> </section> </template> <script> import { ALL_POSTS_QUERY } from '@/graphql' export default { name: 'Home', data () { return { allPosts: [] } }, apollo: { // fetch all posts allPosts: { query: ALL_POSTS_QUERY } } } </script>
ご覧のとおり、JavaScriptセクションはPosts
コンポーネントのセクションと同じです。 ちょうど異なるマークアップ。 投稿配列をループして、スラッグにリンクされた各投稿のタイトルを表示します。
ホームルートの追加
src/router/index.js
を開き、以下のコードを追加します。
src / router / index.js
// ... import Home from '@/components/Home' // ... export default new Router({ routes: [ // ... // add these inside the `routes` array { path: '/', name: 'Home', component: Home } ] })
/
ルートにアクセスすると、次の画像のようにブログのホームページが表示されます。
ステップ16—単一の投稿ページを作成する
最後に追加するのは、特定の投稿を表示する機能です。 以下のコードをsrc/graphql.js
に追加します。
src /graphql.js
export const POST_QUERY = gql` query PostQuery($slug: String!) { post(slug: $slug) { id title slug content user { id username email } } } `
このクエリは、スラッグによって投稿をフェッチします。 引数としてフェッチされるのは投稿のスラッグです。
次に、src/components
内にSinglePost
コンポーネントを作成し、以下のコードを追加します。
src / components / SinglePost.vue
<template> <section class="section"> <div class="columns"> <div class="column is-6 is-offset-3"> <router-link class="button is-link is-small" to="/">Back Home</router-link> <h1 class="title"> {{ post.title }} </h1> <div class="content"> {{ post.content }} </div> </div> </div> </section> </template> <script> import { POST_QUERY } from '@/graphql' export default { name: 'SinglePost', data () { return { post: '', slug: this.$route.params.slug } }, apollo: { // fetch post by slug post: { query: POST_QUERY, variables () { return { slug: this.slug } } } } } </script>
投稿のタイトルとその内容、およびホームページに戻るためのリンクを表示します。 JavaScriptセクションは、ユーザーの詳細を表示する際に使用される実装に従います。 この場合、ルートパラメータからポストスラッグを取得します。
ビューポストルートの追加
src/router/index.js
を開き、以下のコードを追加します。
src / router / index.js
// ... import SinglePost from '@/components/SinglePost' // ... export default new Router({ routes: [ // ... // add these inside the `routes` array { path: '/:slug', name: 'SinglePost', component: SinglePost, props: true } ] })
注:このルートは、routes配列の最後のルートである必要があります。
これで、1つの投稿を表示できるようになります。
結論
このチュートリアルでは、GraphQL、Apolloクライアント、およびVueJSを使用してブログアプリを構築する方法を見てきました。 また、フロントエンドアプリをGraphQLサーバーに接続する方法も確認しました。
このチュートリアルの完全なコードは、GitHubで入手できます。