data
プロパティに定義します。そしてこのデータプロパティはオブジェクトを返す関数である必要があります。
export default {
data() {
return {
value: "foo"
};
}
};
data
プロパティに定義します。そしてこのデータプロパティはオブジェクトを返す関数である必要があります。
export default {
data() {
return {
value: "foo"
};
}
};
コンポーネントオブジェクト(VueConstructor
)にprops
を置くと、親に対して「このコンポーネントは A という値が必要だから渡してね」のように伝えることができます。
一番簡単にてっとり早くそれを実装するには単にprops
に渡せるprops
名を配列で羅列するだけです。
{
props: [
'foo',
'barBaz'
]
}
これでfoo
とbarBaz
というプロパティを受け付けるようになりました。親からは、
<Child foo="a" bar-baz="b" />
のように値を渡すことができます。ご覧の通りbarBaz
のように設定したプロパティ名はテンプレート上ではfoo-baz
のようなケバブケースで使えます。
もし「foo
は数値がいい」「bar-baz
は関数がいい」という注文がある場合、props
をこのように書き換えます。
{
props: {
foo: Number,
barBaz: Function
}
}
使えるコンストラクタには他に、
String,
Boolean,
Array
Object,
Promise
class で定義したもの何でも
が使えます。つまりコンストラクタなら何でもです。
これで先程のままa
やb
という値を渡してしまった場合、「Invalid prop: type check failed for prop "<prop名>"
」というエラーが出ます。
しかしこれでもまだ不十分なケースがあります。それは値を絶対に渡してほしい場合です。つまり先程までのは、どちらかまたはどちらも渡さなくても通ってしまいます。
<Child :foo="1" />
「bar-baz
こそ必要なのに」という場合これでは困ってしまいます。Vue はあるプロパティについては必須にするというやり方も提供しています。それには先程のprops
をまた書き換える必要があります。
{
props: {
foo: Number,
barBaz: {
type: Function,
required: true
}
}
}
barBaz
だけが必須なので、それだけ書き換えてます。barBaz
をオブジェクトに変えコンストラクタをtype
に、そしてrequired: true
を増やします。
これでbar-baz
を渡さなかった時は「Missing required prop: "barBaz"
」というエラーがでるようになりました。
このprop
オブジェクトはdefault
というキーを持つことができます。これはprop
値が渡されなかった時代わりにそのプロパティ値に設定される値になります。
例のようなものを作りました。分かりづらい人はフォークして実際に触ってみてください。
テンプレートの中で条件分岐したい場合v-if
やv-else-if
、v-else
が使えます。これらは必ず同じ階層にある必要があります。またv-else-if
とv-else
は単体では使えず同階層にv-if
が必要です。
例です。
<template>
<span v-if="num === 1">one {{num}}</span>
<span v-else-if="num === 2">two {{num}}</span>
<span v-else>three {{num}}</span>
</template>
<script>
export default {
data() {
return {
num: 1
};
}
};
</script>
テンプレートでデータの数だけ繰り返し表示したい場合はv-for
属性を使います。この属性は配列とオブジェクトどちらでも回すことができます。この属性はループをラップする要素ではなく、ループする(繰り返し出現するタグ)に付けなければいけません。
また値を回す時、そのルートタグにはv-bind:key
(:key
)値の設定が必要です。
値だけを回す、値とインデックスを回すの2つの方法があります。
配列の要素だけを回したい時はitem in array
と置きます。in
の右側に配列値を置き、左側に各値が入る変数名を置きます。
<ul>
<li v-for="item in arr" :key="item">{{item}}</li>
</ul>
インデックスも一緒に回したい場合は左側を括弧で囲み第2引数のような形でインデックス値を受け取れます。
<ul>
<li v-for="(item, index) in arr" :key="item">{{item}}</li>
</ul>
こちらは
値だけ
値とキー
値とキーとインデックス
の3つの方法がありますが、大体は配列と同じです。1つの場合は直に、複数の場合は括弧で囲んで値を受け取ります。
<ul>
<li v-for="value in obj" :key="value">{{value}}</li>
</ul>
<ul>
<li v-for="(value, key, index) in obj" :key="key">{{key}} {{value}} {{index}}</li>
</ul>
グローバルなコンポーネントとは、各ファイルで読み込んでcomponents
セクションに渡さなくとも使えるコンポーネントのことです。
Vue.component
という静的メソッドを使います。これは引数を2つ取り、それぞれ
テンプレート上のコンポーネントの名前string
data
やmounted
などを含む、いわゆる Vue コンポーネントのオブジェクト
を受け取ります。
ちなみに、コンポーネントの名前は-
で繋いだ名前にすると良いです。
以下はmy-component
というコンポーネントの登録例です。
Vue.component('my-component', {
data() {
return {
message: 'hello'
}
},
mounted() {
console.log(this.message);
}
});
new Vue
でアプリをマウントする前に上記のコードで登録しておく必要があります。
Vue.component('...', {/* ... */});
new Vue({/* ... */});
この内容は知見が貯まると共に変更になる可能性が大です。また Vue の最新がvue@2.6.10
、Nuxt の最新がnuxt@2.8.0
の時に書いています。
Vue コンポーネントを作って公開するおおよその流れは以下のような感じです。
*.vue
ファイルを実装
*.vue
を Rollup を使ってビルド
生成されたファイルを npm で公開
ちなみに TypeScript とyarn
を使っていきます。
まずは僕的に必要なパッケージをインストールします。必要なものは vue と vue-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>
とりあえず現在は対応が不十分のようなのでスタイルのスコープ機能は使わないようにするといいと思います。
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 や他必要なものを生成します。
生成ファイルがちゃんとインストール先で読まれるように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
というエラーが出るまでは行きました。恐らく今度はサーバーサイドでは動いていてブラウザサイドで動かなくなった形な気はしましたがそこで力尽きました。
kaorun343/vue-property-decoratorの中身は公式が提供しているvuejs/vue-class-componentというライブラリにいくつかデコレーターを増やしたような感じです。
このライブラリを使うことでよりクラスらしい形で書くことができます。
ちなみにコードは全て TypeScript を使っています。
Prop
デコレーターを使います。例です。
@Component
class extends Vue {
@Prop(String) foo!: string;
}
これは、
foo
というプロパティを受け付けます
それは文字列です
という風なことを定義しています。これは以下のような従来の書き方のものと同等になります。
{
props: {
foo: String
}
}
同等に変換されるようにProp
に渡せる引数も従来の設定と同じものを渡します。(参照: プロパティのバリデーション)
todo