Open9

💚 Vue の Options API を Composition API に書き換える

torish14torish14

data

Options API

<template>
  <div>{{ count }}</div>
</template>

<script>
export default {
  data() {
    return {
      count: 1
    }
  }
}
</script>

Options API with TypeScript

<template>
  <div>{{ count }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  data() {
    return {
      count: 1
    }
  }
})
</script>

Composition API

<template>
  <div>{{ countRef }}</div>
  <div>{{ obj.count }}</div>
</template>

<script>
import { ref, reactive } from 'vue'

export default {
  setup() {
    // ref または reactive を使用して
    // リアクティブな変数を生成する
    const countRef = ref(1)
    const obj = reactive({
      count: 1
    })

    return {
      countRef,
      obj
    }
  }
}
</script>

Composition API with TypeScript

<template>
  <div>{{ countRef }}</div>
  <div>{{ obj.count }}</div>
</template>

<script lang="ts">
import { defineComponent, ref, reactive } from 'vue'

export default defineComponent({
  setup() {
    // ref または reactive を使用して
    // リアクティブな変数を生成する
    const countRef = ref(1)
    const obj = reactive({
      count: 1
    })

    return {
      countRef,
      obj
    }
  }
})
</script>

Composition API with setup and TypeScript

<template>
  <div>{{ countRef }}</div>
  <div>{{ obj.count }}</div>
</template>

<script setup lang="ts">
import { defineComponent, ref, reactive } from 'vue'

export default defineComponent({
  // ref または reactive を使用して
  // リアクティブな変数を生成する
  const countRef = ref(1)
  const obj = reactive({
    count: 1
  })
})
</script>
torish14torish14

methods

Options API

<template>
  <div>
    <button @click="decrement">-</button>
    {{ count }}
    <button @click="increment">+</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 1
    }
  },

  methods: {
    increment() {
      this.count++
    },
    decrement() {
      this.count--
    }
  }
}
</script>

Options API with TypeScript

<template>
  <div>
    <button @click="decrement">-</button>
    {{ count }}
    <button @click="increment">+</button>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  data() {
    return {
      count: 1
    }
  },

  methods: {
    increment() {
      this.count++
    },
    decrement() {
      this.count--
    }
  }
})
</script>

Composition API

<template>
  <!-- template 内での使い方は Options API と同じ -->
  <button @click="decrement">-</button>
  {{ countRef }}
  <!-- template 内での使い方は Options API と同じ -->
  <button @click="increment">+</button>
</template>

<script>
import { ref } from 'vue'

export default {
  setup() {
    const countRef = ref(0)
    // 通常の関数と同じように定義する
    const decrement = () => {
      countRef.value--
    }
    // 通常の関数と同じように定義する
    const increment = () => {
      countRef.value++
    }

    return {
      countRef,
      decrement,
      increment
    }
  }
}
</script>

Composition API with TypeScript

<template>
  <!-- template 内での使い方は Options API と同じ -->
  <button @click="decrement">-</button>
  {{ countRef }}
  <!-- template 内での使い方は Options API と同じ -->
  <button @click="increment">+</button>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const countRef = ref(0)
    // 通常の関数と同じように定義する
    const decrement = () => {
      countRef.value--
    }
    // 通常の関数と同じように定義する
    const increment = () => {
      countRef.value++
    }

    return {
      countRef,
      decrement,
      increment
    }
  }
})
</script>

Composition API with setup and TypeScript

<template>
  <!-- template 内での使い方は Options API と同じ -->
  <button @click="decrement">-</button>
  {{ countRef }}
  <!-- template 内での使い方は Options API と同じ -->
  <button @click="increment">+</button>
</template>

<script setup lang="ts">
import { defineComponent, ref } from 'vue'

export default defineComponent({
  const countRef = ref(0)
  // 通常の関数と同じように定義する
  const decrement = () => {
    countRef.value--
  }
  // 通常の関数と同じように定義する
  const increment = () => {
    countRef.value++
  }
})
</script>
torish14torish14

computed

Options API

<template>
  <div>
    {{ count }}
    <div>2倍すると: {{ doubleCount }}</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 1
    }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    }
  }
}
</script>

Options API with TypeScript

<template>
  <div>
    {{ count }}
    <div>2倍すると: {{ doubleCount }}</div>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  data() {
    return {
      count: 1
    }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    }
  }
})
</script>

Composition API

<template>
  {{ countRef }}
  <div>2倍すると: {{ doubleCount }}</div>
</template>

<script>
import { ref, computed } from 'vue'

export default {
  setup() {
    const countRef = ref(1)
    // computed 関数を使用して計算プロパティを定義する
    const doubleCount = computed(() => {
      return countRef.value * 2
    })

    return {
      countRef,
      doubleCount
    }
  }
}
</script>

Composition API with TypeScript

<template>
  {{ countRef }}
  <div>2倍すると: {{ doubleCount }}</div>
</template>

<script lang="ts">
import { defineComponent, ref, computed } from 'vue'

export default defineComponent({
  setup() {
    const countRef = ref(1)
    // computed 関数を使用して計算プロパティを定義する
    const doubleCount = computed(() => {
      return countRef.value * 2
    })

    return {
      countRef,
      doubleCount
    }
  }
})
</script>

Composition API with setup and TypeScript

<template>
  {{ countRef }}
  <div>2倍すると: {{ doubleCount }}</div>
</template>

<script setup lang="ts">
import { defineComponent, ref, computed } from 'vue'

export default defineComponent({
  const countRef = ref(1)
  // computed 関数を使用して計算プロパティを定義する
  const doubleCount = computed(() => {
    return countRef.value * 2
  })
})
</script>
torish14torish14

props, emit

Options API

Parent.vue
<template>
  <div>
    <ChildComponent :count.sync="count" />
  </div>
</template>

<script>
import ChildComponent from '@/components/ChildComponent'

export default {
  components: {
    ChildComponent
  },

  data() {
    return {
      count: 1
    }
  }
}
</script>
Child.vue
<template>
  <div>
    {{ count }}
    <button @click="increment">+</button>
    <div>2倍すると: {{ doubleCount }}</div>
  </div>
</template>

<script>
export default {
  props: {
    count: {
      type: Number,
      required: true
    }
  },

  computed: {
    doubleCount() {
      return this.count * 2
    }
  },

  methods: {
    increment() {
      this.$emit('update:count', this.count + 1)
    }
  }
}
</script>

Options API with TypeScript

Parent.vue
<template>
  <div>
    <ChildComponent :count.sync="count" />
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue'
import ChildComponent from '@/components/ChildComponent'

export default defineComponent({
  components: {
    ChildComponent
  },

  data() {
    return {
      count: 1
    }
  }
})
</script>
Child.vue
<template>
  <div>
    {{ count }}
    <button @click="increment">+</button>
    <div>2倍すると: {{ doubleCount }}</div>
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue'

export default defineComponent({
  props: {
    count: {
      type: Number,
      required: true
    }
  },

  computed: {
    doubleCount() {
      return this.count * 2
    }
  },

  methods: {
    increment() {
      this.$emit('update:count', this.count + 1)
    }
  }
})
</script>

Composition API

Parent.vue
<template>
  <ChildComponent v-model:count="countRef" />
</template>

<script>
import { ref } from 'vue'
import ChildComponent from '@/components/ChildComponent'

export default {
  components: {
    ChildComponent
  },

  setup() {
    const countRef = ref(1)

    return {
      countRef
    }
  }
}
</script>
Child.vue
<template>
  {{ count }}
  <button @click="increment">+</button>
  <div>2倍すると: {{ doubleCount }}</div>
</template>

<script>
import { computed } from 'vue'

export default {
  props: {
    count: {
      type: Number,
      required: true
    }
  },

  setup(props, context) {
    // props に親コンポーネントから渡されたデータが格納される
    const doubleCount = computed(() => {
      return props.count * 2
    })

    const increment = () => {
      // contextにemitが用意されています
      context.emit('update:count', props.count + 1)
    }

    return {
      increment,
      doubleCount
    }
  }
}
</script>

Composition API with TypeScript

Parent.vue
<template>
  <ChildComponent v-model:count="countRef" />
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
import ChildComponent from '@/components/ChildComponent'

export default defineComponent({
  components: {
    ChildComponent
  },

  setup() {
    const countRef = ref(1)

    return {
      countRef
    }
  }
})
</script>
Child.vue
<template>
  {{ count }}
  <button @click="increment">+</button>
  <div>2倍すると: {{ doubleCount }}</div>
</template>

<script lang="ts">
import { defineComponent, computed } from 'vue'

export default defineComponent({
  props: {
    count: {
      type: Number,
      required: true
    }
  },

  setup(props, context) {
    // props に親コンポーネントから渡されたデータが格納される
    const doubleCount = computed(() => {
      return props.count * 2
    })

    const increment = () => {
      // contextにemitが用意されています
      context.emit('update:count', props.count + 1)
    }

    return {
      increment,
      doubleCount
    }
  }
})
</script>

参考サイト

2022年の最新標準!Vue 3の新しい開発体験に触れよう
【Vue.js 3.2】<script setup> 構文がすごくすごい

torish14torish14

watch

Options API

<template>
  <div>
    {{ count }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 1
    }
  },

  watch: {
    count(count, prevCount) {
      console.log(count)
      console.log(prevCount)
    }
  }
}
</script>

Options API with TypeScript

<template>
  <div>
    {{ count }}
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  data() {
    return {
      count: 1
    }
  },

  watch: {
    count(count, prevCount) {
      console.log(count)
      console.log(prevCount)
    }
  }
})
</script>

Composition API

<template>
  {{ countRef }}
</template>

<script>
import { ref, watch } from 'vue'

export default {
  setup() {
    const countRef = ref(1)

    // watch 関数でリアクティブな変数を監視する
    watch(countRef, (count, prevCount) => {
      console.log(count)
      console.log(prevCount)
    })

    return {
      countRef
    }
  }
}
</script>

Composition API with TypeScript

<template>
  {{ countRef }}
</template>

<script lang="ts">
import { defineComponent, ref, watch } from 'vue'

export default defineComponent({
  setup() {
    const countRef = ref(1)

    // watch 関数でリアクティブな変数を監視する
    watch(countRef, (count, prevCount) => {
      console.log(count)
      console.log(prevCount)
    })

    return {
      countRef
    }
  }
})
</script>

Composition API with setup and TypeScript

<template>
  {{ countRef }}
</template>

<script setup lang="ts">
import { defineComponent, ref, watch } from 'vue'

export default defineComponent({
  const countRef = ref(1)
  // watch 関数でリアクティブな変数を監視する
  watch(countRef, (count, prevCount) => {
    console.log(count)
    console.log(prevCount)
  })
})
</script>
torish14torish14

refs

Options API

<template>
  <div ref="root"></div>
</template>

<script>
export default {
  mounted() {
    console.log(this.$refs.root)
  }
}
</script>

Options API with TypeScript

<template>
  <div ref="root"></div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  mounted() {
    console.log(this.$refs.root)
  }
})
</script>

Composition API

<template>
  <div ref="root"></div>
</template>

<script>
import { ref, onMounted } from 'vue'

export default {
  setup() {
    const root = ref(null)

    onMounted(() => {
      console.log(root.value)
    })

    return {
      root
    }
  }
}
</script>

Composition API with TypeScript

<template>
  <div ref="root"></div>
</template>

<script lang="ts">
import { defineComponent, ref, onMounted } from 'vue'

export default defineComponent{
  setup() {
    const root = ref(null)

    onMounted(() => {
      console.log(root.value)
    })

    return {
      root
    }
  }
})
</script>

Composition API with setup and TypeScript

<template>
  <div ref="root"></div>
</template>

<script setup lang="ts">
import { defineComponent, ref, onMounted } from 'vue'

export default defineComponent{
  const root = ref(null)

  onMounted(() => {
    console.log(root.value)
  })
})
</script>
torish14torish14

ライフサイクルフック

Options API

<template>
  <div></div>
</template>

<script>
export default {
  created() {
    console.log('created')
  },

  mounted() {
    console.log('mounted')
  }
}
</script>

Options API with TypeScript

<template>
  <div></div>
</template>

<script lang="ts">
import { defineComponent }

export default defineComponent({
  created() {
    console.log('created')
  },

  mounted() {
    console.log('mounted')
  }
})
</script>

Composition API

<template>
  <div></div>
</template>

<script>
import { onMounted } from 'vue'

export default {
  setup() {
    console.log('created')

    onMounted(() => {
      console.log('mounted')
    })
  }
}
</script>

Composition API with TypeScript

<template>
  <div></div>
</template>

<script lang="ts">
import { defineComponent, onMounted } from 'vue'

export default defineComponent({
  setup() {
    console.log('created')

    onMounted(() => {
      console.log('mounted')
    })
  }
})
</script>

Composition API with setup and TypeScript

<template>
  <div></div>
</template>

<script setup lang="ts">
import { defineComponent, onMounted } from 'vue'

export default defineComponent({
  console.log('created')

  onMounted(() => {
    console.log('mounted')
  })
})
</script>
torish14torish14

ライフサイクル 対応表

Options API Composition API
beforeCreate setup
created setup
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
update onUpdate
beforeDestroy onBeforeUnmount
destroyed onUnmounted
activated onActivated
deactivated onDeactivated
errorCaptured onErrorCaptured