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ツリーを再現したらアプリのあらゆる状態が再現できる」が満たせなくなる。