Poznajemy, czym jest ten „script setup” w Vue.js. Czytamy dokumentację i oglądamy inne przykłady (z Laravel Breeze). Do dzieła.

Ok, przypomnijmy sobie skrypt naszego pierwszego komponentu:

 <script>
  export default {
    name: 'FirstComponent',
    props: {
      msg: String
    }
  }
  </script>

Mamy tutaj nazwę i propsy. A jak to wygląda w script setup?

<script setup>
import { computed, onMounted, onUnmounted, watch } from 'vue';

const props = defineProps({
    show: {
        type: Boolean,
        default: false,
    },
    maxWidth: {
        type: String,
        default: '2xl',
    },
    closeable: {
        type: Boolean,
        default: true,
    },
});

//(...)

</script>

Ok, powoli. Po pierwsze, jak widać, nie mamy jak nazwy komponentu określić. Tutaj pomoże nam Breeze, przeszukajmy projekt, gdzie jest ten modal:

import Modal from '@/Components/Modal.vue';
//(...)
<Modal :show="confirmingUserDeletion" @close="closeModal">

Znalazł się w deleteUserForm.vue w partials. Ok, tak importujemy i używamy, spoko.

Poczytajmy trochę w dokumentacji Vue o tym. Po pierwsze – top-level bindings exposed to template:

<script setup>
// variable
const msg = 'Hello!'

// functions
function log() {
  console.log(msg)
}
</script>

<template>
  <button @click="log">{{ msg }}</button>
</template>

No tak się robi data i methods w scripts setup, choć to msg to nie jest reaktywna zmienna.

Ok, co dalej – importy również są obecne w templatce:

<script setup>
import { capitalize } from './helpers'
</script>

<template>
  <div>{{ capitalize('hello') }}</div>
</template>

Ok, widzieliśmy metodę, stałą oraz import, a jak zrobić reaktywną zmienną (jak w data „po staremu” albo odpowiednik useState z Reacta)?

Używamy ref:

<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <button @click="count++">{{ count }}</button>
</template>

Używanie komponentów już znamy, ale co nam szkodzi przypomnieć:

<script setup>
import MyComponent from './MyComponent.vue'
</script>

<template>
  <MyComponent />
</template>

Mamy też coś takiego jak dynamiczne komponenty:

<script setup>
import Foo from './Foo.vue'
import Bar from './Bar.vue'
</script>

<template>
  <component :is="Foo" />
  <component :is="someCondition ? Foo : Bar" />
</template>

Pierwszy przykład jest nieco bez sensu i zaprzecza używaniu dynamicznych komponentów (zamiast component powinno być <Foo/> skoro i tak zawsze będzie Foo), drugi zaś pokazuje o co chodzi – warunek i albo jeden albo drugi za pomocą :is.

Własne v-dyrektywy to raczej nie jest coś, co będziemy prędko robić:

<script setup>
const vMyDirective = {
  beforeMount: (el) => {
    // do something with the element
  }
}
</script>
<template>
  <h1 v-my-directive>This is a Heading</h1>
</template>

Ale warto wiedzieć, że to istnieje. Z drugiej strony – defineProps i defineEmits będziemy używać i to ostro:

<script setup>
const props = defineProps({
  foo: String
})

const emit = defineEmits(['change', 'delete'])
// setup code
</script>

Na razie będziemy się bawili głównie scripts export default, bez setup, ale miejmy świadomość, że najnowszy kod Vue pisze się w ten sposób i jak tylko ogarniemy podstawy będziemy przeskakiwać na to podejście.