Help us understand the problem. What is going on with this article?

Vue.jsでSPA - [4] コンポーネントにしてみる

Vue.jsでSPA - [4] コンポーネントにしてみる

前回の続き

前回のルーティングで画面切り替えた時に,テーブル内の値dataが読み込まれなくて以下のエラーで怒られる問題については,なんとなくコンポーネント化してHTMLとJSを動的にリンク(リアクティブ?)させればなんとかなるような予感がしたので,コンポーネントについて調べてみる

vue.js:597 [Vue warn]: Property or method "location" 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.

found in

---> <Anonymous>
       <ElMain>
         <ElContainer>... (1 recursive calls)
           <Root>

コンポーネント?

参考にあげたサイトを読む.とくに青空コメントアウトmille-feuille codeがわかりやすい(たぶん同じ人が書いてる).コンポーネントの書き方は三通りあるらしい.

Vueはvue-cliでセットアップする方法が一般的っぽいけど,今回はひとまず軽く試そうと思ってCDNで始めてしまった.そのため,三通りの中で一番わかりやすそうな単一ファイルコンポーネントがつかえなさそう(いや,WebpackBrowserifyでごにょごにょやればできそうだが,それ自体が目的じゃないので Yak Shaving は今はしないようにする)ひとまずtemplateオプションを使う方法で進めてみる.

一部コンポーネント化したコード

<!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: [{id: 1, name: 'Site1', country: 'USA', metro: 'San Jose', market: 'US', status: 'Active'},
                  {id: 2, name: 'Site2', country: 'USA', metro: 'San Mateo', market: 'US', status: 'Active'},
                  {id: 3, name: 'Site3', country: 'USA', metro: 'San Rafael', market: 'US', status: 'Active'}]
    }
  },
  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> 

前回からの変更点

ざっくりいうと
1. 8. Define component9.Use the component hereを追加
2. それにともなってvar vm = new Vuedata部分をコンポーネント側へ移す

これでエラーがでなくなった.とりあえず動いている.コンポーネントのところはあとでファイル分けたほうがいいかな...

スクリーンショット

Image from Gyazo

参考にしたサイト

  1. 公式
  2. 青空コメントアウト
  3. Qiita - コンポーネントのtemplateの書き方まとめ
  4. mille-feuille code
  5. 公式 - シングルファイルコンポーネント

次回

コンポーネントのところを別ファイルにする.そして,テーブルのデータをサーバから取得する.

シリーズ

narutaro
今日もいいヤクの毛が刈れました
https://gist.github.com/narutaro/e8375fb26967b619748974122103ae79
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away