LoginSignup
9
7

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-01-07

はじめに

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);
  }
}

さいごに

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

9
7
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
9
7