Slide 1

Slide 1 text

Vue 3の導入を 急ピッチでやってみた

Slide 2

Slide 2 text

話す人 福田 雄貴(ふくだ ゆうき) ユアマイスター株式会社 テックリード Twitter: @hecateball

Slide 3

Slide 3 text

Vue 3って実際どうなの?

Slide 4

Slide 4 text

なぜVue 3を導入したのか

Slide 5

Slide 5 text

Vue 3: とにかく大量の機能アップデート ● Composition API ● Teleport ● 非同期コンポーネントと ● 複数のv-model ● ルートノードを複数持つコンポーネント ● filter廃止 ● TypeScriptのサポート ● script setup ● v-bind ● defineCustomElement

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Composition API ロジックとコンポーネント => 疎結合 ロジックと状態(データ) => 高凝集

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

Nuxt3 思ってたよりやんちゃなアップデートだった ...

Slide 10

Slide 10 text

所感 ● Vue 2とVue 3はぜんぜん違う ● VueとReact (Svelte, etc...)は本質的にはそんなに違わない ● Nuxt 3は変わり果てていて簡単に評価が出来ない

Slide 11

Slide 11 text

Vue 3の書き方

Slide 12

Slide 12 text

script setup

Slide 13

Slide 13 text

script setup import EmailInput from ‘~/EmailInput.vue’ import PasswordInput from ‘~/PasswordInput.vue’ import { useSignIn } from ‘~/composables/auth’ const { email, password, signIn } = useSignIn() サインイン .form { … } defineComponent()すら めんどくさい

Slide 14

Slide 14 text

IDEの対応も進んでいます VSCode + Volar WebStorm 2021.2.1

Slide 15

Slide 15 text

Component Tags Order

Slide 16

Slide 16 text

Component Tags Order import EmailInput from ‘~/EmailInput.vue’ import PasswordInput from ‘~/PasswordInput.vue’ import { useSignIn } from ‘~/composables/auth’ const { email, password, signIn } = useSignIn() サインイン .form { … } <template> <style>

Slide 17

Slide 17 text

Evan YouさんのTwitterより I’ve been moving to first in SFCs myself especially with <script setup>. It aligns better with plain JS mental model (imports & declarations first, usage next) Evan You [@youyuxi] (Aug 18th, 2021) “I’ve been moving to <script> first in SFCs myself especially with <script setup>. This tool seems to help you automate that switch :) https://twitter.com/KawamataRyo/status/1427835141833986048” Retreaved from https://twitter.com/youyuxi/status/1427982990957846529 Evan You [@youyuxi] (Aug 18th, 2021) “@reinink It aligns better with plain JS mental module (imports & declarations first, usage next)” Retreaved from https://twitter.com/youyuxi/status/1427985450598338568 Evan You [@youyuxi] (Aug 18th, 2021) “mental model*” Retreaved from https://twitter.com/youyuxi/status/1427985502704226305

Slide 18

Slide 18 text

Component Tags Order { "plugins": [ "vue" ], "rules": { "vue/component-tags-order": [ "error", { "order": [ "script", "template", "style" ] } ] } } <template> <style>

Slide 19

Slide 19 text

Composition API

Slide 20

Slide 20 text

Composition API (1) import { ref, readonly, onBeforeMount } from 'vue' export const useItems = () => { const items = ref([]) // データの操作を行う関数 const refresh = async () => { const response = await fetch('/api/items') items.value = await response.json() } // ライフサイクルフックもコンポーネント外へ! onBeforeMount(refresh) // データと操作をセットで返却 // データは読み取り専用にすることでより堅牢に return { items: readonly(items), refresh } } データとロジックを ひとまとまりにして Vueコンポーネントから分離

Slide 21

Slide 21 text

Composition API (1) import { reactive, toRefs, } from ‘vue’ export const useSignIn = (onSuccess, onError) => { const input = reactive({ email: ‘’, password: ‘’, }) const signIn = async () => { try { await signInWithEmail(input.email, input.password) onSuccess() } catch(error) { onError(error) } } return { ...toRefs(input), signIn } } データとロジックを ひとまとまりにして Vueコンポーネントから分離

Slide 22

Slide 22 text

Composition API (1) import EmailInput from ‘~/EmailInput.vue’ import PasswordInput from ‘~/PasswordInput.vue’ import { useSignIn } from ‘~/composables/auth’ import { useRouter } from ‘vue-router’ const router = useRouter() const { email, password, signIn } = useSignIn(() => { router.push({ name: ‘index’ }) }) サインイン データとロジックを ひとまとまりにして Vueコンポーネントから分離

Slide 23

Slide 23 text

Composition API (2) import { ref, inject, provide, readonly, Ref, InjectionKey } from ‘vue’ const Modal: InjectionKey> = Symbol() export const useModal = (injectionKey = Modal) => { const visible = inject(injectionKey, () => { const visible = ref(false) provide(injectionKey, visible) return visible }, true) const show = () => visible.value = true const dismiss = () => visible.value = false return { visible: readonly(visible), show, dismiss } } コンポーネントを跨ぐ状態管理

Slide 24

Slide 24 text

Composition API (2) import { createApp, ref, Plugin } from ‘vue’ const plugin: Plugin = (app) => { const loading = ref(false) app.provide(‘loading-indicator’, loading) } createApp(App).use(plugin).mount(‘#app’) コンポーネントを跨ぐ状態管理

Slide 25

Slide 25 text

チャレンジ中 コードの見通しの良さ重視 まだ破綻はしてない

Slide 26

Slide 26 text

エンジニア 積極採用中 https://speakerdeck.com/yourmystar/engineer