// useUserService.ts
function isAuthenticated() {
return !!user.value;
}
// Component A
<script>
const { isAuthenticated } = useUserService();
</script>
<template>
<p v-if="isAuthenticated()">hello</p>
</template>
Функции во
Vue
ведут себя не совсем как функцииВ данном примере функция
isAuthenticated()
ведет себя как computed
и будет вызываться каждый раз, когда user
изменится или компонент А
будет перерисовываться.Происходит это из-за того, что
Vue
определяет все реактивные зависимости внутри тела функции и перерендивает компонент, когда кто-то из них меняется.Таким образом, большой разницы в использовании функции вместо
computed
нет. Но если внутри большая логика, то лучше использовать computed
, потому что он будет пересчитываться только когда его зависимости изменились, а функция - при любом рендеринге#reactivity #tip #optimization
❤10💩3👍2😁2👎1🌚1
Для
Для
Добавьте в скрипты своего
Считает число компонент в проекте.
#tip
Linux
:"count:sfc": "find . -type f -name '*.vue' ! -path '*/node_modules/*' | wc -l"
Для
Windows
:"count:sfc": "Get-ChildItem -Recurse -Include *.vue -Exclude '*/node_modules/*' | Measure-Object -Line"
Добавьте в скрипты своего
package.json
. Считает число компонент в проекте.
#tip
👍11
Чтобы заставить
#vite #tip
Vite HMR
перегружаться при изменении конкретных файлов, иногда может понадобиться такой плагин:// vite.config.ts
const fullReloadJson5 = {
name: "full-reload-json5",
handleHotUpdate({ file, server }) {
if (file.endsWith(".json5")) {
server.ws.send({ type: "full-reload" });
}
return [];
},
};
// ...
plugins: [
vue(),
json5Plugin(),
fullReloadJson5,
],
#vite #tip
🤯9
Полезные советы при разработке с
1. Используйте по возможности системный промпт.
Напишите свой и попросите
2. Научитесь азам promp-engineering. Это полезно и при разработке, и при диалогах с обычными чатботами. От простого
3. Используйте сильные стороны
4. Используйте его как консультанта перед реализацией какой-то задачи. Задайте несколько вопросов в чате, как что-то можно сделать (с использованием вашего кода как контекста), проанализируйте варианты, выберите подходящий и дальше в
4.1. Вместо «Напиши такой-то модуль» используйте цепочку:
- Проектирование API
- Реализация core-логики
- Добавление обработки ошибок
- Интеграция с существующим кодом
- Оптимизация производительности
5.
6.
7. При использовании
8. Пробуйте разные модели. Причем, разные модели для разных случаев. Дороже ≠ лучше.
9. Переиспользуемые промпты можно хранить в отдельных текстовых файлах.
Также, научитесь использовать структурированные промпты при необходимости, например:
Для современных
10. Почитайте документацию к вашей
#ai #tip #ide #cursor
IDE
AI
агентами от @vuefaq.1. Используйте по возможности системный промпт.
Cursor
позволяет иметь .cursorrules
файл, в котором можно прописать основные установки по проекту. Пример файла.Напишите свой и попросите
AI
улучшить его. Автокомплит его плохо видит, но чат и composer
- вполне. По крайней мере, свою CSS
дизайн систему и компоненты использует четко.2. Научитесь азам promp-engineering. Это полезно и при разработке, и при диалогах с обычными чатботами. От простого
few-shots prompt
эффективность результата может вырасти в разы. Не надо винить AI
в тупости, если вы не умеете формулировать вопрос на языке, который ему более понятен.3. Используйте сильные стороны
AI
. Он может хорошо сгенерить новый компонент, новый микросервис, добавить функционал, сделать i18n
перевод, дать совет по какой-то лучшей практике в определённой области, рефакторить, делать рутинные задачи, писать тесты, но не так хорошо работает на больших изменениях с существующим кодом. Также может с нуля нагенерировать плохой неоптимальный код на нестандартных задачах (в таких случаях, необходимо давать максимально подробную информацию о контексте задачи).4. Используйте его как консультанта перед реализацией какой-то задачи. Задайте несколько вопросов в чате, как что-то можно сделать (с использованием вашего кода как контекста), проанализируйте варианты, выберите подходящий и дальше в
composer
начните постепенно его реализовывать, руководя процессом. Стратегически важные вопросы задавайте также разным внешним системам - Gemini
, ChatGPT
, DeepSeek
. Иногда кто-то один даёт явно более лучший ответ.4.1. Вместо «Напиши такой-то модуль» используйте цепочку:
- Проектирование API
- Реализация core-логики
- Добавление обработки ошибок
- Интеграция с существующим кодом
- Оптимизация производительности
5.
AI
- не старик Хоттабыч, он не творит чудеса. Более того, он очень тупой. Тупой инструмент. Но сильный. Управление им это как управление двухтонным ковшом экскаватора - можно быстро сделать много полезного, и можно быстро сделать кучу плохого (со своим кодом). Которую потом будешь долго разгребать.6.
AI
хорошо генерит комментарии и документацию. Можете добавить сразу VitePress
к проекту и поддерживать его техническую документацию.7. При использовании
AI
сервисов в приложении используйте структурированные (JSON
) ответы. Не все это умеют, но последняя 4o-mini
, например, умеет (по JSON-scheme
). С учетом цены на нее, она очень полезна для парсинга документов или картинок, скажем, из которых предварительно можно вытащить текст конвенциональными методами (pdf2text
и OCR
).8. Пробуйте разные модели. Причем, разные модели для разных случаев. Дороже ≠ лучше.
9. Переиспользуемые промпты можно хранить в отдельных текстовых файлах.
Также, научитесь использовать структурированные промпты при необходимости, например:
/analyze-tech-debt
--focus=duplication,complexity
--suggest-refactoring
Для современных
LLM
они, часто, предпочтительней для простых задач.10. Почитайте документацию к вашей
LLM
и лучшие практики. Ваша продуктивность ( => стоимость как разработчика) может возрасти в несколько раз с этим инструментом. Потратьте время на то, чтобы научиться им эффективно пользоваться.#ai #tip #ide #cursor
👍20
Если показываете через
Через
Через хук роутера
Второй способ дает еще возможность использовать
#router #tip
<router-view>
страницу с route
параметром (продукты, каталоги, пользователей через id
), и надо при смене параметра загружать нового, - то есть, следить за изменением параметра, то делать это можно двумя способами.Через
watch
:watch(
() => props.id,
async () => {
userData.value = await fetchUser(to.params.id);
},
{ immediate: true }
);
Через хук роутера
onBeforeRouteUpdate
:js
import { onBeforeRouteUpdate } from 'vue-router'
onBeforeRouteUpdate(async (to, from) => {
if (to.params.id !== from.params.id) {
userData.value = await fetchUser(to.params.id);
}
})
Второй способ дает еще возможность использовать
onBeforeRouteLeave
, если вдруг надо#router #tip
🔥19👍7
Если делаете два близких приложения (например, клиентский фронтенд и админку) , и хотите расшарить какие-то компоненты и ресурсы, то есть несколько вариантов
1. Монорепозиторий. Оба проекта идут как пакеты и общие пакеты тоже отдельно. На любителя.
2. Выделить общее в отдельный
3. Делать в одном проекте, настроить на две точки входа. Собирать
4. Два отдельных
4.
#tip
1. Монорепозиторий. Оба проекта идут как пакеты и общие пакеты тоже отдельно. На любителя.
2. Выделить общее в отдельный
NPM
пакет и подключать его. Неудобно возиться с версиями и апдейтом.3. Делать в одном проекте, настроить на две точки входа. Собирать
Vite
будет в одну кучу с двумя html
файлами входа. Подразумевается, что так удобно работать на одном сайте с двумя мини-приложениями4. Два отдельных
vite.config.ts
файла, два html, два App.vue и роутера. В package.json
в скриптах прописываете свой Vite
конфиг и копирование своего html в index.html
. Запускается и собирается каждый как отдельный проект, в коде всё общее.4.
Git submodules
. Отдельный проект подключается как поддиректория в твой (общие компоненты).#tip
👍6👎1
Если работаете с
CSS Variable Autocomplete
#css #tip
CSS properties
в VS Code
, то вот полезное расширениеCSS Variable Autocomplete
#css #tip
Visualstudio
CSS Variable Autocomplete - Visual Studio Marketplace
Extension for Visual Studio Code - Autocomplete CSS Variable support CSS, SCSS, LESS, PostCSS, VueJS, ReactJS and more
👍9❤🔥1🎄1
Я ранее советовал переходить от
Но нужно понимать, что переменные из
Это значит блок кода
не попадет в бандл вообще в первом случае, а аналог с конфиг файлом - попадет, (но не будет выполняться, естественно).
Так что иногда имеет смысл использовать эту конструкцию (для
#vite #tip
.env
к конфигурационным файлам в json
форматеНо нужно понимать, что переменные из
.env
заменяются в коде на этапе компиляции, а из конфига подставляются в райнтаймеЭто значит блок кода
if (import.meta.env.MODE === "development") {
// do some debug work
}
не попадет в бандл вообще в первом случае, а аналог с конфиг файлом - попадет, (но не будет выполняться, естественно).
Так что иногда имеет смысл использовать эту конструкцию (для
import.meta.env.MODE
переменной .env
файл не нужен, она определена всегда).#vite #tip
Telegram
Vue-FAQ
Как организовать конфигурационные параметры в приложении?
Наиболее удобна, имхо, следующая конфигурация конфигов.
Есть, грубо говоря, .env, .env.staging, .env.local
Локально используется .env.local, он в гитигноре, и у каждого разработчика свой. Если работаешь…
Наиболее удобна, имхо, следующая конфигурация конфигов.
Есть, грубо говоря, .env, .env.staging, .env.local
Локально используется .env.local, он в гитигноре, и у каждого разработчика свой. Если работаешь…
❤1
Если у вас есть массив, в каждом элементе которого есть
#tip #performance #reactivity
computed
, то лучше создать один на весь массив, чем много для каждого элемента// Bad
const rows = productRows.map(row => ({
...row,
total: computed(() => row.price * row.qty),
}));
// Good
const computedRows = computed(() =>
productRows.map(row => ({
...row,
total: row.price * row.qty,
}))
);
#tip #performance #reactivity
🗿19👍7🤯4
Глубокое клонирование реактивных объектов в Vue 3
3 рабочих способа
1. Комбинация
2. Ручное глубокое копирование
3. Библиотечные решения
#tip #reactivity
Vue 3
использует Proxy
для реактивности, что создает проблемы при попытке клонировать объекты. Стандартные методы работают не так, как ожидается:const state = reactive({ user: { name: "Al" } });
// Проблемы:
const badCopy1 = { ...state }; // сохраняет Proxy-ссылки
const badCopy2 = JSON.parse(JSON.stringify(state)); // теряет методы и Proxy
3 рабочих способа
1. Комбинация
toRaw
+ structuredClone
import { toRaw } from 'vue';
const original = reactive({ data: 123 });
const copy = structuredClone(toRaw(original));
2. Ручное глубокое копирование
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
const clone = Array.isArray(obj) ? [] : {};
for (const key in obj) {
clone[key] = deepClone(obj[key]);
}
return clone;
}
const copy = reactive(deepClone(toRaw(original)));
3. Библиотечные решения
import { cloneDeep } from 'lodash-es';
const copy = reactive(cloneDeep(toRaw(obj)));
#tip #reactivity
👍11
This media is not supported in your browser
VIEW IN TELEGRAM
:hover > :not(:hover)
#css #tip
hover
обычно используется, чтобы выделить какой-то элемент. Но иногда красивей что-то сделать с остальнымиul {
@media (hover) and (prefers-reduced-motion: no-preference) {
& > li {
transform-origin: left center;
transition: transform 1s var(--ease-spring-3), opacity 0.3s var(--ease-3);
}
&:hover > li:not(:hover) {
opacity: 0.25;
transform: scale(0.8);
}
}
}
#css #tip
👍21
В
И не забываем, что
#js #tip
JS
чтобы выйти из вложенных циклов можно использовать меткиouterLoop: for (let i = 0; i < 5; i++) {
let j = 0;
while (true) {
if (j === 2) {
break outerLoop; // Выходит из внешнего цикла
}
j++;
}
}
И не забываем, что
Array.prototype.sort()
приводит к строкам. Нужен компаратор.[10, 2, 1].sort(); // [1, 10, 2] (как строки!)
[10, 2, 1].sort((a, b) => a - b); // [1, 2, 10] (правильно)
#js #tip
🥴9👍5😁2
Метод
Браузер дает запросу
Практические применения
- Финализация аналитических данных - отправка собранной за сессию аналитики перед закрытием страницы
- Автосохранение - сохранение последнего состояния приложения, которое пользователь мог не сохранить явно
- Отчеты об ошибках - гарантированная отправка логов о критических ошибках
- Трекинг поведения - фиксация последних действий пользователя перед уходом
Ограничения
- Максимальный размер полезной нагрузки ограничен (обычно 64Кб)
- Поддерживает только POST-запросы
- Не поддерживает кастомные заголовки
- Ответ сервера не может быть обработан
#tip
navigator.sendBeacon()
предоставляет возможность гарантированно отправить небольшой объем данных на сервер, даже если пользователь закрывает страницу или браузер. В отличие от традиционных AJAX
-запросов, которые могут быть прерваны при выгрузке страницы, sendBeacon
обеспечивает доставку данных в таких сценариях.Браузер дает запросу
sendBeacon
приоритетное выполнение перед завершением работы страницы, что делает этот метод идеальным для критически важных данных.Практические применения
- Финализация аналитических данных - отправка собранной за сессию аналитики перед закрытием страницы
- Автосохранение - сохранение последнего состояния приложения, которое пользователь мог не сохранить явно
- Отчеты об ошибках - гарантированная отправка логов о критических ошибках
- Трекинг поведения - фиксация последних действий пользователя перед уходом
const data = JSON.stringify({event: 'page_close', time: Date.now()});
navigator.sendBeacon('/analytics', data);
Ограничения
- Максимальный размер полезной нагрузки ограничен (обычно 64Кб)
- Поддерживает только POST-запросы
- Не поддерживает кастомные заголовки
- Ответ сервера не может быть обработан
#tip
👍35❤1