nuxt.jsのviewでパスパラメータを使いたいけど、ドキュメント読んでもよくわからなかった

GWにはいってから、`nuxt.js`をいじりはじめたのだけれど、パスパラメータをviewで表示しようとしたらハマった。

（動的なルーティングを生成するところまでは、[ドキュメント](https://ja.nuxtjs.org/guide/routing#%E5%8B%95%E7%9A%84%E3%81%AA%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0)読めばわかるのだけれど）

# 結論

## 正規

> @ospy さん、コメントありがとうございます

参照： https://router.vuejs.org/ja/essentials/dynamic-matching.html

```
<template>
  <h2>{{ $route.params.id }}</h2>
</template>

<script>
export default {};
</script>
```


## 最初にたどり着いた結論

> スタンダードなやりかたではないので
> こちらでもできなくないぐらいに捉えてください

~~どうやらこうらしい。~~
script上では `params` で参照できるけど、それ以外だと使えない

```vue:_id.vue
<template>
  <h2>{{ p.id }}</h2>
</template>

<script>
export default {
  validate({params}) {
    return /^[0-9a-z]+$/.test(params.id)
  },
  asyncData ({ params }) {
    return { p: params }
  }
};
</script>
```

# 検証

## 最初はこう書いた
```vue:_id.vue
<template>
  <h2>{{ params.id }}</h2>
</template>

<script>
export default {
  validate({params}) {
    return /^[0-9a-z]+$/.test(params.id)
  }
};
</script>
```

ドキュメント読んでいたらparamsにパスパラメータが格納されることが理解でき、`script`で普通に呼べていたので、`template`で普通に使えるものと思っていたら、見事にエラーになった。

> Property or method "params" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

ふむなるほど。わからん。
参照しろといわれたドキュメントを読んで見る。

--- 以下、ドキュメント転記

Vue は動的に新しいルートレベルのリアクティブなプロパティを追加することはできませんので、前もってインスタンス全てのルートレベルのリアクティブな `data` を宣言して初期化する必要があります。空の値でもかまいません:

```vue
var vm = new Vue({
  data: {
    // 空の値として message を宣言する
    message: ''
  },
  template: '<div>{{ message }}</div>'
})
// 後で、`message` を追加する
vm.message = 'Hello!'
```

`data` オプションで `message` を宣言していないと、Vue は `render` ファンクションが存在しないプロパティにアクセスしようとしていることを警告します。

この制限の背後には技術的な理由があります。それは依存性追跡システムにおけるエッジケースのクラスを排除し、 また Vue インスタンスと型チェックシステムとの親和性を高めます。しかし重要な考慮事項はコードの保守性にあります。data オブジェクトはコンポーネント状態のスキーマのようなものです。前もって全てのリアクティブなプロパティを宣言することで、後から見直したり別の開発者が読んだりしたときにコンポーネントのコードを簡単に理解することができます。

--- 以上、ドキュメント転記

`params`は`nuxt.js`で管理されているところで使えるだけなので、 `export default`のなかだったら、`{params}`で参照できるだけで、vueファイル使っているところでプリセットされてるとかそんなわけではないらしい。

ためしに下記のように、`export default`のそとで参照するようにしてみたら見事に`ReferenceError`が出た。

```vue:_id.vue
<template>
  <h2>{{ params.id }}</h2>
</template>

<script>
console.log(params)
export default {
  validate({params}) {
    return /^[0-9a-z]+$/.test(params.id)
  }
};
</script>
```

## 他の人はどう書いてるのか見てみた。

参考にしたページ： https://html5experts.jp/potato4d/24346/

真似して、試してみた。
うごいた。なるほど、`asyncData`などで生成したものは使える。

```vue:_id.vue
<template>
  <h2>{{ user.id }}</h2>
</template>

<script>
import axios from 'axios'

export default {
  validate({params}) {
    return /^[0-9a-z]+$/.test(params.id)
  },
  async asyncData ({ params }) {
    const { data: user } = await axios.get(`https://api.github.com/users/${params.id}`)
    return {
      user
    }
  }
};
</script>
```

## ちなみに、これもうごかない

```vue:_id.vue
<template>
  <h2>{{ window.navigator.userAgent }}</h2>
</template>

<script>
import axios from 'axios'

export default {
  validate({params}) {
    return /^[0-9a-z]+$/.test(params.id)
  }
};
</script>
```

グローバルな変数も宣言しないと動かない