LoginSignup
3
4

More than 3 years have passed since last update.

Vue.js地雷集(Tips)

Last updated at Posted at 2019-08-06

vue-propety-decorator & typescriptで二重にtype定義しなくてよくね?

vue, vue-propety-decorator, vue-class-component, class-api, typescript

export default class MyChildComponent extends Vue {
  @Prop({ type: number/* ←これ */ }) hogeId!: number /* ←とこれ */

export default class MyChildComponent extends Vue {
  @Prop hogeId!: number // これでええやんけ

A: ダメ。死にます。二重なのを我慢して必ず両方に定義しましょう

vueの親テンプレート上から、typescriptの型をガン無視したものを入れれちゃう

MyParentComponent.vue
<template>
    <my-child-component hogeId="abcd" />
</template>

エラー無しで通る。
まじかよ。

初期値undefinedのdataが動かない

vue, vue-propety-decorator, vue-class-component, class-api, typescript

<template>
  <div>{{post.content}}</div>
</template>

<script lang="ts">
export default class extends Vue {
  post!: Post

  created () {
    this.post = { content: "postContent" }
  }

  changePostContent() {
    this.post.content = `${this.post.content}+`
  }
}
</script>
  • 初期値は画面に出ているみたい
  • changePostContentをしても画面に反映されない
  • devtoolでみてもpostがdataとして扱われていない

A. 仕様っぽい nullを利用しよう

undefinedはだめだけどnullはいける。

export default class extends Vue {
-  post!: Post
+  post: Post | null = null

  created () {
    this.post = { content: "postContent" }
  }

  changePostContent() {
-    this.post.content = `${this.post.content}+`
+    this.post!.content = `${this.post!.content}+`
  }
}
  • nullだと暗黙unwrap構文が使えないので、各所でforced-unwrapする必要がある
  • created(すくなくともbeforeMount)までに初期化しないと死ぬ

vuex使いたくないがprop-callback地獄にもなりたくない

vue

PostPage.vue
<template>
  <post :post="post" />
</template>

<script lang="ts">
import PostComponent from './Post.vue'

@Component({
  components: { post: PostComponent }
})
export default class extends Vue {
  post: Post | null = null

  created () {
    this.post = { content: "postContent" }
  }
}
</script>
Post.vue
<template>
  <div>
    <p>{{ post.content }}</p>
    <button @click="changePostContent">changePostContent</button>
  </div>
</template>

<script lang="ts">
import { Prop, Vue, Component } from "vue-property-decorator";
import { Post } from "~/src/Post";
import { PropType } from "vue";

@Component
export default class PostComponent extends Vue {
  @Prop({ type: Object as PropType<Post> }) post!: Post;

  changePostContent() {
    // 本来propを書き換えてもreactiveにはならないが、これはちゃんと画面に反映される
    // 親の方のdataで監視しているオブジェクトの中身を変更しているので
    // 親でdataの変更→propの更新→このComponentのPropの再セットが起こる(ということだと思う)
    this.post.content = `${this.post.content}+`;
  }
}
</script>

以下のようにすればvuexを使わずともprop-callback地獄にならない。
静的なものではなくて、ライフサイクルがある親コンポーネントと一致しているstate-storeは、こっちのほうがいいとおもう。
誰がそのstateを更新するかわからないのはvuexも同じだし。更新手続きをカプセル化してるのもvuexと同じ。
デメリットとして、redux的な思想の「storeツリーを再現したらアプリのあらゆる状態が再現できる」が満たせなくなる。

3
4
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
3
4