LoginSignup
2
1

More than 3 years have passed since last update.

Vue.jsでSPA - [7] Vueからサーバデータ取得

Last updated at Posted at 2018-08-11

Vue.jsでSPA - [7] Vueからサーバデータ取得

前回のサーバへのAPIコールをVueの中に入れてく回.今回はスクリーンショットから

スクリーンショット

リアルデータでそれっぽく動くようになってきたでこれ

image

APIコールを入れたコード

長くなってきたがとりあえず貼り付ける.fetchをつかうパターン.

index.html
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <!-- import CSS -->
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  <!-- import Vue before Element -->
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <!-- 1. import Vue router -->
  <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  <!-- import JavaScript -->
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.4.1/locale/en.js"></script>
  <link rel="stylesheet" href="../app.css">
</head>


<body>
  <div id="app">
    <el-container>
      <el-header height="100px">
        <img src="../static/img/placeholder-logo-2-300x167.png" height="100" align="left">
      </el-header>
    <el-container>
      <el-aside width="200px">
        <el-col :span="24">
          <el-menu default-active="1" class="el-menu-vertical-demo">
            <el-menu-item index="1">
              <i class="el-icon-location"></i>
              <!-- 6. When clicking, it loads the contents defined in 2 and 1 -->
              <router-link to="/location"><span>Location</span></router-link>
            </el-menu-item>
            <el-menu-item index="2">
              <i class="el-icon-document"></i>
              <!-- 6. When clicking, it loads the contents defined in 2 and 1 -->
              <router-link to="/foo"><span>foo</span></router-link>
            </el-menu-item>
            <el-menu-item index="3">
              <i class="el-icon-setting"></i>
              <!-- 6. When clicking, it loads the contents defined in 2 and 1 -->
              <router-link to="/bar"><span>bar</span></router-link>
            </el-menu-item>
          </el-menu>
        </el-col>
      </el-aside>

     <el-main>
        <!-- 7. The contents will be load here -->
        <router-view></router-view>
      </el-main>
    </el-container>
  </el-container>
  </div>
</body>

<script>

// 2. Define route components.
const Location = { template: '<location-table></location-table>' } // 9. Use the component here
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }

// 3. Define some routes
const routes = [
  { path: '/location', component: Location },
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

// 4. Create the router instance and pass the `routes` option
const router = new VueRouter({
  routes // short for `routes: routes`
})

// 8. Define component
Vue.component('location-table', {
  data: function() {
    return {
      location: [] // 10-1. location is now initialized as empty - get data from a server!
    }
  },
  created: function() {
    this.getLocation();
  },
  methods: { 
    getLocation: function(){  // 10-2. function for server API call
      let url = 'your-api-endpoint-here';
      fetch(url)
        .then(response => response.json())
        .then(json => {     
            this.location = json.data;  // 10-3. Accessing data in [[PromiseValue]]
            console.log(json.data);
          }) 
        .catch(error => console.error(error))
    }
  },
  template: `
      <el-table :data="location" style="width: 100%">
        <el-table-column prop="id" label="id" width="100"></el-table-column>
        <el-table-column prop="name" label="name"></el-table-column>
        <el-table-column prop="country" label="country" width="180"></el-table-column>
        <el-table-column prop="metro" label="metro" width="180"></el-table-column>
        <el-table-column prop="market" label="market" width="180"></el-table-column>
        <el-table-column prop="status" label="status" width="180"></el-table-column>
      </el-table>
  `
})

ELEMENT.locale(ELEMENT.lang.en)
var vm = new Vue({
  // 5. Inject the router in the Vue instance
  router, 
  el: '#app'
})

</script>

</html>

前回からの変更点

Vue.component10-1 10-2 10-3のところ
1. 10-1はサーバから持ってくるので空にしておいて
2. 10-2にデータ取ってくるメソッドgetLocationを定義
3. 10-3createdでインスタンスの準備ができたらgetLocationをコールする

APIコールをどの時点(created or mounted)で行うかについてはこの考察が詳しかった:Vuejs APIアクセスはcreatedとmountedのどちらで行う?

長くなってきたのでファイル分ける

こんなんでいいのかようわからんけど,見にくくなってきたのでコンポーネントのところを分けることにする.おれおれな感じもするが,まあ一応テンプレートとロジック入ってる形で切り出せるし.やっぱり単一ファイルコンポーネント使いやすいようにvue-cliでやっとくべきだったか...

メイン側

index.html
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <!-- import CSS -->
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  <!-- import Vue before Element -->
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <!-- 1. import Vue router -->
  <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  <!-- import JavaScript -->
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.4.1/locale/en.js"></script>
  <link rel="stylesheet" href="../../app.css">
</head>


<body>
  <div id="app">
    <el-container>
      <el-header height="100px">
        <img src="../../static/img/placeholder-logo-2-300x167.png" height="100" align="left">
      </el-header>
    <el-container>
      <el-aside width="200px">
        <el-col :span="24">
          <el-menu default-active="1" class="el-menu-vertical-demo">
            <el-menu-item index="1">
              <i class="el-icon-location"></i>
              <!-- 6. When clicking, it loads the contents defined in 2 and 1 -->
              <router-link to="/location"><span>Location</span></router-link>
            </el-menu-item>
            <el-menu-item index="2">
              <i class="el-icon-document"></i>
              <!-- 6. When clicking, it loads the contents defined in 2 and 1 -->
              <router-link to="/foo"><span>foo</span></router-link>
            </el-menu-item>
            <el-menu-item index="3">
              <i class="el-icon-setting"></i>
              <!-- 6. When clicking, it loads the contents defined in 2 and 1 -->
              <router-link to="/bar"><span>bar</span></router-link>
            </el-menu-item>
          </el-menu>
        </el-col>
      </el-aside>

     <el-main>
        <!-- 7. The contents will be loaded here -->
        <router-view></router-view>
      </el-main>
    </el-container>
  </el-container>
  </div>
</body>

<!-- 10. Load components -->
<script src="./location.js"></script>

<!-- Routing and main -->
<script>
// 2. Define route components.
const Location = { template: '<location-table></location-table>' } // 9. Use the component here
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }

// 3. Define some routes
const routes = [
  { path: '/location', component: Location },
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

// 4. Create the router instance and pass the `routes` option
const router = new VueRouter({
  routes // short for `routes: routes`
})

ELEMENT.locale(ELEMENT.lang.en)
var vm = new Vue({
  // 5. Inject the router in the Vue instance
  router, 
  el: '#app'
})
</script>


</html>        

コンポーネント側

location.js
Vue.component('location-table', {
  data: function() {
    return {
      location: [] // 10-1. location is now initialized as empty - get data from a server!
    }
  },
  created: function() {
    this.getLocation();
  },
  methods: {
    getLocation: function(){  // 10-2. function for server API call
      let url = 'your-api-end-point-here';
      fetch(url)
        .then(response => response.json())
        .then(json => {
            this.location = json.data;  // 10-3. Accessing data in [[PromiseValue]]
            console.log(json.data);
          })
        .catch(error => console.error(error))
    }
  },
  template: `
      <el-table :data="location" style="width: 100%">
        <el-table-column prop="id" label="id" width="100"></el-table-column>
        <el-table-column prop="name" label="name"></el-table-column>
        <el-table-column prop="country" label="country" width="180"></el-table-column>
        <el-table-column prop="metro" label="metro" width="180"></el-table-column>
        <el-table-column prop="market" label="market" width="180"></el-table-column>
        <el-table-column prop="status" label="status" width="180"></el-table-column>
      </el-table>
  `
})

次回

これであとはコンポーネントを増やせばアプリっぽくなっていく感じになってきたので,次は

  1. コンポーネント増やしていくか
  2. このあたりでどこかクラウドにデプロイしてみるか(サーバレスな感じでやりたい)
  3. 1をやりながらPOST系の動きを書くか

あたりをやってみるかな

シリーズ

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1