Slide 1

Slide 1 text

Deep Dive Into Vue Composition API v-kansai Vue.js/Nuxt.js meetup #10 @Daikids2

Slide 2

Slide 2 text

খౡ େج / Daiki Kojima @Daikids2 @jiko21 ژେӃ৘ใֶݚڀՊM2 (20ଔ) ΠϯϑϥҎ֎͍͍ͩͨͳΜͰ΋ Vue fes JPࢀՃ͠·͢!!

Slide 3

Slide 3 text

ͤΜͰΜ! • KFUG 2019Ͱొஃ͠·͢!

Slide 4

Slide 4 text

Posted on … IUUQCJUMZ*[E#-4

Slide 5

Slide 5 text

Today’s Topic • What is Composition API? • How to write… • ͪΐͬͱߴ౓ͳLogicͷ࠶ར༻

Slide 6

Slide 6 text

αϯϓϧίʔυ • GitHub: bit.ly/2Mgwy77 • Demo: bit.ly/2OmiuLQ

Slide 7

Slide 7 text

What is Composition API?

Slide 8

Slide 8 text

What is Composition API? • Vue 3Ͱొ৔༧ఆ?ͷAPI • چ໊: function-api https://github.com/vuejs/rfcs/pull/78

Slide 9

Slide 9 text

Motivation of Composition API • ϩδοΫ࠶ར༻ͨ͠Γίʔυͷߏ੒·ΘΓ • ࠓͷAPIͩͱoption࢖ͬͯ΍Δ͔Βηϯε͕ཁΔ • ܕਪ࿦ • thisʹґଘͯͯ͠ܕ͕ͭΒ͍ • IDEͱ͔ͷॿ͚͕ಘΒΕʹ͍͘… https://vue-composition-api-rfc.netlify.com/#motivation

Slide 10

Slide 10 text

Μ?

Slide 11

Slide 11 text

ܕपΓͳΒ

Slide 12

Slide 12 text

Class Style API͕
 ͋Δ͡ΌΜ?

Slide 13

Slide 13 text

Vue3ʹ͸࠾༻͞Ε·ͤΜ… https://github.com/vuejs/rfcs/pull/17#issuecomment-494242121

Slide 14

Slide 14 text

Why Class Style API is dropped? • Vueࣗମɺ৭Μͳ΋ͷΛthisʹͻͬ͘ΔΊͯΔ… • propsΛѻ͏ࡍʹσίϨʔλΛ࢖͏ඞཁ͕͋Γɺ
 ෆ࣮֬ੑ͕ଟ͍(TC39ͱͷ݉Ͷ߹͍) • TSXαϙʔτͱ߹Θͳ͍… https://vue-composition-api-rfc.netlify.com/#motivation

Slide 15

Slide 15 text

How to write…

Slide 16

Slide 16 text

४උ • ҎԼͷίϚϯυͰύοέʔδΛΠϯετʔϧ
 • main.ts(js)ʹҎԼͷΑ͏ʹॻ͚͹OK npm install @vue/composition-api --save import Vue from "vue"; import VueCompositionApi from '@vue/composition-api'; Vue.use(VueCompositionApi);

Slide 17

Slide 17 text

ྫ͑͹… • ୯७ͳTodoΞϓϦΛ
 ߟ͑Δ • Root Component Todo.vue

Slide 18

Slide 18 text

ྫ͑͹… • Todo௥Ճ༻ͷϑΥʔϜ TodoForm.vue

Slide 19

Slide 19 text

ྫ͑͹… • Todoදࣔ༻ͷ
 List TodoList.vue

Slide 20

Slide 20 text

TodoForm.vueΛݟͯΈΔ
Add

Slide 21

Slide 21 text

ྫ͑͹… • ϑπʔʹॻ͘ͱ
 ͜Μͳ͔Μ͡? import Vue, {PropType} from 'vue'; export default Vue.extend({ name: 'TodoForm', props: { onSubmit: { type: Function as PropType<(text: string) => void>, required: true, }, }, data() { return { text: '', }; }, computed: { isValid(): boolean { return this.text.length > 0; }, }, methods: { submit() { this.onSubmit(this.text); this.text = ''; }, }, });

Slide 22

Slide 22 text

ྫ͑͹… • ͜͏ͳΔ import {computed, createComponent, PropType, reactive} from '@vue/composition-api'; const TodoForm = createComponent({ props: { onSubmit: { type: Object as PropType<(text: string) => void>, required: true, }, }, setup(props) { const state = reactive({ text: '', }); const isValid = computed( () => state.text.length > 0 ); const submit = () => { props.onSubmit(state.text); state.text = ''; }; return { state, submit, isValid }; } });

Slide 23

Slide 23 text

ίϯϙʔωϯτͷ࡞Γํ • createComponentͰίϯϙʔωϯτΛ࡞੒
 (jsͰॻ͘ͳΒexport default {}ͰOK) import {createComponent, PropType, reactive} from '@vue/composition-api'; const TodoForm = createComponent({ ... });

Slide 24

Slide 24 text

ίϯϙʔωϯτͷ࡞Γํ • props͸͍ͭ΋ͷΑ͏ʹॻ͚·͢… import {createComponent, PropType, reactive} from '@vue/composition-api'; const TodoForm = createComponent({ props: { onSubmit: { type: Object as PropType<(text: string) => void>, required: true, }, }, });

Slide 25

Slide 25 text

ίϯϙʔωϯτͷ࡞Γํ • setupؔ਺಺ʹ৭ʑॻ͍͍ͯ͘… • reactive: Vue.observableͷ͜ͱ
 dataͷΑ͏ʹ࢖͏͜ͱ͕ଟ͍͔΋ • computed: ؔ਺ͷΑ͏ʹॻ͘ setup(props) { const state = reactive({ text: '', }); const isValid = computed( () => state.text.length > 0 ); ...

Slide 26

Slide 26 text

ίϯϙʔωϯτͷ࡞Γํ • setupؔ਺಺ʹ৭ʑॻ͍͍ͯ͘… • methods: ؔ਺Λͦͷ··ఆٛ • props͸props.Ͱ࢖͏ • ࠷ޙʹreturnͰఆٛͨ͠΋ͷΛ
 ฦ͢ setup(props) { ... const submit = () => { props.onSubmit(state.text); state.text = ''; }; return { state, submit, isValid }; } });

Slide 27

Slide 27 text

σϞ

Slide 28

Slide 28 text

ͪΐͬͱߴ౓ͳLogicͷ࠶ར༻

Slide 29

Slide 29 text

Logic Extraction and Reuse • ίϯϙʔωϯτͷछྨ͸ҧ͑Ͳɺڞ௨ͯ͠࢖͍͍ͨ
 ϩδοΫΛநग़ͯ͠࠶ར༻Ͱ͖Δɻ • ݱߦͷmixinͳͲͱಉ͡Α͏ͳ͜ͱ͕Ͱ͖Δ… https://vue-composition-api-rfc.netlify.com/#logic-extraction-and-reuse

Slide 30

Slide 30 text

HOW TO • Component͔Βɺ
 Stateͱɺmethods͚ͩΛ
 Ҿ͖ണ͕ͯؔ͠਺Ͱฦ͢ • ref: reactiveͰՄม(mutable)ͳ
 data import {reactive, ref} from "@vue/composition- api"; const useTodos = () => { const todos = ref([] as string[]); const addTodo = (todo: string) => { todos.value.push(todo); }; const deleteTodo = (position: number) => { todos.value.splice(position, 1); }; return { todos, addTodo, deleteTodo, }; }; export default useTodos;

Slide 31

Slide 31 text

HOW TO • ࢖͍͍ͨComponent಺Ͱ
 ӈهͷΑ͏ʹ࢖༻͢Δ import {createComponent, reactive} from '@vue/ composition-api'; import TodoList from '@/components/normal/TodoList.vue'; import TodoForm from '@/components/normal/TodoForm.vue'; import useTodos from './Store'; const Todo = createComponent({ components: { TodoList, TodoForm, }, setup() { const {todos, deleteTodo, addTodo} = useTodos(); return { todos, deleteTodo, addTodo, }; }, });

Slide 32

Slide 32 text

σϞ

Slide 33

Slide 33 text

ΑΓߴ౓ͳ͜ͱ…

Slide 34

Slide 34 text

࣮͸ɺ • ͜ͷComposition APIΛ
 ࢖͍͜ͳͤ͹
 ͳΜͪΌͬͯঢ়ଶ؅ཧ͕
 Ͱ͖·͢ ͍ͭ͜Έ͍ͨͳ΍ͭͰ͢ https://vuex.vuejs.org/ja/ ʹ͋ΔVu○xͷֆ

Slide 35

Slide 35 text

Ͳ͏΍Δͷ? • todosΛؔ਺ͷ֎ʹग़͢
 -> 1ճ͚ͩੜ੒͞ΕΔ! import {reactive, ref} from "@vue/composition-api"; const todos = ref([] as string[]); const useTodos = () => { const addTodo = (todo: string) => { todos.value.push(todo); }; const deleteTodo = (position: number) => { todos.value.splice(position, 1); }; return { todos, addTodo, deleteTodo, }; }; export default useTodos;

Slide 36

Slide 36 text

σϞ

Slide 37

Slide 37 text

·ͱΊ • Composition API͸ܕਪ࿦ͳͲͷվળΛਤͬͨ
 ͜Ε·Ͱͱ͸Ұຯҧ͏ΦτφͷVue.js • ϩδοΫͷ࠶ར༻͕Ͱ͖ɺͳΜͪΌͬͯঢ়ଶ؅ཧ΋
 Ͱ͖ͪΌ͏!! • ϓϩμΫτʹ࢖͏ͷ͸(·ͩ)࣌ظঘૣ?

Slide 38

Slide 38 text

Reference? • Vue-function-api rfc
 https://vue-composition-api-rfc.netlify.com • API Document
 https://vue-composition-api-rfc.netlify.com/api.html • GitHub
 https://github.com/vuejs/composition-api