Code Example 1: setup() функция vs script setup
❓ Чем отличаются эти два подхода? Какие преимущества даёт <script setup>?
setup():
<template>
<p>{{ message }}</p>
<button @click="greet">Привет</button>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const message = ref('Привет, Vue!')
function greet() {
alert(message.value)
}
return {
message,
greet
}
}
}
</script>
script setup:
<template>
<p>{{ message }}</p>
<button @click="greet">Привет</button>
</template>
<script setup>
import { ref } from 'vue'
const message = ref('Привет, Vue!')
function greet() {
alert(message.value)
}
</script>
Code Example 2: Регистрация компонентов
❓ Как отличается регистрация компонентов в <script setup> и в setup()? Что нужно сделать дополнительно во втором варианте?
Вариант A — script setup:
<template>
<MyButton @click="handleClick">
Нажми
</MyButton>
</template>
<script setup>
import MyButton from './MyButton.vue'
function handleClick() {
console.log('Клик!')
}
</script>
Вариант B — setup():
<template>
<MyButton @click="handleClick">
Нажми
</MyButton>
</template>
<script>
import MyButton from './MyButton.vue'
export default {
components: {
MyButton
},
setup() {
function handleClick() {
console.log('Клик!')
}
return { handleClick }
}
}
</script>
Code Example 3: Работа с props
❓ Как объявляются props в <script setup>? Нужно ли импортировать defineProps?
<template>
<p>{{ title }} - {{ count }}</p>
</template>
<script setup>
const props = defineProps({
title: {
type: String,
required: true
},
count: {
type: Number,
default: 0
}
})
console.log(props.title)
</script>
Code Example 4: Эмиты событий
❓ Как объявляются emit-события в <script setup>? Как вызвать событие?
<template>
<button @click="handleClick">Отправить</button>
</template>
<script setup>
const emit = defineEmits(['submit', 'cancel'])
function handleClick() {
emit('submit', { data: 'payload' })
}
</script>
Code Example 5: TypeScript с props и emits
❓ Как типизировать props и emits в <script setup> с TypeScript? Что делает withDefaults?
<script setup lang="ts">
interface Props {
title: string
count?: number
}
const props = withDefaults(defineProps<Props>(), {
count: 0
})
const emit = defineEmits<{
(e: 'submit', value: string): void
(e: 'cancel'): void
}>()
</script>
Code Example 6: Аргументы setup() vs макросы script setup
❓ Какие аргументы принимает setup() и какие макросы заменяют их в <script setup>?
setup():
<script>
export default {
props: {
title: String
},
emits: ['update'],
setup(props, context) {
console.log(props.title)
const { attrs, slots, emit, expose } = context
emit('update', 'новое значение')
return {}
}
}
</script>
script setup:
<script setup>
import { useAttrs, useSlots } from 'vue'
const props = defineProps(['title'])
const emit = defineEmits(['update'])
const attrs = useAttrs()
const slots = useSlots()
</script>
Code Example 7: defineExpose
❓ Зачем нужен defineExpose? Что произойдёт, если не вызвать его в <script setup>?
Дочерний компонент:
<script setup>
import { ref } from 'vue'
const count = ref(0)
const publicMethod = () => console.log('Публичный метод')
const privateMethod = () => console.log('Приватный метод')
defineExpose({
count,
publicMethod
})
</script>
Родительский компонент:
<template>
<ChildComponent ref="childRef" />
</template>
<script setup>
import { ref, onMounted } from 'vue'
import ChildComponent from './ChildComponent.vue'
const childRef = ref(null)
onMounted(() => {
console.log(childRef.value.count)
childRef.value.publicMethod()
})
</script>
Code Example 8: Двойной script блок
❓ Зачем может понадобиться обычный <script> рядом с <script setup>? Какие опции нельзя указать в <script setup>?
<script>
export default {
name: 'MyCustomComponent',
inheritAttrs: false
}
</script>
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
Code Example 9: Ошибки при использовании макросов
❓ Почему нельзя импортировать defineProps и defineEmits? Что это за конструкции?
<script setup>
const props = defineProps(['title'])
const emit = defineEmits(['click'])
</script>