Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

Vue.js で Router 使ってみよう

$
0
0

Router 使うと簡単に画面遷移するアプリ作れるってことで試してみましょう。 まぁ、Vue.js は公式ドキュメントがとてもよくて、さらには日本語もあって読みやすい!!なので、公式みたらわかるようになってるのですが、とりあえず試してみたログということで。

ちなみに Vue Router のドキュメントはこちら

router.vuejs.org

Router のないプロジェクトを Vue CLI で作ろう

とりあえずサクッと作ります。Router のない TypeScript のプロジェクトを作りました。とりあえず現状の最新の Vue CLI 3.9.2 でやってます。

$ vue create router-sample

オプションはこんな感じで

f:id:okazuki:20190706221228p:plain

Use class-style component syntax? は、No で行きます。それ以外は Enter 連打で。

Router を導入

ではプロジェクトが出来たので Router を導入していきます。プロジェクトのフォルダーで以下のコマンドでインストールします。

npm i vue-router

そして src/main.tsで Router を使うようにします。とりあえずの動作確認なので各種ページは適当に

import Vue from'vue';import Router,{ RouteConfig }from'vue-router';import App from'./App.vue';

Vue.use(Router);// これで vue-router を使うということを明示
Vue.config.productionTip =false;// とりあえずのコンポーネントconst Home = Vue.extend({
  render(){returnthis.$createElement('h2','Home');},});const About = Vue.extend({
  render(){returnthis.$createElement('h2','About');},});// ルートを定義const routes: RouteConfig[]=[{ path: '/', component: Home },{ path: '/about', component: About},];const router =new Router({
  routes,});new Vue({
  router,
  render: (h)=> h(App),}).$mount('#app');

そして、src/App.vueで Router 系のタグを入れます。

<template><divid="app"><h1>Router sample</h1><div><router-link to='/'>Home</router-link><router-link to='/about'>About</router-link></div><router-view></router-view></div></template><scriptlang="ts">import Vue from 'vue';exportdefault Vue.extend({  name: 'app',});</script>

f:id:okazuki:20190706224045p:plain

f:id:okazuki:20190706224109p:plain

ちゃんとしたコンポーネントにする

src/componentsフォルダーに Home.vueAbout.vueを追加して以下のようにします。

<template><div><h2>Home</h2><router-link to="/about">About ページへ</router-link></div></template><scriptlang="ts">import Vue from 'vue'exportdefault Vue.extend({});</script>
<template><div><h2>About</h2><button @click="goBack">Go back</button></div></template><scriptlang="ts">import Vue from 'vue'exportdefault Vue.extend({    methods: {        goBack(e: MouseEvent){this.$router.back();},},});</script>

実行すると初期状態で Homeが表示されて…

そして src/main.tsでこのコンポーネントを使うように変更します。

import Vue from'vue';import Router,{ RouteConfig }from'vue-router';import App from'./App.vue';import Home from'./components/Home.vue';import About from'./components/About.vue';

Vue.use(Router);
Vue.config.productionTip =false;const routes: RouteConfig[]=[{ path: '/', component: Home },{ path: '/about', component: About},];const router =new Router({
  routes,});new Vue({
  router,
  render: (h)=> h(App),}).$mount('#app');

これでとりあえず動くはずです。

f:id:okazuki:20190706225258p:plain

f:id:okazuki:20190706225319p:plain

ページ内のリンクやボタンも動きます。コード補完も効いて書き味もばっちりです!!

ハッシュじゃない感じで

URL をみてみると http://localhost:8080/#/aboutみたいにハッシュが使われてます。これでもいいのですが HTML5 histry モードというのもあって URL が綺麗になります。適用の仕方は簡単で src/main.tsの Router をインスタンス化しているところで mode を history に設定するだけです。

以下のような感じで。

import Vue from 'vue';
import Router, { RouteConfig } from 'vue-router';
import App from './App.vue';
import Home from './components/Home.vue';
import About from './components/About.vue';

Vue.use(Router);
Vue.config.productionTip = false;

const routes: RouteConfig[] = [
  { path: '/', component: Home },
  { path: '/about', component: About},
];
const router = new Router({
  mode: 'history', // これを追加
  routes,
});

new Vue({
  router,
  render: (h) => h(App),
}).$mount('#app');

動かしてみると URL が綺麗になった!

f:id:okazuki:20190706232707p:plain

こうした時の注意点はデプロイ先で失敗したリクエストも全て index.html に回すするようにする必要があります。

URL にパラメーターも渡したい

http://localhost:8080/users/1みたいにして 1 を渡したいってことがよくありますね。これもしてみましょう。

src/main.tsのルートの定義をちょっと追加します。

import Vue from'vue';import Router,{ RouteConfig }from'vue-router';import App from'./App.vue';import Home from'./components/Home.vue';import About from'./components/About.vue';import Users from'./components/Users.vue';

Vue.use(Router);
Vue.config.productionTip =false;const routes: RouteConfig[]=[{ path: '/', component: Home },{ name: 'users', path: '/users/:id', component: Users},{ path: '/about', component: About},];const router =new Router({
  mode: 'history',// これを追加
  routes,});new Vue({
  router,
  render: (h)=> h(App),}).$mount('#app');

/users/:idとパスを定義してるの点と、あとでプログラムからパラメーターを渡して画面遷移するために nameを設定している点がポイントです。

src/components/Users.vueは以下のような感じです。

<template><div><h2>User</h2><div v-if="loading">loading...</div><div v-if="!loading">{{ id }}</div></div></template><scriptlang="ts">import Vue from 'vue';exportdefault Vue.extend({  data(){return{        loading: false,      id: 0,};},  async created(){// 初回      await this.fetchData();},  async beforeRouteUpdate(to, from, next){// users/1 から users/2 みたいにコンポーネントが再利用される時用      await this.fetchData();      next();},  methods: {      async fetchData(){this.loading = true;          await new Promise((r) => {            setInterval(r, 1000);});this.loading = false;this.id = parseInt(this.$route.params.id, 10);},},});</script>

これで http://localhost:8080/users/22みたいな URL にアクセスすると以下のような表示になります。スクショにはとってませんが、ちゃんと 1 秒くらい loading... と表示されます。

f:id:okazuki:20190706234806p:plain

src/components/About.vueをちょっと変更してテキストに文字入れて users に画面遷移するようにしてみました。

<template><div><h2>About</h2><button @click="goBack">Go back</button><form @submit.prevent="submit"><inputtype="text" v-model="id" /><inputtype="submit"value="画面遷移" /></form></div></template><scriptlang="ts">import Vue from 'vue';exportdefault Vue.extend({    data(){return{            id: '',};},    methods: {        goBack(e: MouseEvent){this.$router.back();},        submit(){this.$router.push({ name: 'users', params: { id: this.id }});},},});</script>

this.$router.pushで簡単にいい感じに画面遷移出来ますね。素敵。

About を開いて適当に数字を入れて…

f:id:okazuki:20190707002502p:plain

画面遷移ボタンを押すか、Enter キーで users/:idで定義した Users コンポーネントに遷移します。

f:id:okazuki:20190707002600p:plain

おまけ

画面遷移と関係ないですが Home コンポーネントに入力した文字をそのまま大文字にして出すような処理も追加してみました。ルーター使っても普通に動いていいね。

<template><div><h2>Home</h2><router-link to="/about">About ページへ</router-link><div><inputtype="text" v-model="input" /></div><div><span>{{ output }}</span></div></div></template><scriptlang="ts">import Vue from 'vue';exportdefault Vue.extend({  data(){return{      input: '',      output: '',};},  watch: {    input(val: string){this.output = val.toUpperCase();},},});</script>

まとめ

簡単でいい感じですね!!

試した時のソースコードなので整理されてないですが GitHub に上げてます。

github.com


Viewing all articles
Browse latest Browse all 1387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>