グローバルなコンポーネント

グローバルなコンポーネントとは、各ファイルで読み込んでcomponentsセクションに渡さなくとも使えるコンポーネントのことです。

グローバルコンポーネントの登録

Vue.componentという静的メソッドを使います。これは引数を2つ取り、それぞれ

  1. テンプレート上のコンポーネントの名前string
  2. datamountedなどを含む、いわゆる Vue コンポーネントのオブジェクト

を受け取ります。
ちなみに、コンポーネントの名前は-で繋いだ名前にすると良いです。

以下はmy-componentというコンポーネントの登録例です。

Vue.component('my-component', {
  data() {
    return {
      message: 'hello'
    }
  },
  mounted() {
    console.log(this.message);
  }
});

アプリをマウントする前に

new Vueでアプリをマウントする前に上記のコードで登録しておく必要があります。

Vue.component('...', {/* ... */});

new Vue({/* ... */});

Vue コンポーネントを作って npm で公開する

この内容は知見が貯まると共に変更になる可能性が大です。また Vue の最新がvue@2.6.10、Nuxt の最新がnuxt@2.8.0の時に書いています。

Vue コンポーネントを作って公開するおおよその流れは以下のような感じです。

  1. *.vueファイルを実装
  2. *.vueを Rollup を使ってビルド
  3. 生成されたファイルを npm で公開

ちなみに TypeScript とyarnを使っていきます。

*.vue ファイルを実装

まずは僕的に必要なパッケージをインストールします。必要なものは vuevue-property-decorator そして typeScript です。

yarn add -P vue@^2.6.0
yarn add -D \
  vue \
  vue-property-decorator \
  typescript

そしたら軽く*.vueを1つ作ります。src/index.vue辺りに、

<template>
  <div>
    <h1>{{message}}</h1>
  </div>
</template>

<script lang="ts">
import {Component, Vue} from 'vue-property-decorator';

@Component
export default class extends Vue {
  public message = 'hello';
}
</script>

<style>
h1 {
  color: orange;
}
</style>

とりあえず現在は対応が不十分のようなのでスタイルのスコープ機能は使わないようにするといいと思います。

*.vueを Rollup を使ってビルド

Webpack よりこちらのほうが出力コードが少ないです。その設定ファイルrollup.config.jsはこんな感じです。

import nodeResolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import typescript from 'rollup-plugin-typescript2';
import cssOnly from 'rollup-plugin-css-only';
import vue from 'rollup-plugin-vue';

export default {
  input: 'src/index.vue',
  external: ['vue'],
  plugins: [
    nodeResolve(),
    commonjs(),
    typescript({
      clean: true,
      objectHashIgnoreUnknownHack: true,
    }),
    cssOnly(),
    vue({css: false}),
  ],
};

上2つは環境によって変わります。typescriptのオプションはエラーを回避する為にこうなった的な感じです。下2つは今回のやり方では必須です。必要なプラグインはdevDependenciesに追加するかyarn add -Dが必要なので忘れずに。

下2つはvue({css: false})によって「JavaScript で<style>を作り Dom に挿入しなくていい」と設定しています。これはブラウザでのみ実行が想定するファイルを作る事になってしまうため、Nuxt などでエラーを起こしてしまいます。

実は今vue({css: false})により「*.cssということで扱う」(ソースコード中にimport '*.css'で使った)という意味にできています。この*.cssを抜き出し.cssファイルを作ってくれるのがrollup-plugin-css-onlyプラグインです。

さて Rollup の設定ファイルができたのであとは以下のようなコマンドで変換します。

rollup -c rollup.config.js --sourcemap --format esm --file dist/module/index.js

これは--format esmなので ES Module でdist/index.jsに吐き出されると思います。その時にindex.cssも同じディレクトリに存在すればうまくいってます。
同じように--format cjs --file dist/main/index.jsなどで CommonJS や他必要なものを生成します。

生成されたファイルを npm で公開

生成ファイルがちゃんとインストール先で読まれるようにpackage.jsonを編集します。

{
  "name": "vue-xxx",
  "main": "dist/main/index.js",
  "types": "typescript の型へのパス",
  "module": "dist/module/index.js",
  "source": "src/index.vue",
  "browser": "ブラウザ用にビルドしたファイルへのパス",
  "style": "dist/module/index.css"
}

nameには好きな名前を置きます。ただvue-とプレフィックスは付けたほうがいいと思います。あとはyarnで上げるだけです。

yarn publish
# 上によってコミットされたものを `git push`

メモ

CSS も JavaScript で挿入する形で最初考えていて、いろいろ試した結果_vm._ssrEscape is not a functionというエラーが出るまでは行きました。恐らく今度はサーバーサイドでは動いていてブラウザサイドで動かなくなった形な気はしましたがそこで力尽きました。

vue-property-decorator の使い方

kaorun343/vue-property-decoratorの中身は公式が提供しているvuejs/vue-class-componentというライブラリにいくつかデコレーターを増やしたような感じです。
このライブラリを使うことでよりクラスらしい形で書くことができます。

ちなみにコードは全て TypeScript を使っています。

プロパティ

Propデコレーターを使います。例です。

@Component
class extends Vue {
  @Prop(String) foo!: string;
}

これは、

  1. fooというプロパティを受け付けます
  2. それは文字列です

という風なことを定義しています。これは以下のような従来の書き方のものと同等になります。

{
  props: {
    foo: String
  }
}

同等に変換されるようにPropに渡せる引数も従来の設定と同じものを渡します。(参照: プロパティのバリデーション

データ

todo