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

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

2018.09.26

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

2017.10.09

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

2017.07.10

技術書、参考書のしおりには【BOOK DARTS】がオススメ!

2017.07.01

会社で npm Private導入して、1ヶ月で8個ほどパッケージ作成したお話。

2017.06.02

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

2017.03.26

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

2017.02.21

Facebook製 JavaScript 関数ライブラリ。Immutable.js がいい感じ!

2016.07.31

【JS】フロントでレコメンドアルゴリズムを簡単実装できるJavaScriptライブラリ「RecommendJS」を公開しました。

2016.05.30

JavaScript ビット演算・ビットマスクについてまとめてみました。

2016.03.15

CATEGORY LIST

LATEST NEWS

Jenkins 認証情報「Jenkinsマスター上の~/.sshから」が表示しない

tool

2018.11.17

流れで、Raspberry Pi Zero WHを購入。気がつけばもうラズパイ4台。

RaspberryPi

2018.11.06

安く電子工作を始めるなら、電子パーツ購入は「aitendo」がおすすめ!

RaspberryPi

2018.11.06

ASUS Chromebook Flip C101PAに、Visual Studio Codeをインストール

Chromebook

2018.10.15

Chromebookに、Ubuntu (Xubuntu)をインストールしたあとの日本語入力設定

Chromebook

2018.10.14

ASUS Chromebook Flip C101PAに、Ubuntu (Linux)インストール手順

Chromebook

2018.10.10

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

JavaScript

2018.09.26

安い!軽い!早い! ノートPC(開発環境)。 Chromebookをついに購入いたしました!

Chromebook

2018.07.22

debian & Xserver XDSLで FireFoxが真っ白のページとなる件

Linux

2018.07.08

Kindle Fire HD 8 にLinuxを導入して扱えるようにする。超コスパ Linux タブレット構築方法!!

Linux

2018.07.04

Laravel 4 を PHP 7 環境へ移行したお話。

PHP

2018.06.10

iPhoneXで、ubuntuを動かす。

サーバー

2018.06.09

RANKING

Follow

SPONSOR

現在、掲載募集中です。



Links

About Us

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

Entry Profile

Graphical FrontEnd Engineer
- Daisuke Takayama

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

FOLLOW US