このサイトは、只今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

OAuthのフローを可視化できるツールを作ってみました。

2020.05.17

令和の時代に、JavaScriptで Shift-JISファイル作成 全銀データフォーマットに対応する。

2020.03.03

インターネットにて世論調査を行う「世論Web」サービスを始めてみました。

2020.01.31

年末のレトロゲーム熱の際、ファミコンソフト一覧パッケージ作ってました。

2020.01.24

あと10日で「jsdo.it」のサービスが終わってしまう!! ソースダウンロードまだの方は急げぇ〜!

2019.10.21

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

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

CATEGORY LIST

LATEST NEWS

iPad Air で、Web開発環境構築(iSH Alpine使用)

mac

2021.04.11

【Qt】Mac開発 ソートダイアログ (拡張するダイアログ)を作成

C++

2021.04.01

M1 (Appleシリコン)Macで Widowsアプリを起動

mac

2021.03.27

M1(Appleシリコン)Macで、ファミコンソフトプログラミング。 サクッと開発環境準備編

Game

2021.03.21

iPad Air 2020を購入しちゃった件。

mac

2021.03.14

眠っているラズベリーパイをネットワークオーディオ化 Volumio2 インストール手順

RaspberryPi

2021.03.12

ラズベリーパイ 5インチDSIタッチスクリーン ディスプレイを使う。

RaspberryPi

2021.01.11

今年読んで良かった書籍は、「Go言語でつくるインタプリタ」でした。

イベント

2020.12.31

【Qt】Macの、Qt Creatorで Dialog GUI作成

C++

2020.12.29

【Qt】Macで、Qt Creatorをbrew installしてサクッと起動する。

C++

2020.12.14

Macで、Qt5 開発 QPushButton、QSliderなどウィジェット作成

C++

2020.12.13

M1搭載 Mac miniをついにポチった件。Appleさんに翻弄される日々の記録。

mac

2020.12.06

RANKING

Follow

SPONSOR

現在、掲載募集中です。



Links

About Us

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

Entry Profile

Graphical FrontEnd Engineer
- Daisuke Takayama

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

FOLLOW US