Jako PHP developer pewnie masz za sobą kontakt z jQuery i może trochę czystego JS. Vue.js to kolejny krok – reaktywny framework, który coraz częściej pojawia się w projektach e-commerce jako warstwa frontendowa przy headless Magento lub jako zamiennik starszego knockout.js. Pokazuję podstawy z perspektywy kogoś, kto na co dzień myśli w PHP.
Dlaczego Vue, a nie React czy Angular?
React wymaga myślenia w JSX i ma bardziej stromą krzywą uczenia się. Angular to pełny framework z rozbudowaną architekturą – overkill do małych komponentów. Vue zajmuje środek: prosta składnia szablonów bliska HTML, reaktywność wbudowana bez ceremonii, dokumentacja w języku polskim. Dla PHP developera, który nie jest frontendowcem z wyboru, Vue jest najłagodniejszym wejściem w świat komponentów.
W ekosystemie Magento Vue pojawia się w Vue Storefront – najpopularniejszym headless frontend dla Magento 2.
Podstawowa struktura komponentu Vue 3
// Komponent Vue 3 - Options API (prostszy dla przybyszów z PHP)
const ProductCard = {
// Dane komponentu - odpowiednik właściwości klasy PHP
data() {
return {
quantity: 1,
addedToCart: false,
};
},
// Właściwości przekazywane z zewnątrz - odpowiednik parametrów metody
props: {
product: {
type: Object,
required: true,
},
maxQuantity: {
type: Number,
default: 99,
},
},
// Obliczone właściwości - odpowiednik getterów w PHP
computed: {
totalPrice() {
return (this.product.price * this.quantity).toFixed(2);
},
canAddMore() {
return this.quantity < this.maxQuantity;
},
},
// Metody - odpowiednik metod klasy PHP
methods: {
addToCart() {
if (!this.canAddMore) return;
// Wywołanie API lub emitowanie zdarzenia do rodzica
this.$emit('add-to-cart', {
productId: this.product.id,
quantity: this.quantity,
});
this.addedToCart = true;
},
increment() {
if (this.quantity < this.maxQuantity) {
this.quantity++;
}
},
decrement() {
if (this.quantity > 1) {
this.quantity--;
}
},
},
// Szablon HTML z dyrektywami Vue
template: `
<div class="product-card">
<h3>{{ product.name }}</h3>
<p class="price">{{ totalPrice }} PLN</p>
<div class="quantity-control">
<button @click="decrement" :disabled="quantity <= 1">-</button>
<span>{{ quantity }}</span>
<button @click="increment" :disabled="!canAddMore">+</button>
</div>
<button @click="addToCart" :class="{ 'btn-success': addedToCart }">
{{ addedToCart ? 'Dodano!' : 'Dodaj do koszyka' }}
</button>
</div>
`,
};
Dyrektywy Vue – odpowiedniki z PHP
| Vue dyrektywa | Co robi | Analogia PHP/Twig |
|---|---|---|
{{ variable }} |
Wyświetla wartość | <?= $var ?> |
v-if="condition" |
Warunkowe renderowanie | {% if condition %} |
v-for="item in items" |
Pętla po tablicy | {% for item in items %} |
v-model="variable" |
Dwukierunkowe wiązanie z inputem | brak bezpośredniego odpowiednika |
@click="method" |
Obsługa zdarzenia click | brak (to jest JS) |
:class="object" |
Dynamiczne klasy CSS | class="{{ condition ? 'a' : 'b' }}" |
Komunikacja z Magento API przez Vue
// Pobieranie danych z Magento 2 REST API w komponencie Vue
const ProductList = {
data() {
return {
products: [],
loading: false,
error: null,
};
},
async mounted() {
await this.fetchProducts();
},
methods: {
async fetchProducts() {
this.loading = true;
this.error = null;
try {
const response = await fetch(
'/rest/V1/products?searchCriteria[pageSize]=12&searchCriteria[currentPage]=1',
{
headers: {
'Content-Type': 'application/json',
// Token dla zalogowanego klienta
// 'Authorization': 'Bearer ' + customerToken,
},
}
);
if (!response.ok) {
throw new Error('API error: ' + response.status);
}
const data = await response.json();
this.products = data.items;
} catch (err) {
this.error = err.message;
} finally {
this.loading = false;
}
},
},
template: `
<div>
<div v-if="loading">Ładowanie...</div>
<div v-else-if="error">Błąd: {{ error }}</div>
<div v-else>
<product-card
v-for="product in products"
:key="product.id"
:product="product"
@add-to-cart="handleAddToCart"
/>
</div>
</div>
`,
};
Composition API – podejście bardziej "PHP-owe"
Vue 3 wprowadził Composition API – alternatywę dla Options API, gdzie logikę grupujesz funkcjami zamiast opcjami obiektu. Dla PHP developera przyzwyczajonego do klas i metod, Composition API może być bardziej intuicyjne:
import { ref, computed, onMounted } from 'vue';
// Composition API - setup() zamiast data/methods/computed
export default {
props: ['productId'],
setup(props) {
// ref() to odpowiednik właściwości klasy - reaktywna wartość
const product = ref(null);
const quantity = ref(1);
const loading = ref(false);
// computed - odpowiednik gettera
const totalPrice = computed(() => {
return product.value
? (product.value.price * quantity.value).toFixed(2)
: '0.00';
});
// Funkcja - odpowiednik metody
async function loadProduct() {
loading.value = true;
const response = await fetch('/rest/V1/products/' + props.productId);
product.value = await response.json();
loading.value = false;
}
// Hak cyklu życia - uruchom po zamontowaniu komponentu
onMounted(loadProduct);
// Eksportuj to co ma być dostępne w template
return { product, quantity, totalPrice, loading };
},
};
Podsumowanie
Vue.js ma łagodną krzywą uczenia się – komponent z Options API jest strukturalnie podobny do klasy PHP z właściwościami i metodami. Reaktywność (automatyczna aktualizacja widoku przy zmianie danych) to największa zmiana w myśleniu względem klasycznego PHP, gdzie renderowanie to jednorazowy proces. Jeśli planujesz pracę z Vue Storefront lub budujesz interaktywne komponenty dla sklepu Magento – warto poświęcić na Vue kilka weekendów.
