Вивчення Vue для розробників React

текст перекладу
Будучи знайомими з кількома фреймворками, ви не єдиний у фронтенд-розробці. Більшість сучасних фреймворків мають спільні основи: архітектуру на основі компонентів, управління станом, маршрутизацію, декларативний рендеринг тощо. Багато з цих концепцій є спільними для фреймворків, і в кінцевому підсумку, це все просто JavaScript.

Якщо ви вже знайомі з React, навчання Vue має бути простим. Давайте порівняємо деякі приклади коду.

Зміст

  1. Оголошення компонентів
  2. Шаблони
  3. Оголошення реактивних даних
  4. Обробка подій
  5. Умовний рендеринг
  6. Прив'язка класів
  7. Списки
  8. Комунікація між батьківським і дочірнім компонентами (Props)
  9. Комунікація з батьківським компонентом (Emits)
  10. Виведення стану
  11. Продуктивність компонентів
  12. Побічні ефекти та спостерігачі
  13. Хуки життєвого циклу
  14. Завантаження даних
  15. Стилі CSS
  16. Анімації
  17. Користувацькі хуки та композиційні функції
  18. Управління глобальним станом
  19. Інструменти
  20. Маршрутизація

1. Оголошення компонентів

Перша основна відмінність полягає в оголошенні компонентів. У React компонент — це просто експортована функція, яка має повертати шаблон:

export function MyComponent() {  
 return 
Hello, React World!
;   } ```  

У **Vue** компоненти оголошуються всередині спеціального файлу з розширенням `.vue`, який називається **Single File Components (SFC)**. SFC має три чітко розмежовані секції:  
      ```  

Усі три секції є необов'язковими. Ми дізнаємось більше про них пізніше.

2. Шаблони

Це ще одна суттєва відмінність. Шаблони в попередніх прикладах можуть виглядати як звичайний HTML, але це не так.
React використовує JSX, спеціальний синтаксис для представлення DOM. У ньому є кілька відмінностей, зокрема безліч кастомних правил і можливість писати JavaScript всередині.
З іншого боку, синтаксис шаблонів Vue виглядає значно ближче до чистого HTML, але також підтримує такі функції, як директиви та вирази JavaScript.
Ця відмінність є основою для багатьох наступних секцій.

3. Оголошення реактивних даних

Обидва фреймворки підтримують реактивність. Вони автоматично відстежують зміни та оновлюють усі залежності, зокрема інтерфейс користувача.
У React реактивні дані оголошуються за допомогою хука useState, який створює змінну стану та відповідну функцію для її оновлення.

import { useState, useEffect } from "react";
export function MyComponent() {
const [count, setCount] = useState(0);
return (
Count: {count}
);
}

У цьому прикладі count — це реактивні дані, а setCount — функція, яка оновлює їх. Кожного разу, коли викликається setCount, React перерендерює компонент, щоб відобразити оновлене значення count. Для виведення значення змінної або вводу JavaScript в шаблон використовується одинарний синтаксис фігурних дужок { }.

У Vue реактивні дані керуються за допомогою допоміжних функцій ref (абоreactive) з Composition API. Обидві функції повертають реактивну змінну.


Тут count робиться реактивним за допомогою допоміжної функції ref. Кожна змінна або функція, оголошена всередині скрипту, буде автоматично доступна в шаблоні. Vue використовує подвійний синтаксис фігурних дужок {{ }} для інтерполяції.
На відміну від React, де потрібно явно викликати функцію для оновлення стану, Vue відстежує зміни в count автоматично та перерендерює інтерфейс, коли це необхідно. Усередині секції скрипту ми можемо оновити значення через count.value, а в шаблонах .value можна опустити.

**4.

текст перекладу

Обробка подій

У React події обробляються за допомогою атрибутів в стилі camelCase, таких як onClick.

import { useState } from "react";  

export function MyComponent() {  
 const [count, setCount] = useState(0);  

 const handleClick = () => {  
 setCount(count + 1);  
 };  

 return (  

Count: {count}
Increment    
    );   } ```  

React приєднує функцію `handleClick` до кнопки. Коли кнопка натискається, функція оновлює стан і перерендерює компонент.  

**Vue** використовує ту ж саму ідею, але з дещо іншим синтаксисом.  

    ```  

Функція збільшення прив'язана до кнопки за допомогою @click. Коли кнопка натискається, функція оновлює реактивну змінну, і шаблон автоматично оновлюється.

Ми також можемо використовувати модифікатори, такі як .prevent, .stop, .once і більше для керування поведінкою подій безпосередньо в шаблоні.

Increment

5. Умовний рендеринг

React і Vue по-різному обробляють умовний рендеринг.

У React ми можемо використовувати тернарний оператор або оцінку з коротким замиканням (&&) для умовного рендерингу.

import { useState } from "react";      
export function MyComponent() {    
   const [isVisible, setIsVisible] = useState(true);       
   return (    
    {isVisible && 
This is visible
}    
    {isVisible ? 
This is visible
 : 
This is hidden
}    
    );   
} ```  

Для обробки кількох випадків часто використовують вкладений тернарний оператор.

{
condition1 ? (
Condition 1
) : condition2 ? (
Condition 2
) : (
Else
)
} ```

У Vue умовний рендеринг здійснюється за допомогою вбудованих директив v-if і v-else.

        ```  

Кілька випадків обробляються за допомогою `v-else-if`.  

Condition 1
Condition 2
Else
```

6. Прив'язка класів

Тернарний оператор також можна використовувати для умовного застосування класу в React.

import { useState } from "react";      
export function MyComponent() {    
   const [isVisible, setIsVisible] = useState(true);       
   return (    

   This is a conditionally styled message.  

    );   
} ```  

У **Vue** синтаксис трохи інший, де директива класів приймає об'єкт як параметр.  

текст перекладу

Списки

Ітерації в React виконуються всередині інтерполяції за допомогою методу JavaScript .map().

export function MyComponent() {  
 const items = ["Item 1", "Item 2", "Item 3"];  

 return (  

    {items.map((item, index) => (    
{item}
    ))}    
    );   
} ```  

У **Vue** ми використовуємо `v-for`, іншу вбудовану директиву.  

    ```  

8. Комунікація з батьківського до дочірнього компонента (Props)

Обидва фреймворки використовують концепцію props для передачі даних між компонентами.

У React props передаються як атрибути в шаблоні. Вони доступні тільки для читання та можуть бути доступні як аргументи в дочірньому компоненті.

export function ParentComponent() {    
   const message = "Hello from React!";       
   return ;   
}    

export function ChildComponent({ message }) {    
   return 
{message}
;   
} ```  

Та сама ідея у Vue, але дочірній компонент має явно оголосити кожен `prop`, використовуючи допоміжну функцію `defineProps`. Кожен `prop` можна типізувати і [мати необов'язковий валідатор або значення за замовчуванням](https://vuejs.org/guide/components/props#prop-validation).  

       ```  
           ```  

## **9. Комунікація з дочірнього до батьківського компонента (Emits)**

`Props` дозволяють передавати дані з батьківського до дочірнього компонента, але як бути в зворотному напрямку?  

У React немає спеціальної функціональності для цього. Натомість ми можемо передати функцію зворотного виклику як `prop` дочірньому компоненту, який може використовувати її для оновлення стану батьківського компонента.  

export function ParentComponent() {
const handleCustomEvent = (message) => {
console.log(message);
};
return ;
}

export function ChildComponent({ onCustomEvent }) {
return (
onCustomEvent("Hello from the child!")}>
Click Me
);
} ```

У Vue використовується інша модель. Дочірні компоненти можуть викидати (emit) власні події за допомогою допоміжної функції defineEmits.

           ```  
       ```  

Дочірній компонент викидає подію customEvent з деякими необов'язковими даними, а батьківський компонент слухає її за допомогою директиви @customEvent. Допоміжна функція defineEmits забезпечує типову безпеку і чіткість для оголошених подій.

10. Виведений стан (Derived State)

У React виведений стан обчислюється за допомогою хуку useMemo, який мемоізує результат, щоб уникнути непотрібних перерахунків.

import { useState, useMemo } from "react";      

export function MyComponent() {    
   const [firstName, setFirstName] = useState("Frodo");    
   const [lastName, setLastName] = useState("Baggins");       
   const fullName = useMemo(() => `${firstName} ${lastName}`, [firstName, lastName]);       
   return 
Full Name: {fullName}
;   
} ```  

**Vue** використовує обчислювані властивості (computed properties).
текст перекладу
## 11. Продуктивність компонентів

Важливо знати, що в **React** компоненти перерендерюються після кожної зміни стану або `prop`. Хоча це зазвичай ефективно, це може стати дорогим процесом, коли йдеться про складні обчислення або великі компоненти. Щоб уникнути непотрібних перерахунків, React надає інструменти, такі як `React.memo`, `useMemo` та `useCallback`.

`React.memo` запобігає перерендеренню функціонального компонента, якщо його `props` не змінилися.

import React, { useState } from "react";

const ChildComponent = React.memo(({ count }) => {
console.log("Child rendered");
return
Count: {count}
;
});

export function ParentComponent() {
const [count, setCount] = useState(0);
return (
setCount(count + 1)}>Increment
);
} ```

useMemo запобігає перерахунку дорогих функцій, якщо їх залежності не змінилися. (Див. також розділ про виведений стан)

import { useState, useMemo } from "react";      

export function MyComponent() {    
   const [count, setCount] = useState(0);       
   const expensiveCalculation = useMemo(() => {    
    console.log("Calculating...");    
    return count * 2;    
   }, [count]);       

   return (    
Count: {count}
Calculated: {expensiveCalculation}
 setCount(count + 1)}>Increment    
 );   
} ```  

`useCallback` мемоізує функції, щоб запобігти їх повторному створенню, що особливо корисно при передачі функцій зворотного виклику як `props`.  

import { useState, useCallback } from "react";

export function MyComponent() {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount((prevCount) => prevCount + 1);
}, []);

return (
Count: {count}
Increment
);
} ```

Код для виконання тих самих оптимізацій у Vue виглядає так. У Vue багато оптимізацій обробляються автоматично його системою реактивності. Вона відстежує залежності для реактивних змінних і перераховує їх лише тоді, коли це необхідно. Тому немає потреби в ручному налаштуванні продуктивності на низькому рівні.

12. Побічні ефекти та спостерігачі (Watchers)

У React для моніторингу певних значень і виконання функцій зворотного виклику при зміні цих значень використовується useEffect.

import { useState, useEffect } from "react";      

export function MyComponent() {    
   const [count, setCount] = useState(0);       
   useEffect(() => {    
    console.log(`Count changed to ${count}`);    
   }, [count]);       

   return (    
Count: {count}
 setCount(count + 1)}>Increment    
 );   
} ```  

Масив залежностей `[count]` гарантує, що ефект буде виконаний лише коли зміниться значення `count`.

У Vue для цього є спостерігачі (watchers).  

    ```  

Функція зворотного виклику буде виконана кожного разу, коли зміниться значення count.

Є ще watchEffect, але він не такий крутий!
текст перекладу

13. Хуки життєвого циклу

Хук useEffect, у поєднанні з порожнім масивом залежностей, можна використовувати для виконання коду під час ініціалізації компонента або перед його знищенням.

import { useEffect } from "react";  

export function MyComponent() {  
   useEffect(() => {  
      console.log("Component mounted");  

      return () => {  
         console.log("Component unmounted");  
      };  
   }, []);  

   return 
My React Component
;   
} ```  

Vue надає спеціалізовані хуки, такі як `onMounted` та `onUnmounted` для етапів [життєвого циклу компонента](https://vuejs.org/guide/essentials/lifecycle).

    ```  

14. Завантаження даних

Обидва фреймворки часто використовують сторонні бібліотеки, такі як Axios, React Query, або Vue Query для завантаження даних. Однак основна логіка залишається подібною до використання вбудованого методу fetch. Ось типовий випадок використання:

У React завантаження даних обробляється всередині хука useEffect.

import { useState, useEffect } from "react";      

export function MyComponent() {    
   const [data, setData] = useState(null);    
   const [loading, setLoading] = useState(true);       

   useEffect(() => {    
      async function fetchData() {    
         const response = await fetch("https://api.example.com/data");    
         const result = await response.json();    
         setData(result);    
         setLoading(false);    
      }       

      fetchData();    
   }, []);       

   if (loading) return 
Loading...
;       

   return 
Data: {data.message}
;   
} ```  

У **Vue** завантаження даних можна обробляти безпосередньо під час ініціалізації компонента.

    ```  

15. CSS стилі

Існує безліч способів стилізувати компонент React. Від інлайнових стилів до CSS-модулів і бібліотек, таких як Emotion та Styled Components, усе може стати досить складним і, ймовірно, потребує окремої статті. Ми розглянемо лише найпоширеніші варіанти використання, але ви можете більше дізнатися про опції стилізації в React.

Використання інлайнових стилів:

export function MyComponent() {    
   const style = {    
      color: "blue",    
      fontSize: "20px",    
   };       

   return 
Styled Text
;   
} ```  

Використання зовнішніх CSS файлів:

import "./styles.css";

export function MyComponent() {
return
Styled Text
;
} ```

Зверніть увагу, що в React використовується className, а не class, щоб уникнути конфліктів з зарезервованими ключовими словами JavaScript.
текст перекладу

18. Особливості JSX

Це одна з особливостей JSX.

Використання CSS Модулів:

import styles from "./MyComponent.module.css";  

export function MyComponent() {  
   return 
Styled Text
;   
} ```  

CSS Модулі автоматично обмежують застосування стилів поточним компонентом, і вони наразі є дуже популярним вибором. У **Vue** стилі — це одна з трьох секцій в компоненті з єдиним файлом.

    ```  

Атрибут scoped гарантує, що CSS впливатиме лише на поточний компонент. Препроцесори, такі як Scss, Less, Stylus або postcss, також підтримуються через додавання атрибута lang до тега стилів. Scss — це популярний вибір.

        ```  

> Атрибут `lang` також можна використовувати для інших секцій, щоб конвертувати ваші скрипти в `typescript` або ваш шаблон в `pug`, наприклад.

## 16. Анімації

React не займається анімаціями, але їх можна створювати в React за допомогою сторонніх бібліотек, таких як [**Framer Motion**](https://www.npmjs.com/package/framer-motion), [**React Spring**](https://www.react-spring.dev/), або навіть CSS-переходів. Хоча у Vue також підтримується використання сторонніх бібліотек, він пропонує потужний вбудований механізм, який може обробляти як прості, так і складні анімації. Обгортання елемента в компонент `transition` або `transition-group` автоматично застосовує класи під час анімації, які можна націлювати за допомогою CSS для створення власних ефектів.

Простий приклад:

          ```  

[ ## Vue 3 Real Life Transitions and Micro-Interactions

Vue надає простий і елегантний спосіб обробки анімацій. Ви можете легко застосувати їх, додавши …

fadamakis.com ](/vue-js-real-life-transitions-and-micro-interactions-e86bd51301b8?source=post_page-----602d0f98755a--------------------------------)

17. Користувацькі хуки та композиційні функції

Ось де відбувається вся магія*.

  • реалізація складної бізнес-логіки, яка точно викличе головний біль

У React користувацькі хуки — це просто функції JavaScript, які можуть зберігати стан і функції. Вони можуть використовувати інші хуки, такі як useState або useEffect.

import { useState } from "react";      

function useCounter(initialValue = 0) {    
   const [count, setCount] = useState(initialValue);       

   const increment = () => setCount(count + 1);    
   const decrement = () => setCount(count - 1);       

   return { count, increment, decrement };   
}      

export function MyComponent() {    
   const { count, increment, decrement } = useCounter();       

   return (    
      Count: {count}    
      Increment    Decrement    
   );   
} ```  

У **Vue** композиційні функції виконують ту ж саму роль.
текст перекладу
## **Користувацькі хуки та композиційні функції (Composables)**

Вони зберігають стан та повторно використовувану логіку.

// useCounter.js
import { ref } from "vue";

export function useCounter(initialValue = 0) {
const count = ref(initialValue);

const increment = () => count.value++;
const decrement = () => count.value--;

return {
count,
increment,
decrement
};
}
```




[

Композиційні функції (Composables) як управління станом у Vue3

Спільне використання стану між компонентами у світі Vue 3 стало легшим, завдяки композиційним функціям. Ця нова парадигма…

fadamakis.com

](/composables-as-state-management-in-vue3-ad59837cad48?source=post_page-----602d0f98755a--------------------------------)

18. Глобальне управління станом

Ще одна складна тема, яка могла б бути окремою статтею. Ми зосередимося на базовому випадку, але ви можете дізнатися більше про управління станом у React або Vue, якщо хочете більше інформації.

У React глобальне управління станом зазвичай здійснюється за допомогою бібліотек, таких як Redux, Zustand або вбудованого Context API. Ось приклад використання останнього.

import { createContext, useContext, useState } from "react";  

const CounterContext = createContext();  

export function CounterProvider({ children }) {  
   const [count, setCount] = useState(0);  

   return (  

     {children}  

   );  
}  

export function useCounter() {  
   return useContext(CounterContext);  
}  

// Приклад використання:  
export function MyComponent() {  
   const { count, setCount } = useCounter();  

   return (  

Count: {count}
 setCount(count + 1)}>Increment    
    );   
} ```  

У **Vue** новішою та офіційно рекомендованою бібліотекою для управління станом є [Pinia](https://pinia.vuejs.org/).

import { defineStore } from "pinia";

export const useCounterStore = defineStore("counter", () => {
const count = ref(0);
const increment = () => {
count.value++;
};
return { count, increment };
});
```

        ```  

Зверніть увагу, як це схоже на композиційну функцію? Тому що це вона! Основна перевага використання Pinia — легкість перевірки та відлагодження за допомогою Vue DevTools.

## 19. Інструменти

Інструментів було б дуже багато кілька років тому. Але на щастя, зараз **Vite** домінує в обох екосистемах і широко вважається найкращим вибором. Він надає швидкі збірки, гарячу заміну модулів, розподіл коду та плагіни, і його набагато легше налаштовувати.

npm create vite@latest my-react-app -- --template react
```

 npm create vite@latest my-vue-app -- --template vue

текст перекладу
## Маршрутизація (Routing)

Обидва фреймворки використовують зовнішні бібліотеки для маршрутизації, але їх підходи відрізняються за синтаксисом та структурою.

**React** використовує [**React Router**](https://reactrouter.com/). Конфігурація нагадує оголошення компонента і може здаватися трохи незвичною на перший погляд.

import { BrowserRouter as Router, Route, Routes, Link } from "react-router-dom";

export function App() {
return (

 <Router>  
   <nav>  
     <Link to="/">Home</Link>  
     <Link to="/about">About</Link>  
   </nav>  
   <Routes>  
     <Route path="/" element={<Home />} />  
     <Route path="/about" element={<About />} />  
   </Routes>  
 </Router>  

);
}

function Home() {
return

Home Page

;
}

function About() {
return

About Page

;
}
```

Vue використовує Vue Router. Конфігурація більш декларативна, визначаючи зіставлення маршрутів у конфігураційному об'єкті.

import { createRouter, createWebHistory } from "vue-router";   
import Home from "./components/Home.vue";   
import About from "./components/About.vue";  

const routes = [  
   { path: "/", component: Home },  
   { path: "/about", component: About },  
];  

export const router = createRouter({  
   history: createWebHistory(),  
   routes,  
});  
        ```  

`<router-link>` та `<router-view>` доступні глобально і не потребують явного імпорту.

## Висновок

Тепер настав час для питання на мільйон доларів. Який з фреймворків кращий?

Ну...  
> Все залежить від того, що вам важливіше.

Навчання API нового фреймворка займає лише кілька тижнів. Справжнім викликом є реалізація складної бізнес-логіки всередині користувацьких хуків (custom hooks) або композиційних функцій (composables), управління станом і... вирівнювання div-ів. І жоден з цих аспектів не є частиною жодного з фреймворків.

Для мене вибір очевидний, і він залежить від того, чи **любите ви писати JSX чи ні**. React значною мірою покладається на нього, тоді як Vue слідує більш декларативному, шаблонно орієнтованому синтаксису.

Крім того, різниці незначні, якщо подивитися на картину в цілому. Обидва фреймворки потужні і здатні впоратися з будь-яким масштабним додатком. В кінці кінців, важливо не стільки з яких інструментів ви користуєтесь, скільки з того, як ви їх використовуєте. Тому використовуйте їх добре!

![pic](https://drive.javascript.org.ua/d90d204e6a1_QXb_ojcVnekAmWDeHHkrmA_png)

_Вибору немає._



Перекладено з: [Learning Vue for React Developers](https://fadamakis.medium.com/learning-vue-for-react-developers-602d0f98755a)

Leave a Reply

Your email address will not be published. Required fields are marked *