Code Example 1: Options API vs Composition API — базовый счётчик
❓ Чем отличаются эти два варианта реализации счётчика? Какой подход использует Options API, а какой — Composition API?
Options API:
<template>
<p>{{ count }}</p>
<button @click="increment">+1</button>
</template>
<script>
export default {
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
}
}
}
</script>
Composition API:
<template>
<p>{{ count }}</p>
<button @click="increment">+1</button>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
Code Example 2: Компонент с поиском и фильтрацией
❓ Что делает этот компонент? Какие возможности Composition API здесь используются для работы с данными и вычислениями?
<template>
<div>
<input v-model="searchQuery" placeholder="Поиск..." />
<ul>
<li v-for="item in filteredItems" :key="item.id">
{{ item.name }}
</li>
</ul>
<p>Найдено: {{ itemCount }}</p>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const searchQuery = ref('')
const items = ref([
{ id: 1, name: 'Vue.js' },
{ id: 2, name: 'React' },
{ id: 3, name: 'Angular' }
])
const filteredItems = computed(() => {
const query = searchQuery.value.toLowerCase()
return items.value.filter(item =>
item.name.toLowerCase().includes(query)
)
})
const itemCount = computed(() => filteredItems.value.length)
</script>
Code Example 3: Организация кода по фичам
❓ Как организован код в Options API и в Composition API? Какой подход лучше масштабируется при росте компонента и почему?
Options API:
<script>
export default {
data() {
return {
searchQuery: '',
currentPage: 1,
sortField: 'name'
}
},
computed: {
filteredItems() { /* ... */ },
paginatedItems() { /* ... */ },
sortedItems() { /* ... */ }
},
methods: {
search() { /* ... */ },
goToPage() { /* ... */ },
sortBy() { /* ... */ }
}
}
</script>
Composition API:
<script setup>
import { ref, computed } from 'vue'
// === Поиск ===
const searchQuery = ref('')
const filteredItems = computed(() => { /* ... */ })
function search() { /* ... */ }
// === Пагинация ===
const currentPage = ref(1)
const paginatedItems = computed(() => { /* ... */ })
function goToPage(page) { /* ... */ }
// === Сортировка ===
const sortField = ref('name')
const sortedItems = computed(() => { /* ... */ })
function sortBy(field) { /* ... */ }
</script>
Code Example 4: Composable-функция и её использование
❓ Что такое composable? Что делает функция useCounter и как она используется в компоненте?
// composables/useCounter.js
import { ref, computed } from 'vue'
export function useCounter(initialValue = 0) {
const count = ref(initialValue)
const doubled = computed(() => count.value * 2)
function increment() {
count.value++
}
function decrement() {
count.value--
}
return {
count,
doubled,
increment,
decrement
}
}
Использование в компоненте:
<template>
<p>Счётчик: {{ count }}</p>
<p>Удвоенный: {{ doubled }}</p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</template>
<script setup>
import { useCounter } from '@/composables/useCounter'
const { count, doubled, increment, decrement } = useCounter(10)
</script>
Code Example 5: Доступ к данным в script setup
❓ Как в этом коде работает обновление счётчика? Какие два варианта обращения к count показаны (Version A и Version B) и какой из них правильный?
Version A:
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
this.count++
}
</script>
Version B:
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
Code Example 6: Автодоступность в шаблоне
❓ Что из объявленного в <script setup> доступно в <template>? Нужно ли явно возвращать что-то из setup?
<script setup>
import { ref } from 'vue'
import MyComponent from './MyComponent.vue'
const message = ref('Привет')
function greet() {
alert(message.value)
}
</script>
<template>
<MyComponent />
<p>{{ message }}</p>
<button @click="greet">Приветствие</button>
</template>