Posted at

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

More than 1 year has passed since last update.

この記事はオールアバウトアドベントカレンダー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を使いたくなりますね