RSS
nuxt.js

Nuxt.jsのasyncData メソッドを使ってRSSを読み込む

この記事はオールアバウトアドベントカレンダー18日目の記事です

Nuxt.jsの機能を使って
RSSを取得して値を書き出してみます

使う機能

asyncData メソッド

サーバーサイドでデータを取得し、それをレンダリングしたいことがあるでしょう。Nuxt.js はコンポーネントのデータをセットする前に非同期の処理を行えるようにするために asyncData メソッドを追加しています。

参照: https://ja.nuxtjs.org/guide/async-data/

手順

前準備

  • npm install xml2js
    • XMLを扱うのでparseしてくれるモジュールinstallしておく

コンポーネントを用意する

pages/rss.vueという名前のpageコンポーネントを用意します
先に完成形を↓↓

pages/rss.vue
<template>
  <div>
    <ul>
      <li v-for="item in data">
        <a v-bind:href="item.link">
          {{item.title}}
        </a>
      </li>
    </ul>
  </div>
</template>

<script>
  export default {
    asyncData ({params}, callback) {
      axios.get(`RSSのURL`)
        .then((res) => {
          var parseString = require('xml2js').parseString
          var xml = res.data
          parseString(xml, (message, xmlres) => {
            callback(null, {data: xmlres.rss.channel[0].item})
          })
        })
        .catch((e) => {
          callback({ statusCode: 404, message: 'ページが見つかりません' })
        })
    }
  }
</script>

<style>
</style>

部分的に説明していきます

まず、asyncData() {}を用意します

非同期処理を行ってくれます

pages/rss.vue
<script>
  export default {
    asyncData ({params}, callback) { // ←非同期処理をしてくれる関数
    }
  }
</script>

XMLを取得していきます

今回はaxiosを使っています
取得した結果はres.dataのオブジェクトに格納されます

pages/rss.vue
<script>
  export default {
    asyncData ({params}, callback) {
      axios.get(`RSSのURL`)
        .then((res) => {
          console.log(res.data) // xmlが入ってる
        })
        .catch((e) => {
        })
    }
  }
</script>

XMLをparseします

pages/rss.vue
          var parseString = require('xml2js').parseString
          var xml = res.data // XML入ってる
          parseString(xml, (err, xmlRes) => {
        console.log(xmlRes) // xmlResはXMLをオブジェクトに変換した形
          })

前準備でいれたxml2jsを使って取得したXMLをparseします

書き出しの時に扱えるようにdataに登録する

pages/rss.vue
          parseString(xml, (err, xmlRes) => {
        callback(null, {data: xmlres.rss.channel[0].item})
          })

callback(null, {<変数名>: <データ>}) とすることで
変数に登録できます
今回の場合、<template>のところで使います

XMLが無かったときの処理

pages/rss.vue
        .catch((e) => {
          callback({ statusCode: 404, message: 'ページが見つかりません' })
        })

XMLが取得できなかったときの事を考え
取得できなかったら,404を返すようにします

ビューに書き出す

あとはお好みでいい感じに書き出してください

pages/rss.vue
<template>
  <div>
    <ul>
      <li v-for="item in data">
        <a v-bind:href="item.link">
          {{item.title}}
        </a>
      </li>
    </ul>
  </div>
</template>

実際にやった結果

適当なRSSを読み込み元として
http://localhost:3000/rss/ にアクセスした結果がこちら

スクリーンショット 2017-12-19 14.22.20.png

無事取得できてますねー
こんなかんじでズラ~と出てきます

[おまけ]URLに応じて読み込むRSSを変えたい時

pases/category/_name.vueを作った時
Nuxt.jsは http://localhost:3000/category/<なんか>/
というルーティングを作ってくれます
参照: https://ja.nuxtjs.org/guide/routing#動的なルーティング

その<なんか>の部分を使ってRSSの読み込み先を変更することも可能です

サンプル↓↓

pases/category/_name.vue
<script>
  import axios from 'axios'

  export default {
    asyncData ({params}, callback) {
      axios.get(`https://rss.allabout.co.jp/aa/latest/ch/${params.name}`)
        .then((res) => {
          var parseString = require('xml2js').parseString
          var xml = res.data
          parseString(xml, (message, xmlres) => {
            callback(null, {data: xmlres.rss.channel[0].item})
          })
        })
        .catch((e) => {
          var result = { statusCode: 404, message: 'ページが見つかりません' }
          callback(result)
        })
    }
  }
</script>

${params.name}でURL上の引数を取得することが出来ます、便利!

まとめ

ブラウザへのレンダリング前に実行してくれるasyncDataは
非同期処理のことを考える手間を減らしてくれて最高です

Vue.jsには無かったメソッドな気がする(別でnpm installすればある)ので
コレだけでもNuxt.jsを使いたくなりますね