LoginSignup
27
30

More than 3 years have passed since last update.

Vue.js: マウントのしかた まとめ

Posted at

Vue.jsでコンポーネント用のオブジェクト(オプションオブジェクト)をマウントする方法のまとめです。

オプションオブジェクトは別ファイルに分けましょう

Vue.jsのサイトや入門書では、次のように new Vue にオブジェクトを丸ごと入れる書き方が紹介されています。

var app = new Vue({
  el: '#app',
  data() {
    return {
      message: 'hello'
    };
  }
});

これはよい方法ではありません。実際に運用されるアプリケーションでこの書き方をすると、オブジェクトの内容が長くなったときに、ソースコードが読みづらくなります。

オプションオブジェクトは別のjsファイルまたはvueファイルにしてエクスポート、インポートするようにしましょう。

HTMLファイル
<div id="app"></div>
オプションオブジェクト(vueファイル)
<template>
 <div>
  {{message}}
 </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'hello'
    };
  }
})
</script>
マウントするJavaScript
import Vue from 'vue';
import App from './app.vue';

new Vue(App).$mount('#app');

この書き方をするにはWebpackが必要で面倒ですが、Vue.jsの学習を始めるときにも、最初からファイルを分ける書き方で行くのがおすすめです。これは、仕事で作ったプロジェクトに入門用の書き方を持ち込んでしまい、メンテしづらいコードにしてしまったという私の反省です。

学習用にWebpackを使うには、Vue CLIを使うのが簡単です。Railsの人はWebpackerを使えばいいでしょう。手作業でスクラッチからWebpackを使うこともできます。

マウントの基本形

繰り返しになりますが、オプションオブジェクトをマウントするには、最初は次の形だけ覚えればよいでしょう。

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

new Vue(App).$mount('#app');

Vue 3では、次のようになります。mount$が付かないことに注意しましょう。

import { createApp } from 'vue';
import App from './app.vue';

createApp(App).mount('#app');

テンプレートがHTML内にある場合

VueのテンプレートをHTML内に置く場合も、同じような形になります。オプションオブジェクトのファイルはjsファイルでもいいですし、<script> ... </script> だけのvueファイルでもいいです。

HTMLファイル
<div id="app">
  {{message}}
</div>
オプションオブジェクト(jsファイル)
export default {
  data() {
    return {
      message: 'hello'
    };
  }
})
マウントするJavaScript
import Vue from 'vue';
import App from './app.js';

new Vue(App).$mount('#app');

この場合は、マウント時にHTML内の <div id="app"> ... </div> はDOMツリーから削除され、テンプレートを元に作られた新しいdiv要素が埋め込まれます(jQueryであれこれしたいときは、mountedメソッドに書かなければならないのはこのためです)。

elオプション

どのHTML要素にマウントするのかを指定するのにelオプションを使うこともできます。elオプションがあると、$mountメソッドを呼ばなくても自動的にマウントされます。

マウントするJavaScript
import Vue from 'vue';
import App from './app.js';

new Vue({ ...App, el: '#app' });

Vue 3のcreateAppではelオプションが効きません。Vue 3に備えるために、elオプションは使わずに上記の基本形を使うとよいでしょう。

propsを渡す方法

次のようにプロパティ(props)のあるVueコンポーネントもマウントできます。

オプションオブジェクト(vueファイル)
<template>
  <div>
    <h1 :style="{color: color}">{{message}}</h1>
  </div>
</template>

<script>
export default {
  props: ['color'],
  data() {
    return {
      message: 'hello'
    };
  }
}
</script>

マウントするときは、renderだけのオブジェクトを作り、その中でhメソッドの第1引数にインポートしたオブジェクト、第2引数にプロパティを渡す、という形にします。

Vue.jsのマウントのしかたについては、これと上記の基本形の2パターンだけ覚えればいいと思います。

マウントするJavaScript
import Vue from 'vue';
import App from './app.js';

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

Vue 3では次のようにします。記述量がちょっと減りました。

マウントするJavaScript
import { createApp, h } from 'vue';
import App from './app.js';

createApp({
  render: () => h(App, { color: 'red' })
}).mount('#app');

propsDataオプションとVue 3での書き方

上記のようにプロパティを渡すと、親コンポーネント(renderだけのオブジェクトによる)とその子コンポーネント(インポートしたオブジェクトによる)の2つが作られます。これはちょっと無駄な感じがします。

また、テンプレートのないオブジェクト(HTML内にテンプレートを置く場合など)では、上記のrenderを使ったマウントはできません。

あまり紹介されることのないpropsDataというオプションでプロパティを渡すことができます。この場合はコンポーネントが1つだけで済みます。

マウントするJavaScript
import Vue from 'vue';
import App from './app.js';

new Vue({ ...App, propsData: { color: 'red' } }).$mount('#app');

ただし、Vue 3のcreateAppではpropsDataが効きません。その代わり、createAppの第2引数にプロパティを渡せるようになりました。これは便利。

マウントするJavaScript
import { createApp } from 'vue';
import App from './app.js';

createApp(App, { color: 'red' }).mount('#app');

おまけ

引数を渡さずに$mountメソッドを読んでもVueコンポーネントができます。この場合、$elは親のないDOMオブジェクトとなるので、appendChildなどで追加します。

この例はRailsのrails webpacker:install:vue でできるファイルで見つけました。

マウントするJavaScript
import Vue from 'vue';
import App from './app.js';

let app = new Vue(App1).$mount();
document.getElementById('app1').appendChild(app.$el);

なお、この方法はVue 3では使えません。

27
30
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
27
30