1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Vue.js を使ってみたの続き

Last updated at Posted at 2023-11-11

はじめに

いわゆるウェブアプリを作るのに自分は Vue.js を使っています。

Vue.js を使ってみた - Qiita
Onsen UI+Vue.js を使ってみた - Qiita

ただし、Vue 3 を使っていませんでした。また、コンポーネントも使っていませんでした。
今後の開発に使うかどうか分かりませんが、勉強しておこうと思いました。

Vue.js を使ってみた

・Vue.2.7
・Vue 3.3

インストールする

Vue.js のアプリを作るには、Node.js を使ってローカルな開発環境を構築するのが一般的なようです。

Vue.jsのインストール → プロジェクト作成と起動まで~ - Qiita

今回はあくまでも HTML ファイル一つで、ブラウザだけで動く Vue.js アプリを作っていきたいと思います。

HTML ファイルに以下を追記します。

    <script src="https://unpkg.com/vue@2.7.10/dist/vue.min.js"></script>

Vue 3 のとき↓

    <script src="https://unpkg.com/vue@3.3.7/dist/vue.global.prod.js"></script>

マウントする

Vue オブジェクトで管理する対象になる HTML タグを指定するのに、オプション指定の el プロパティを使います。↓

    <div id='root'>
      <p>Hello, {{ name }}.</p>
    </div>
<script>
    var name = "Vue.js";

    new Vue({
      el: '#root',
      data: {
        name: name
      }
    });

Vue オブジェクトを生成しておいて、HTML タグに mount する書き方があります。↓

参考:マウントのしかた まとめ - Qiita

<script>
    var name = "Vue.js";

    var vm = new Vue({
      data: {
        name: name
      }
    });
    vm.$mount('#root');

Vue 3 の書き方↓

参考:Vue2 Vue3 比較(new Vue() vs createApp())- Qiita

    let name = "Vue.js";

    const app = Vue.createApp({
      data() {
        return {
          name: name
        };
      } 
    });
    app.mount('#root');

data の書き方を変えないといけません。↑

コンポーネントを作成する

Vue.js も React.js のように、コンポーネントを作って利用することができます。

参考:コンポーネントの基本 — Vue.js

<script>
    Vue.component('v-element', {
      props: [ 'name' ],
      template: `<p>Hello, {{ name }}.</p>`
    });

    new Vue({
      el: '#root'
    });
    <div id='root'>
      <v-element name="Vue.js" />
    </div>

独自タグを作れると言ってよさそうです。↑
呼出元から値を渡してコンポーネントで受取して使用できます。

HTML タグはマウントするポイントだけにして、Vue オブジェクトの template に内容を記述してマウントする書き方もできます。

    <div id='root' />
<script>
    var vm = new Vue({
      template: `<v-element name="Vue.js" />`
    });
    
    Vue.component('v-element', {
      props: [ 'name' ],
      template: `<p>Hello, {{ name }}.</p>`
    });

    vm.$mount('#root');

Vue 3 のとき↓

参考:【vue3】component基礎 #JavaScript - Qiita

<script>
    const app = Vue.createApp({
      template: '<v-element name="Vue.js" />'
    });

    app.component('v-element', {
      props: [ 'name' ],
      template: `<p>Hello, {{ name }}.</p>`
    });

    app.mount('#root');

コンポーネントに状態を加える

コンポーネントは、呼出元から値を受取って使うだけでなく、内部で値を保持して使用します。
datamethods を用意します。

カウントアップするボタンのコンポーネントを作ってみます。↓

    Vue.component('v-element', {
      data() {
        return {
          count: 0
        }
      },
      methods: {
        addCount() {
          this.count += 1;
        }
      },
      template: `
        <div>
          <p>count: {{ count }}</p>
          <button v-on:click='addCount'>+</button>
        </div>
      `
    });

Vue 3 の書き方↓

    app.component('v-element', {
      data() {
        return {
          count: 0
        }
      },
      methods: {
        addCount() {
          this.count += 1;
        }
      },
      template: `
        <div>
          <p>count: {{ count }}</p>
          <button v-on:click='addCount'>+</button>
        </div>
      `
    });

コンポーネント間で状態を共有する①

親のコンポーネントで定義された変数を、埋込された子のコンポーネントで参照して使用したいことがあります。

参考:Vue.jsコンポーネント間でデータをやり取りする方法

子コンポーネントで props を定義します。親コンポーネントから v-bind で子コンポーネントに値を渡せるようになります。

    Vue.component('v-child', {
      props: [ 'count' ],
      template: `
        <div>
          <p>Child</p>
          <p>count: {{ count }}</p>
        </div>
      `
    });
    Vue.component('v-parent', {
      data() {
        return {
          count: 0
        }
      },
      methods: {
        addCount(){
          this.count += 1;
        }
      },
      template: `
        <div>
          <p>Parent</p>
          <p>count: {{ count }}</p>
          <button v-on:click='addCount'>+</button>
          <v-child v-bind:count='count' />
        </div>
      `
    });

Vue 3 の書き方↓

    app.component('v-child', {
      props: [ 'count' ],
      template: `
        <div>
          <p>Child</p>
          <p>count: {{ count }}</p>
        </div>
      `
    });
    app.component('v-parent', {
      data() {
        return {
          count: 0
        }
      },
      methods: {
        addCount() {
          this.count += 1;
        }
      },
      template: `
        <div>
          <p>Parent</p>
          <p>count: {{ count }}</p>
          <button v-on:click='addCount'>+</button>
          <v-child v-bind:count='count' />
        </div>
      `
    });

親コンポーネントで値を変えると子コンポーネントの値も変わります。

コンポーネント間で状態を共有する②

上記の例は、子のコンポーネントで値を変えても、親のコンポーネントの値は変わりません。
親コンポーネントで定義された変数を、子コンポーネントで参照して変更して、それを親コンポーネントで使用したいことがあります。

参考:Vue.jsコンポーネント間でデータをやり取りする方法

親コンポーネントに値を渡したいタイミングで、子コンポーネントでイベントを emit します。親コンポーネントは v-on でイベントを受取して、そこでメソッドを呼出して値を受取できます。

    Vue.component('v-child', {
      props: [ 'count' ],
      methods: {
        addCount() {
          this.count += 1;
          this.$emit('CountChanged', this.count);
        }
      },
      template: `
        <div>
          <p>Child</p>
          <p>count: {{ count }}</p>
          <button v-on:click='addCount'>+</button>
        </div>
      `
    });
    Vue.component('v-parent', {
      中略
      methods: {
        中略
        countChanged(value) {
          this.count = value;
        }
      },
      template: `
        <div>
          <p>Parent</p>
          <p>count: {{ count }}</p>
          中略
          <v-child v-bind:count='count' v-on:CountChanged='countChanged' />
        </div>
      `
    });

Vue 3 の書き方↓

参考:emits オプション | Vue 3 移行ガイド

    app.component('v-child', {
      props: [ 'count' ],
      emits: [ 'CountChanged' ],
      setup(props, context) {
        return {
          addCount() {
            props.count += 1;
            context.emit('CountChanged', props.count);
          }
        }
      },
      template: `
        <div>
          <p>Child</p>
          <p>count: {{ count }}</p>
          <button v-on:click='addCount'>+</button>
        </div>
      `
    });
    app.component('v-parent', {
      中略
      methods: {
        中略
        countChanged(value) {
          this.count = value;
        }
      },
      template: `
        <div>
          <p>Parent</p>
          <p>count: {{ count }}</p>
          中略
          <v-child v-bind:count='count' v-on:CountChanged='countChanged' />
        </div>
      `
    });

子コンポーネントで値を変えると親コンポーネントの値も変わります。

コンポーネント間で状態を共有する③

          <v-child v-bind:count='count' v-on:CountChanged='countChanged' />

v-onv-bindv-bind に書換してみます。

          <v-child v-model='count' />

Vue 2 の場合、これは以下と同じです。

          <v-child v-bind:value='count' v-on:input='count = $event.target.value' />

参考:v-model を正しく理解して親子間コンポーネントのデータ伝播をマスターする - Qiita

これに合わせて子コンポーネントの propsemit を書換します。

    Vue.component('v-child', {
      props: [ 'value' ],
      methods: {
        addCount() {
          this.value += 1;
          this.$emit('input', this.value);
        }
      },
      以下略

Vue 3 の書き方↓

参考:v-model | Vue 3 移行ガイド

v-model に引数を指定できるので、引数 count で子に渡すようにします。子で emit するイベントは、引数 count を指定して update します。

          <v-child v-model:count='count' />
    app.component('v-child', {
      props: [ 'count' ],
      emits: [ 'update' ],
      setup(props, context) {
        return {
          addCount() {
            props.count += 1;
            context.emit('update:count', props.count);
          }
        }
      },
      以下略

コンポーネント間で状態を共有する④

コンポーネント間で状態を共有する、別の方法です。

参考:Vue.jsでコンポーネント間のデータ受け渡し(Provide/Inject) - Qiita

親コンポーネントで provide して、子コンポーネントで inject します。

    Vue.component('v-parent', {
      data() {
        return {
          count: 0
        }
      },
      provide() {
        return {
          count: Vue.computed(() => this.count),
          updateCount: (value) => this.count = value,
        };
      },
      以下略

    Vue.component('v-child', {
      inject: [ 'count', 'updateCount' ],
      methods: {
        addCount() {
          this.updateCount(this.count + 1);
        }
      },
      以下略

Vue 3 の書き方↓

    app.component('v-parent', {
      data() {
        return {
          count: 0
        }
      },
      provide() {
        return {
          count: Vue.computed(() => this.count),
          updateCount: (value) => this.count = value,
        };
      },
      以下略

    app.component('v-child', {
      inject: [ 'count', 'updateCount' ],
      methods: {
        addCount() {
          this.updateCount(this.count + 1);
        }
      },
      以下略

親コンポーネントで用意した変数 count に対して、これを更新するメソッド updateCount と一緒に provide します。この変数とメソッドを、子コンポーネントで inject して利用できるようにします。子コンポーネントで updateCount を使って変数 count を更新すると、親コンポーネントの count が更新されます。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?