LoginSignup
0
1

More than 3 years have passed since last update.

vue.jsを初めて学ぶ ⑤ [ コンポーネントの扱いについて ]

Posted at

前回までの記事

vue.jsを初めて学ぶ ① [hello world]

vue.jsを初めて学ぶ ② [テンプレート構文]

vue.jsを初めて学ぶ ③ [レンダリング]

vue.jsを初めて学ぶ ④ [VueCLI 3.7.0 + Vue.js 2系のインストール]

目次

1. Vue.jsの、コンポーネントとは?

2. ローカル登録とグローバル登録について

3. Vueプロジェクトにおける、コンポーネントの概念

4. templateタグの注意点とは?

5. ケバブケースとパスカルケースの記法について

6. (親と子)コンポーネント間のデータ受け渡しについて




コンポーネントとは

以前までの記事とは、書き方が異なってくる

いいね数を表示する

従来のVue.js書き方

index.html

<div id="app">
</div>
index.js

new Vue({
  el:'#app',
  data: {
    number: 12
  },
  template: '<p>いいね{{number}}</p>'
})

コンポーネントを利用した書き方

index.html

<div id="app">
  <my-component></my-component>
</div>
index.js

Vue.component('my-component', {
  data: function(){
    return {
      number: 12
    }
  },
  template: '<p>いいね{{number}}</p>'
})

new Vue({
  el:'#app',
})
  1. Vue.componentを作成する。

  2. Vue.componentでは、
    第1引数=>[コンポーネント名]
    第2引数=>[プロパティ]
    が入る

  3. Vue.component内のdataプロパティでは、
    関数(returnによる返り値)を用意しないと駄目

  4. new Vueインスタンス内のelプロパティでは、
    html側の'#app'を指定している

  5. html側では、
    コンポーネント名の第1引数をタグとして用意
    代入される。

なぜ?
コンポーネントでは、
dataプロパティ内の変数を
関数として扱わないと駄目か?

  1. オブジェクト形式では、
    変数が参照→変数に処理が加わる
    全コンポーネントで適用

  2. 関数の形式では、
    変数に処理が加わる
    単体のコンポーネントのみに適用

実例 : +1されるボタン(オブジェクトver)

index.html
  <div id="app">
    <my-component></my-component>
    <my-component></my-component>
    <my-component></my-component>
  </div>
index.js

//無理やり、オブジェクト形式のdataをreturnにセットしている。
    var data = {
      number: 12
    }

    Vue.component('my-component', {
      data: function(){

//returnされているけど、中身はオブジェクトのnumberが入っている。
          return data
      },
      template: '<p>いいね{{number}}<button v-on:click="countUp">+1</button></p>',
      methods: {
        countUp: function(){
          this.number += 1;
        }
      }
    }),
    new Vue({
      el:'#app',
    })

オブジェクト形式のnumber(12)を+1すると、

スクリーンショット 2020-10-29 19.40.14.png

すべてのコンポーネント内の変数numberに適用

実例 : +1されるボタン(関数ver)

index.html
  <div id="app">
    <my-component></my-component>
    <my-component></my-component>
    <my-component></my-component>
  </div>
index.js

    Vue.component('my-component', {
      data: function(){
        return {
          number: 12
        }
      },
      template: '<p>いいね{{number}}<button v-on:click="countUp">+1</button></p>',
      methods: {
        countUp: function(){
          this.number += 1;
        }
      }
    }),
    new Vue({
      el:'#app',
    })

単体のコンポーネントに対して適用されているのが分かる。

スクリーンショット 2020-10-29 19.42.52.png


ローカル登録 と グローバル登録

グローバル登録とは?

  • 全インスタンスが使用できる
index.html

  <div id="app">
    <my-component></my-component>
    <my-component></my-component>
    <my-component></my-component>
    <hr>
  </div>

  <div id="app2">
    <my-component></my-component>
    <my-component></my-component>
    <my-component></my-component>
    <hr>
  </div>
index.js

    Vue.component('my-component', {
      data: function(){
        return {
          number: 12
        }
      },
      template: '<p>いいね{{number}}<button v-on:click="countUp">+1</button></p>',
      methods: {
        countUp: function(){
          this.number += 1;
        }
      }
    }),
    new Vue({
      el:'#app',
    })
    new Vue({
      el:'#app2',
    })

グローバル登録の結果

スクリーンショット 2020-10-29 20.14.44.png

インスタンス'div#app''div#app2' どちらも適用


ローカル登録とは?

  • 特定のインスタンスのみが使用できる
index.html

  <div id="app">
    <my-component></my-component>
    <my-component></my-component>
    <my-component></my-component>
    <hr>
  </div>

  <div id="app2">
    <my-component></my-component>
    <my-component></my-component>
    <my-component></my-component>
    <hr>
  </div>
index.js

    var component = {
      data: function(){
        return {
          number: 12
        }
      },
      template: '<p>いいね{{number}}<button v-on:click="countUp">+1</button></p>',
      methods: {
        countUp: function(){
          this.number += 1;
        }
      }
    }

    new Vue({
      el:'#app',
      components: {
        'my-component': component
      }
    })
    new Vue({
      el:'#app2',
    })
  1. varで、
    変数を用意する。

  2. 変数に、
    グローバル登録していた
    コンポーネントの 第2引数 をすべて格納する。

  3. ローカル登録したいインスタンスへ、
    componentsプロパティ を持たせる。

  4. componentsプロパティ は、
    オブジェクト形式
    ・キーにhtml側で代入するタグ名
    ・バリューには先程格納した変数名
    を指定する

ローカル登録の結果

スクリーンショット 2020-10-29 20.13.43.png

インスタンス 'div#app' のみに、divタグが適用


コンポーネントの概念

  • Vueプロジェクトでは、
    main.js内のimportによって、
    ・指定の.vueファイル
    を読み込んでコンポーネントとして使用している。

  • App.vueファイルでは、
    importによって、
    ・componentsディレクトリ配下の.vueファイル
    を読み込んでコンポーネントとして使用している。

[Vue-CLI3.7.0によって、vue createされたディレクトリ構成]
スクリーンショット 2020-10-29 22.20.06.png

main.js
// (1) 
import App from './App.vue'

// (2)
new Vue({
  render: h => h(App),
}).$mount('#app')
App.vue

<script>
// (3) 
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
// (4)
    HelloWorld
  }
}
</script>

  1. ファイルのimport時に、
    コンポーネント名がfromで指定される。
    各インスタンスで、使用できる

templateタグの注意点

親要素として一つでないと、エラーとなる。

+1をするメソッド追加 エラー パターン

main.js

import Vue from 'vue'
import App from './App.vue'

// グローバル登録(1)
import LikeNumber from "./LikeNumber.vue"

Vue.config.productionTip = false

// グローバル登録(1)
Vue.component('LikeNumber', LikeNumber);

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

App.vue

<template>
  <LikeNumber></LikeNumber>
</template>
LikeNumber.vue

<template>
// 親要素が2つだと、エラーになる!
    <p>いいね({{number}})</p>
    <button @click="countUp">+1</button>
</template>

<script>
export default {
  data() {
    return {
      number: 6
    }
  },
  methods: {
    countUp(){
      this.number += 1;
    }
  }
}
</script>

divタグで括り、親要素を1つに

LikeNumber.vue

<template>
  <div>
    <p>いいね({{number}})</p>
    <button @click="countUp">+1</button>
  </div>
</template>

これでエラーがなくなる


ケバブとパスカルケース記法

App.vue(パスカルケース)
<LikeHeader></LikeHeader>
App.vue(ケバブケース)
<like-header></like-header>

プロジェクト内では、どちらかのケース記法で統一しよう。

・HTML要素は、ケバブケース
なので目視でわかりやすくするため
パスカルケースがおすすめ

htmlタグ内では、ケバブケース記法統一がおすすめ!

App.vue
// キャメルケース
    <LikeNumber :totalNumber="number"></LikeNumber>

// ケバブケース
    <LikeNumber :total-number="number"></LikeNumber>

htmlでは、大文字を判別できない。
公式でもhtmlタグ内では、ケバブケースを推奨


コンポーネント間のデータ受け渡し

親要素から子要素への、データ受け渡し

各いいね数とトータルいいね数

App.vue

<template>
  <div>
    <likeHeader></likeHeader>
    <h2>{{ number }}</h2>
    <LikeNumber :number="number"></LikeNumber>
    <LikeNumber :number="number"></LikeNumber>
  </div>
</template>

<script>
import LikeHeader from "./components/LikeHeader.vue";
export default {
  data() {
    return {
      number: 10
    }
  },
  components: {
    LikeHeader
  }
}
</script>

親要素であるApp.vue内
dataプロパティ
number:10 を受け渡す

propsプロパティを使用する

LikeNumber.vue

<template>
  <div>
    <p>いいね({{ number / 2 }})</p>
  </div>
</template>

<script>
export default {
  props: ["number"],
}
</script>

子要素であるLikeNumber.vue内にて、
propsプロパティを 配列[ ] で指定する。
number:10が使用できる。

スクリーンショット 2020-10-30 10.43.51.png


子要素から親要素への、データ受け渡し

+1ボタンを子要素に設置、押すと親要素のトータルいいね数が変更される。

  • $emit が必須!
    • カスタムイベントを作成できる。
App.vue

<template>
  <div>
    <likeHeader></likeHeader>
    <h2>{{ number }}</h2>
    <LikeNumber :total-number="number" @my-click="number = $event"></LikeNumber>
    <LikeNumber :total-number="number"></LikeNumber>
  </div>
</template>

<script>
import LikeHeader from "./components/LikeHeader.vue";
export default {
  data() {
    return {
      number: 10
    }
  },
  components: {
    LikeHeader
  }
}
</script>
LikeNumber.vue

<template>
  <div>
    <p>いいね({{ harfNumber }})</p>
    <button @click="incriment">+1</button>
  </div>
</template>

<script>
export default {
  props: ["totalNumber"],
  computed: {
    harfNumber() {
      return this.totalNumber / 2;
    }
  },
  methods: {
    incriment() {
      this.$emit("my-click", this.totalNumber +1);
    }
  }
};
</script>
  1. LikeNumber.vueファイル内で、
    methodsプロパティで、
    totalNumberに+1する関数を作成。

    $emitを用いて、
    ・第1引数にカスタムイベント名
    ・第2引数にイベント処理

    を書く

  2. App.vueファイル内で、
    v-on:my-click時
    親要素のnumberが$emitで発火した値を$eventで拾い、値を更新する。

スクリーンショット 2020-10-30 11.01.22.png


0
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
0
1