このサイトは、只今WEB業界で活躍中のデザイナー、プログラマーの方々の情報を集めたweb統合情報サイトです。

Archives Details

Vue.js が予想以上に良かったので、既存WordPressに導入。Vue.js (vue-class-component) + TypeScript + WordPress で作る、記事読み込み component 「実装編」

JavaScript

2017.03.26

この記事は最終更新日から1年以上が経過しています。

こちらの続きとなります。

Vue.js が予想以上に良かったので、既存WordPressに導入。Vue.js (vue-class-component) + TypeScript + WordPress で作る、記事読み込み component 「環境構築編」

では、前回の続きから、

components/post-more-btn.html

<div class="moreBtnBox">
  <a @click="onClick">他の記事を読み込む</a>
</div>

componentsである、「post-more-btn.html」をクリックすると、その対となる 「post-more-btn.ts」の「PostMoreBtn」 のonClickが実行される流れでした。

components/post-more-btn.ts

import Vue = require('vue');
import Component from 'vue-class-component';
import PostMoreService from '../service/post-more.service';
import bus from '../bus'

@Component({
  props: ['nowPostNum'],
  template: require('./post-more-btn.html')
})
export class PostMoreBtn extends Vue {
  private nowPostNum: number;
  private postMoreService: PostMoreService = new PostMoreService();

  onClick (): void {
    this.postMoreService.fetchData(this.nowPostNum)
      .then((response: any) =>; {
        bus.$emit('update-post', response.data);

        this.nowPostNum += 10;
      }, (error: any) => {
        console.error(error);
      });
  }
}

onClick関数を見てみると、postMoreServicefetchDataを行っているのが確認できます。

そのpostMoreServiceを見てみると、このようになっています。

service/post-more.service.ts

const axios = require('axios'),
      wpAjaxUrl = window['wpAjaxUrl'];

export default class PostMoreService {
  private formData = new FormData();

  constructor() {
    this.formData.append('action', 'get_more_post');
  }

  public fetchData(nowPostNum: number): any {
    this.formData.append('now_post_num', nowPostNum);

    return axios({
      method: 'post',
      url: wpAjaxUrl,
      data: this.formData
    });
  }
}

formDataオブジェクトのインスタンスをprivateで保持しているのは、wordpressでAjax通信する(POSTでリクエストする)際、
RequestHeaderのcontent-typeが「application/x-www-form-urlencoded」である必要であるためです。

jQueryなどを使用していて、$.ajax()を用いてAjax通信する際は、jQuery側がよしなにやってくれているかもですが、今回は、特に、jQuery等も使わず「axios」を用いてAjax通信しているので、formDataオブジェクトのインスタンスを作っています。

PostMoreServiceのインスタンスが生成される際に実行されるconstructor関数に書かれている

this.formData.append('action', 'get_more_post');

は、formDataオブジェクトに action名である「get_more_post」をappendし、Ajax通信後のwordpress側の関数を実行するためのものです。

axiosはAjax通信後、Promiseが返却されますので、axios関数自体をreturnしております。

service/post-more.service.ts

return axios({
  method: 'post',
  url: wpAjaxUrl,
  data: this.formData
});

APIのエンドポイントである、「wpAjaxUrl」は、tml側でグローバル変数として受け取っている形となります。

これは、wordpressで用意されているAjaxの経路となります。

該当のファイル(エンドポイント)は、「wp-admin/admin-ajax.php」となり、そちらにリクエストを送る形となります。

この経路が一般的に、「wordpressでのAjax経路」として知られている形となります。

<script>var wpAjaxUrl = '<?php echo admin_url('admin-ajax.php'); ?>';</script>

admin_url関数に「’admin-ajax.php‘」の引数を渡すことで、wordpressのAjaxのpathを取得することができます。

wordpress側

Ajax用のアクションフックに登録

function.php

add_action( 'wp_ajax_get_more_post', 'get_more_post' );
add_action( 'wp_ajax_nopriv_get_more_post', 'get_more_post' );

この関数をアクションフックに登録する必要があります。

アクションフック処理をするadd_actionメソッドが二つありますが、一つ目はログイン状態での登録で、二つ目は非ログイン状態での登録となります。

function.php

function get_more_post() {
  global $wpdb;

  $now_post_num = $_POST['now_post_num'];
  $get_post_num = 10;

  $sql = "SELECT 
            $wpdb->posts.ID,
            $wpdb->posts.post_title,
            $wpdb->posts.post_content
          FROM 
            $wpdb->posts 
          WHERE 
            $wpdb->posts.post_type = 'post' 
          AND 
            $wpdb->posts.post_status = 'publish' 
          ORDER BY
            $wpdb->posts.post_date 
          DESC 
            LIMIT $now_post_num, $get_post_num";

  echo create_post_json($wpdb->get_results($sql));

  die();
}

function create_post_json($posts) {
  $post_list = array();

  foreach($posts as $post) {
    $postId = $post->ID;

    $post_list[] = array(
      "title"        => $post->post_title,
      "date"         => get_the_date("Y年n月j日 l", $postId),
      "imageUrl"     => get_post_image_src($postId),
      "postUrl"      => get_permalink($postId),
      "postDetail"   => mb_substr(strip_tags($post->post_content), 0, 160).'…',
      "tagList"      => create_post_tag_list(get_the_tags($post->ID)),
      "categoryList" => create_post_category_list(get_the_category($postId))
    );
  }

  return json_encode($post_list);
}

 

get_more_post関数は、アクションフックと結びついており呼び出されます。

何件目から記事データを取得するかを、「now_post_num」をpostデータで受け取ります。

global変数である「$wpdb」を使用し、SQL文を発行します。

コードでreturnを使っていないのは、returnを使用するとレスポンスに0が返ってしまう為、die()で処理を終わらせています。

create_post_json関数は、フロント用にjsonデータとして加工する関数です。

これでVueJS側のリクエストである、「postMoreService」と、レスポンス側のwordpressのfunction.phpの準備が整いました。

最後は、レスポンスが返って来た後の、pub/subの役割を持つbusについてです。

親子間以外の通信を行う 「bus」

親子関係ではない2つのコンポーネントの通信を行う場合は、「bus」を利用します。

これは、空の Vue インスタンスを中心のイベントバスとして使用することができます。

公式ガイドページより

親子間以外の通信

bus.ts

var bus = new Vue();
// コンポーネント A のメソッドの中で
bus.$emit('id-selected', 1)
// コンポーネント B の created フックで
bus.$on('id-selected', function (id) {
  // ...
})

と、公式ガイドページとあまり説明もなく、実際にもあまり説明することもないのですが。。

とりあえず、ざっくり言うと、「EventEmitter的な振る舞いが、空の Vueインスタンスで実現できますよ」と、いった感じです。

ちょっと、前回の記事に振り返り、「Vue.js が予想以上に良かったので、既存WordPressに導入。Vue.js (vue-class-component) + TypeScript + WordPress で作る、記事読み込み component 「環境構築編」」で、作成した post-list.tsを見てみましょう。

components/post-list.ts

created() {
  bus.$on('update-post', this.onUpdatePost)
}
 
destroyed() {
  bus.$off('update-post', this.onUpdatePost)
}

post-list.tsで定義されている「created関数」は、component生成されたタイミングで実行され、destroyed関数はその逆で、componentsが破棄されたタイミングで実行されます。

なので、component生成されると同時に、「bus.$on」でupdate-postを購読登録し、this.onUpdatePostを実行するようにしております。

また、componentsが破棄されると同時に、「bus.$off」でupdate-postを購読解除を行っております。

なので、post-more.serviceでは、レスポンスが返ると、update-postがemitされ、components/post-list.ts
側のthis.onUpdatePost関数が呼び出され、記事リストである componentsの、「components/post-list.html」が更新される流れとなります。

service/post-more.service.ts

bus.$emit('update-post', response.data);

と、簡単ではありましたが、「wordpress」と「Vue Class component」を使った、「もっと記事を読み込む」の流れでした。

なんとなく、「Angular」に近い感じではありますが、「Angular」を使うとなると、ガッツリ「SPA」になってしまうので、今回の様な、ちょっとした機能には、手軽にすぐに実装できる「Vue Class component」が良い気がしました。

実は、「カテゴリ」とかに全く考慮していないので、工夫して作ってみると良いかもしれませんね。

それでは、またぁまたぁ。

公式ガイドページ

TypeScript のサポート

Comment

Related Article

正規表現 先読み後読み 論理積

2019.07.28

「二段階認証?」という方も 5分で覚える パスワードレス WebAuthnのまとめ

2019.07.07

上級者向け JavaScript 問題集 「javascript-questions」日本語翻訳担当してます。

2019.06.22

SPAサイトでの認証認可 JWT✗Rails5✗Nuxt.js

2019.03.24

Nuxt.js と auth-module (@nuxtjs/auth)で、JWT(JSON Web Tokens)& OAuth 認証 ログイン

2019.02.21

ブラウザフィンガープリントは、Cookieの代用となるのか? JSライブラリ Fingerprintjs2など。

2019.02.03

Vue.jsでSPA、Vuex使用するなら Nuxt.jsが超絶便利な件。

2018.12.23

nodeのない環境にnodeを導入(HTML5ゲームも提供)し続け、1年数ヶ月経過後、かなり開発環境が整ってきたお話。

2018.09.26

Vue.js + SSR (Universal JavaScript)環境を、「NUXT.js」でサクッと構築する方法。

2017.10.09

フロントエンド開発が捗る JSON Serverについて

2017.07.10

CATEGORY LIST

LATEST NEWS

Arduino IDEとArduino接続して、サクッと設定。

電子工作

2019.08.15

ついに、M5Stack Gray 購入!! その他諸々、購入したボードの振り返りなど。

電子工作

2019.08.12

正規表現 先読み後読み 論理積

JavaScript

2019.07.28

PythonでGUIアプリ開発「PyQt」を使った感想

Python

2019.07.18

「二段階認証?」という方も 5分で覚える パスワードレス WebAuthnのまとめ

JavaScript

2019.07.07

上級者向け JavaScript 問題集 「javascript-questions」日本語翻訳担当してます。

JavaScript

2019.06.22

Wordpress サイトで、長時間 500 Internal Server Error発生。解決した方法とは。

WordPress

2019.06.18

Ubuntu 18.04 LTSで OpenGL開発

ubuntu

2019.05.20

MacOS Mojave (10.14.4)の Xcode に、過去のMacOSのSDKをインストール

C++

2019.05.19

クローンソフトの「EaseUS Disk Copy」を使って、OSのバックアップを取ってみた。

tool

2019.05.06

Rails5 gemでmysql2が インストールできない

Ruby

2019.05.05

平成最後のお買い物!!「Logicool MX Master 2 Wireless Mouse」と「K780 マルチデバイス BLUETOOTH® キーボード」で快適PC生活。

ubuntu

2019.04.27

RANKING

Follow

SPONSOR

現在、掲載募集中です。



Links

About Us

WEBデザイナーの、WEBデザイナーによる、WEBデザイナーの為のサイト。「みんなで書こう!」と仲間を募ってみたが、結局書くのは自分だけとなってしまいました。日々のメモを綴っていきます。

Entry Profile

Graphical FrontEnd Engineer
- Daisuke Takayama

MAD CITY 北九州市で生まれ育つ。20代はバンド活動に明け暮れ、ふと「webデザイナーになりたい。」と思い、デジタルハリウッド福岡校入学。卒業後、数々の賞を受賞、web業界をざわつかせる。
現在、主に、ゲーム制作中心に港区六本木界隈で活動中。

FOLLOW US