Edited at

Vue.jsで〇〇なときどう書く?


はじめに

Vue.jsを書いている時に、「〇〇なときどう書いたっけな?」と困ることがあったりするので、備忘録として残していくだけの記事です。

では始めていきましょう。


前提

ここで紹介するVueファイルを構成するソースコードは、 Pug / TypeScript / Scss とします。

また、UIコンポーネントにElementUIを採用しています。


ソースコード

githubにPushしてます。

https://github.com/ryo-is/vue-demo-sample


1. onClickやonChangeで関数を呼びたいとき

@click や @change を使う。

この @hoge というのは v-on:hoge 表記の省略形です。


1-1. ClickEvent

下記の例では、ボタンをクリックすると countNumber を1ずつ増やしています。


template

.click-event

.child-title ClickEvent デモ
el-row
el-col(:span="16")
el-button(@click="addCount") カウントアップ
el-col(:span="2")
.count-number {{ countNumber }}


script

import { Component, Vue } from "vue-property-decorator";

@Component({})
export default class ClickEventComponent extends Vue {
public countNumber: number = 0;

public addCount() {
this.countNumber += 1;
}
}



1-2. ChangeEvent

セレクトボックスの選択肢を変更した時にテキストの内容 ( selectedText ) を書き換えています。


template

.change-event

.child-title ChangeEvent デモ
el-row
el-col(:span="16")
el-select(v-model="selectItem" @change="changeItem")
el-option(label="Apple" value="Apple") Apple
el-option(label="Banana" value="Banana") Banana
el-option(label="Orange" value="Orange") Orange
el-col(:span="4")
.select-text {{ selectedText }}


script

import { Component, Vue } from "vue-property-decorator";

@Component({})
export default class ChangeEventComponent extends Vue {
public selectItem: string = "";
public selectedText: string = "";

public changeItem() {
this.selectedText = this.selectItem;
}
}



2. 要素の表示 / 非表示を切り替えたいとき

v-showv-if を使う。


2-1. v-show の場合

ボタンをクリックした時に displayFlag を切り替えています。

trueなら display:block 、falseなら display:none となります。


template

.v-show

.child-title v-showによる表示/非表示切り替え
.button-area
el-button(@click="displayFlag=!displayFlag") 切り替えボタン
img.logo-img(v-show="displayFlag" alt="" src="../../assets/logo.png")


script

import { Component, Vue } from "vue-property-decorator";

@Component({})
export default class vShowComponent extends Vue {
public displayFlag: boolean = true;
}



2-2. v-if の場合

v-show とは少し違って条件式を書くことができるので、表示/非表示の状態を、割と自由に設定することができます。

下記の例では、ボタンをクリックした時に displayFlagindicate または hide に切り替えています。

indicate なら display:blockhide なら display:none となります。


template

.v-if

.child-title v-ifによる表示/非表示切り替え
.button-area
el-button(@click="changeDisplayFlag") 切り替えボタン
img.logo-img(v-if="displayFlag==='indicate'" alt="" src="../../assets/logo.png")


script

import { Component, Vue } from "vue-property-decorator";

@Component({})
export default class vIfComponent extends Vue {
public displayFlag: string = "indicate";

public changeDisplayFlag() {
if (this.displayFlag === "indicate") {
this.displayFlag = "hide";
} else {
this.displayFlag = "indicate";
}
}
}



3. 要素の表示 / 非表示にアニメーションを付けたいとき

transition を使う。

transitionとは、Vueがデフォルトで用意してくれている、 DOM からアイテムが追加、更新、削除されたときにトランジション効果を適用するための方法です。

先程の v-show のソースコードを少し書き換えます。


template

.v-show

.child-title v-show デモ
.button-area
el-button(@click="displayFlag=!displayFlag") 切り替えボタン
transition(name="image-transition")
img.logo-img(v-show="displayFlag" alt="" src="../../assets/logo.png")

transitionのnameで渡している値 (上記のソースコード内で言う image-transition ) が、Styleの image-transition-enter-active に対応するので、Styleを調整するときは下記のように書くことができます。


style

.v-show {

.image-transition-enter-active,
.image-transition-leave-active {
transition: all .5s;
}

.image-transition-enter,
.image-transition-leave-to {
opacity: 0;
transform: translateY(-10px);
}
}



4. 要素を繰り替えし生成したいとき

v-for を使う。

下記の例では ["Apple", "Banana", "Orange"] という文字列をli要素として生成しています。


template

.v-for

.child-title v-for デモ
ul.list-items
li(v-for="item in listItems" :key="item") {{ item }}


script

import { Component, Vue } from "vue-property-decorator";

@Component({})
export default class vForComponent extends Vue {
public listItems: string[] = ["Apple", "Banana", "Orange"];
}



5. inputの要素を変数に保存したいとき

v-model を使う。

下記の例では、テキストエリアに入力した値を、別要素のテキストとして表示しています。


template

.v-model

.child-title v-model デモ
el-row
el-col(:span="10")
el-input(v-model="inputText")
el-col(:span="14")
.input-text {{ inputText }}


script

import { Component, Vue } from "vue-property-decorator";

@Component({})
export default class vModelComponent extends Vue {
public inputText: string = "";
}



6. 親Componentの関数を子Componentから呼び出したいとき

$emit を使う。

下記の例では、子Componentのボタンをクリックしたら、親Componentのテキストを非表示にしたり、表示したりしています。


子Component


template(ChildComponent)

.emit

.child-title $emit デモ
el-button(@click="$emit('changeTitleDisplay')") タイトル表示/非表示


親Component


template(ParentComonent)

.home

.title(v-show="titleDisplay") {{ homeTitle }}
emitComponent(v-on:changeTitleDisplay="changeTitleDisplay")


script(ParentComonent)

import { Component, Vue } from "vue-property-decorator";

import emitComponent from "@/components/emit/Emit.vue";

@Component({
components: {
emitComponent,
},
})
export default class Home extends Vue {
public homeTitle: string = "Vue Demo Sapmle";
public titleDisplay: boolean = true;

public changeTitleDisplay() {
this.titleDisplay = !this.titleDisplay;
}
}



7. 動的にclassを切り替えたいとき

v-bind:class を使う。

下記の例では、タイトルのClassを変更することで、文字色を変更しています。


template

.change-class

.child-title(v-bind:class="fontColorClass") Change Class デモ
el-button(@click="changeFontColor('red')") 赤色に変更
el-button(@click="changeFontColor('yellow')") 黄色に変更
el-button(@click="changeFontColor('normal')") 元に戻す


script

import { Component, Vue } from "vue-property-decorator";

@Component({})
export default class ChangeClassComponent extends Vue {
public fontColorClass: string = "normal-font-color";

public changeFontColor(color: string) {
this.fontColorClass = color + "-font-color";
}
}



style

.change-class {

.red-font-color {
color: red;
};

.yellow-font-color {
color: yellow;
}
}



8. 子Componentに値を渡したいとき

Prop を使う。

下記の例では、親Componentから子Componentに直接テキストを渡したり、インスタンス変数を渡したりしています。


子Component


template(ChildComponent)

.prop

.child-title Prop デモ
.prop-text {{ propText }}
.prop-value {{ propValue }}


script(ChildComponent)

import { Component, Vue, Prop } from "vue-property-decorator";

@Component({})
export default class PropComponent extends Vue {
@Prop() public propText: string;
@Prop() public propValue: string;
}



親Component


template(ParentComponent)

.home

propComponent(:prop-text="'Propで値を子Componentに渡す'", :prop-value="propValue")


script(ParentComponent)

import { Component, Vue } from "vue-property-decorator";

import propComponent from "@/components/prop/Prop.vue";

@Component({
components: {
propComponent,
},
})
export default class Home extends Vue {
public propValue: string = "インスタンス変数を子Componentに渡す";
}



9. 親Componentから子Componentを識別したいとき (2019/01/10 追記)

ref を使う。

親コンポーネントの template に子コンポーネントを読み込むときに ref 属性を定義すると vm.$refs で子コンポーネントを識別することができます。

ただ注意が必要なのが created() の段階ではまだ子コンポーネントがインスタンス化されていないので取得できません。 mounted() やClickなどのイベントなどで取得しましょう。

下記の例では子コンポーネントの変数を取得して、標準出力しています。


子Component


template(ChildComponent)

.ref

.child-title Ref デモ


script(ChildComponent)

import { Component, Vue } from "vue-property-decorator";

@Component({})
export default class RefComponent extends Vue {}



親Component


template(ParentComponent)

.home

refComponent(ref="refDemo")


script(ParentComponent)

import { Component, Vue } from "vue-property-decorator";

import refComponent from "@/components/ref/Ref.vue";

@Component({
components: {
refComponent,
},
})
export default class Home extends Vue {
public created() {
const refDemoComponent: refComponent = this.$refs.refDemo as refComponent;
console.log(refDemoComponent); // undefined
}

public mounted() {
const refDemoComponent: refComponent = this.$refs.refDemo as refComponent;
console.log(refDemoComponent);
}
}



10. 親Componentから子Componentの関数を呼びたいとき (2019/01/10 追記)

ref を使う。

「9. 親Componentから子Componentを識別したいとき」と同じように ref を使っていきます。

下記の例では親Componentの mounted() のタイミングで、子Componentのメソッドを呼び出して、変数に代入しています。

途中型宣言がうまくできなくてやむなく any を使っています…ここきれいに型宣言できる方法知っている方いたら、コメントいただけると幸いです。


子Component


template(ChildComponent)

.ref

.child-title Ref デモ


script(ChildComponent)

import { Component, Vue, Prop } from "vue-property-decorator";

@Component({})
export default class RefComponent extends Vue {
public sampleText: string = "Refのデモです";

public returnText(): string {
return this.sampleText;
}
}



親Component


template(ParentComponent)

.home

refComponent(ref="refDemo")
.ref-demo-text {{ refDemoText }}


script

import { Component, Vue } from "vue-property-decorator";

import refComponent from "@/components/ref/Ref.vue";

@Component({
components: {
refComponent,
},
})
export default class Home extends Vue {
public refDemoText: string = "";

public mounted() {
const refDemoComponent: any = this.$refs.refDemo; // ここの型宣言がうまくできなかった…
this.refDemoText = refDemoComponent.returnText();
}
}



11. Propの変数が更新されたら子Componentも更新したいとき (2019/01/10 追記)

ref を使う。

「9. 親Componentから子Componentを識別したいとき」と同じように ref を使っていきます。

というよりは「10. 親Componentから子Componentの関数を呼びたいとき」の応用です。

下記の例では、親Componentのテキストボックスの内容(refInputText)をpropで子Componentの値(refText)に渡していて、 refInputText を更新した時に、子Componentの updateRefText() を呼び出して refText を更新しています。


子Component


template(ChildComponent)

.ref

.child-title Ref デモ
.ref-input-text {{ refText }}


script(ChildComponent)

import { Component, Vue, Prop } from "vue-property-decorator";

@Component({})
export default class RefComponent extends Vue {
@Prop() public refText: string;

public sampleText: string = "Refのデモです";

public updateRefText(newText: string) {
this.refText = newText;
}
}



親Component


template(ParentComponent)

.home

refComponent(ref="refDemo")
el-row
el-col(:span="10")
el-input(v-model="refInputText" @change="changeRefInputText")
el-col(:span="14")
.ref-demo-text {{ refDemoText }}


script(ParentComponent)

import { Component, Vue } from "vue-property-decorator";

import refComponent from "@/components/ref/Ref.vue";

@Component({
components: {
refComponent,
},
})
export default class Home extends Vue {
public refDemoText: string = "";

public mounted() {
const refDemoComponent: any = this.$refs.refDemo;
this.refDemoText = refDemoComponent.returnText();
}

public changeRefInputText() {
const refDemoComponent: any = this.$refs.refDemo;
refDemoComponent.updateRefText(this.refInputText);
}
}



さいごに

これからも「〇〇なときどう書いたっけな?」と困ることがあったら随時アップデートしていこうと思います!

ではまた!!