Пользователь @kirilljs написал в Проблема с дублированием данных при вызове return вместо reply.send - Fastify:
const userService = new UserService();
Лучше не создавать сервис каждый раз в функции, это лишние затраты
Пользователь @kirilljs написал в Проблема с дублированием данных при вызове return вместо reply.send - Fastify:
const userService = new UserService();
Лучше не создавать сервис каждый раз в функции, это лишние затраты
Во первых ты описал createNewUser()
как асинхронную функцию, и она у тебя ничего не возвращает, а также ты нигде await не используешь, у тебя тогда и try не будет ничего ловить
Попробуй вместо userRepository.save(user)
написать асинхронную функцию простую (например таймер), и сделай там console.log(), посмотри сколько сообщений выдаст, сделай такой дебаггинг
Пользователь @kirilljs написал в pm2 автоматический restart при перезагрузки сервера:
Далее нам необходимо запустить скрипт startup, который как раз отвечает за автоматический запуск pm2 после перезагрузки сервера:
Поправка: команда startup просто показывает команду, при исполнении которой сервис pm2 будет загружать автоматически сохраненные процессы
После обновления Next js до 15 версии, в динамических маршрутах разработчики некоторые изменения, что приведет к ошибкам при сборке проекта.
пример:
Type error: Type 'Props' does not satisfy the constraint 'PageProps'.
Types of property 'params' are incompatible.
Type '{ slug: string; }' is missing the following properties from type 'Promise<any>': then, catch, finally, [Symbol.toStringTag]
Разработчики сделали динамические параметры асинхронными, поэтому нужно будет поменять типы, и получать их мы должны, например, через await
до 15 версии:
// СТАРЫЙ КОД
type Props = {
params: {
slug: string;
};
};
export async function generateMetadata({ params: { slug } }: Props) {
const { category } = await fetchData(slug);
...
}
}
export default async function Page({ params: { slug } }: Props) {
const data = await fetchData(slug);
...
}
после 15 версии:
// НОВЫЙ КОД
type Props = {
params: Promise<{
slug: string;
}>;
};
export async function generateMetadata(props: Props) {
const { slug } = await props.params;
const { category } = await fetchData(slug);
...
}
}
export default async function Page(props: Props) {
const { slug } = await props.params;
const data = await fetchData(slug);
...
}
Пользователь @kirilljs написал в Оптимизация React js приложений. Использование функции debounde():
И почему onInput, а не onChange
onInput отлавливает все изменения значения в <input />
, даже такие как нажатие клавиш и вставку текста, поэтому он предпочтительнее в данном случае
Пользователь @kirilljs написал в Оптимизация React js приложений. Использование функции debounde():
Простыми словами, мы колбэчим submitHandler через debounceHandler то как оно должно быть по спецификации JS
не понял вопроса, напомню, чтчо тут не используется никаких форм, фактически все обработчики привязаны к onInput событию, функция debounce()
- самописная
Допустим мы имеем очень абстрактный компонент, который имеет поле ввода текста, кнопку отправки этого текста на сервер, и сообщение о состоянии отправки данных на сервер
// функция иммитации запроса на сервер
function fakeFetch(val: string) {
return new Promise<string>(function (resolve) {
setTimeout(function () {
resolve(`Сервер получил сообщение: ${val}`);
}, 1000);
});
}
// самый простой пример компонента
function App() {
const [val, setVal] = useState('');
const [response, setResponse] = useState('');
const inputHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
setVal(e.target.value);
setResponse('');
};
const submitHandler = async () => {
setVal('');
setResponse('отправка ...');
const resp = await fakeFetch(val);
setResponse(resp);
};
return (
<>
<input type="text" value={val} onInput={inputHandler} />
<button onClick={submitHandler}>Отправить</button>
<p>{response}</p>
</>
);
}
Теперь перед нами встала задача заменить поведение: отправлять данные не по кнопке, а автоматически. Однако мы не может просто так повесить функцию в обработчик inputHandler(), мало того что он будет неоправданно часто отправлять запросы на сервер, так еще и будет сбивать значение val
. Но если мы добавить функцию debounce()
, то она решит эти вопросы.
debounce() - это функция-обертка, которая ограничивает число выполнений переданной в нее функции, некоторым промежутком времени. Если точнее, то, пока промежуток времени не прошел, то зарегистрированная функция не будет исполнятся, а пока она не исполнилась, новый вызов функции будет замещать старый, исключая повторное выполнение.
пример:
function debounce(func, delay: number) {
let timeoutId: number;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func(...args), delay);
};
}
function App() {
const [val, setVal] = useState('');
const [response, setResponse] = useState('');
const inputHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
setVal(e.target.value);
setResponse('');
debounceHandler();
};
const submitHandler = useCallback(async () => {
setResponse('отправка ...');
const resp = await fakeFetch(val);
setVal('');
setResponse(resp);
}, []);
const debounceHandler = useMemo(() => {
return debounce(submitHandler, 800);
}, [submitHandler]);
return (
<>
<input type="text" value={val} onInput={inputHandler} />
{/* <button onClick={submitHandler}>Отправить</button> */}
<p>{response}</p>
</>
);
}
При изменении стейта функциональный компонент вызывает свою функцию каждый раз, и без мемоизации мы бы получали каждый раз новый обработчик debounceHandler()
и submitHandler()
. Но для того чтобы все работало нам необходимо передать одну функцию в debounce один раз!
Поэтому мемоизируем submitHandler() через useCallback
(линтер обычно потребует указать submitHandler
как зависимость debounceHandler
) и саму функцию debounceHandler()
в useMemo
, (т.к debounce() возвращает функцию)
Сначала необходимо войти в систему как суперпользователь базы данных на сервере postgresql. Опять же, самый простой способ подключиться в качестве пользователя postgres — это перейти на пользователя postgres unix на сервере базы данных с помощью команды su следующим образом:
$ su postgres
Далее заходим в среду PostgreSQL
$ psql
В случае успеха вы должны увидеть следующее:
postgres=#
В командной строке PostgreSQL создайте базу данных, имя пользователя и пароль, а затем предоставьте весь доступ этому новому пользователю. Например:
CREATE DATABASE {database};
CREATE USER {user} WITH PASSWORD 'password';
GRANT ALL ON DATABASE {database} TO {user};
выходим из среды PostgreSQL
$ \q
профит!
Если вылезла подобная ошибка:
driverError: error: permission denied for schema public
PostgreSQL версии 15+ может выдать сообщение об ошибке, что у вас нет разрешения на создание чего-либо внутри общедоступной схемы, если заранее явно не указать, кому разрешено это делать.
Нам нужно явно предоставить разрешения пользователю.
sudo su postgres
psql -d {database}
GRANT ALL ON SCHEMA public TO {user};
\q
{database}
- имя базы данных
{user}
- имя пользователя
@Manul поэтому и приходится велосипедить)
Очень удобно внедрять проверку данных запроса декларативно, в контроллерах. Так и учит нас официальная документация nestjs, и для этого нам необходима библиотека class-validator
Но многим не нравится обмазываться декораторами, особенно когда их много решение кажется очень сомнительным:
class CreateCompanyDto implements Dto {
@IsString({message: 'Must be text format'})
@MinLength(2, { message: "Must have at least 2 characters" })
@MaxLength(20, { message: "Can't be longer than 20 characters" })
@IsDefined({ message: 'Must specify a receiver' })
public name!: string;
@MaxLength(253, { message: "Can't be longer than 253 characters" })
@IsFQDN({}, {message: 'Must be a valid domain name'})
@IsDefined({ message: 'Must specify a domain' })
public domain!: string;
@MaxLength(30, { message: "Can't be longer than 30 characters" })
@IsString({message: 'Must be text format'})
@IsDefined({ message: 'Must specify a company size' })
public size!: string;
@IsPhoneNumber(null, {message: 'Must be a valid phone number'})
@IsDefined({ message: 'Must specify a phone number' })
public contact!: string;
}
Zod - это удобная альтернатива библиотеке проверки классов для проверки тела запроса.
Итак поехали…
Создаем схему
import { z } from "zod";
export const createProductShema = z.object({
title: z.string(),
text: z.string(),
active: z.boolean(),
});
type CreateProductDtoType = z.infer<typeof createProductShema>;
// или вместо типа можем использовать интерфейс
export interface CreateProductDto extends CreateProductDtoType {}
z.infer() позволит нам получить тип для данных, которые будем валидировать
далее создаем Pipe
@Injectable()
export class ZodPipe implements PipeTransform {
constructor(private readonly schema: any) {}
transform(value: any, metadata: ArgumentMetadata) {
this.schema.parse(value);
return value;
}
}
и обмазываем наш контролер ранее созданным пайпом
@Controller()
export class AppController {
constructor(private readonly productUseCaseService: ProductUseCaseService) {}
@Post()
createProduct(@Body(new ZodPipe(schema)) body: CreateProductDto) {
return this.productUseCaseService.create(body);
}
}
Ну и для того, чтобы мы отлавливали ошибки валидации, и формировали ответ запроса как нам нужно
напишем фильтр и подключим его
@Catch(ZodError)
export class ZodFilter<T extends ZodError> implements ExceptionFilter {
catch(exception: T, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const status = 400;
response.status(status).json({
errors: exception.errors,
message: exception.message,
statusCode: status,
});
}
}
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalFilters(new ZodFilter());
await app.listen(3000);
}
Такая схема кажется гибче, и вообще zod закрывает проблемные места typescript связанные с отсутствием проверки типов в runtime
Часто объединенные типы Union Type
и перечисляемый тип Enum
- это онди из способов обеспечения типобезопасности кода, в частности типизация ограниченного списка каких либо значений.
Они также оба хорошо работают с современными IDE предлагая в подсказках отфильтрованные значения.
Но бывает задаешься вопросом: что лучше использовать в той или иной ситуации?
Объединенные типы не будут создавать какой либо дополнительный код.
Вот Простой пример:
Версия с Union Type
type VehicleTypeUnion = 'SUV' | 'SEDAN' | 'TRUCK';
const a: VehicleTypeUnion = 'SUV'
->
"use strict";
const a = 'SUV';
Версия с Enum
enum VehicleTypeEnum {
SUV,
SEDAN,
TRUCK,
}
const b: VehicleTypeEnum = VehicleTypeEnum.SUV
->
var VehicleTypeEnum;
(function (VehicleTypeEnum) {
VehicleTypeEnum[VehicleTypeEnum["SUV"] = 0] = "SUV";
VehicleTypeEnum[VehicleTypeEnum["SEDAN"] = 1] = "SEDAN";
VehicleTypeEnum[VehicleTypeEnum["TRUCK"] = 2] = "TRUCK";
})(VehicleTypeEnum || (VehicleTypeEnum = {}));
const b = VehicleTypeEnum.SUV;
перечисляемый тип обычно описывается в виде числовых значений или в виде строковых.
// список
enum VehicleType1 {
SUV,
SEDAN,
TRUCK,
BUS,
MOTORCYCLE
}
// эквивалентный список
enum VehicleType2{
SUV = 0,
SEDAN = 1,
TRUCK = 2,
BUS = 3,
MOTORCYCLE = 4
}
// список со строковыми значениями
enum VehicleType3{
SUV = 'SUV',
SEDAN = 'SEDAN',
TRUCK = 'TRUCK',
BUS = 'BUS',
MOTORCYCLE = 'MOTORCYCLE'
}
->
"use strict";
// перечисляемый тип
var VehicleType1;
(function (VehicleType1) {
VehicleType1[VehicleType1["SUV"] = 0] = "SUV";
VehicleType1[VehicleType1["SEDAN"] = 1] = "SEDAN";
VehicleType1[VehicleType1["TRUCK"] = 2] = "TRUCK";
VehicleType1[VehicleType1["BUS"] = 3] = "BUS";
VehicleType1[VehicleType1["MOTORCYCLE"] = 4] = "MOTORCYCLE";
})(VehicleType1 || (VehicleType1 = {}));
// эквивалентный тип
var VehicleType2;
(function (VehicleType2) {
VehicleType2[VehicleType2["SUV"] = 0] = "SUV";
VehicleType2[VehicleType2["SEDAN"] = 1] = "SEDAN";
VehicleType2[VehicleType2["TRUCK"] = 2] = "TRUCK";
VehicleType2[VehicleType2["BUS"] = 3] = "BUS";
VehicleType2[VehicleType2["MOTORCYCLE"] = 4] = "MOTORCYCLE";
})(VehicleType2 || (VehicleType2 = {}));
// тип со строковыми значениями
var VehicleType3;
(function (VehicleType3) {
VehicleType3["SUV"] = "SUV";
VehicleType3["SEDAN"] = "SEDAN";
VehicleType3["TRUCK"] = "TRUCK";
VehicleType3["BUS"] = "BUS";
VehicleType3["MOTORCYCLE"] = "MOTORCYCLE";
})(VehicleType3 || (VehicleType3 = {}));
Первый тип мы описали без инициализирующих значений, его значения инициализируются автоматически, в зависимости от порядка, поэтому порядок значений менять опасно!
Это также накладывает ограничение, что мы не можем использовать тип с проинициализированными значениями и без:
enum VehicleType {
SUV = 'SUV',
SEDAN = 'SEDAN',
TRUCK = 'TRUCK',
BUS = 'BUS',
MOTORCYCLE
}
Выведет ошибку error TS1061: Enum member must have initializer.
Вам придется описать тип так:
enum VehicleType {
SUV = 'SUV',
SEDAN = 'SEDAN',
TRUCK = 'TRUCK',
BUS = 'BUS',
MOTORCYCLE = 0,
}
Тут вы можете создавать объединения с другими типами значений, отличными от строк:
type VehicleType = 'SUV' | 'SEDAN' | 'TRUCK' | 0 | [];
Это дает вам дополнительную гибкость в определении типов. Однако такая дополнительная гибкость может привести к неожиданному поведению в коде при отсутствии четкого понимания типа переменной, которая может быть строкой, или числом, или массивом объектов и т.д.
Перечисления - это объекты, где каждому ключу свойства может быть автоматически присвоено значение или строка на случай, если мы определим значение вручную. Следовательно, вы можете повторять значения свойств точно так же, как и любой другой объект:
export enum VehicleType {
SUV = 'SUV',
SEDAN = 'SEDAN',
TRUCK = 'TRUCK',
BUS = 'BUS',
MOTORCYCLE = 'MOTORCYCLE'
}
for (const type in VehicleType) {
console.log(type);
}
Object.keys(VehicleType).forEach((key) => {
console.log('key ', key);
})
Попытка сделать что-то подобное с union types приведет к ошибке при попытке выполнения кода
type VehicleType = 'SUV' | 'SEDAN' | 'TRUCK' | 'BUS' | 'MOTORCYCLE';
for (const type in VehicleType) {
// my logic in here
console.log(type);
}
Object.keys(VehicleType).forEach((key) => {
console.log('key ', key);
})
error TS2693: 'VehicleType' only refers to a type, but is being used as a value here.
Если вам нужно будет выполнять итерации по набору значений, лучше всего использовать enums
, но вы тем самым пожертвуете размером собранного кода.
С того момента, как я начал изучать React, он показался глотком свежего воздуха в мире фронтенда.
Я могу создавать красивые пользовательские интерфейсы только с помощью JavaScript? Внезапно у меня появилась мощь JavaScript внутри HTML и CSS?
Мне очень понравилось. Все было прекрасно.
Я пользовался этим инструментом в течение многих лет, но не мог удержаться от наблюдения за ажиотажем вокруг Vue.js Судя по всему, каждый разработчик, который его использует, очень любит его!
Несколько месяцев назад я запустил Vue в коммерческом проекте и полностью ушел с React.
Но эти фреймворки — всего лишь инструменты; Мы никогда не должны принимать строгие карьерные решения, основываясь на них.
Это фронтенд-мир — все инструменты скоро исчезнут; Новые придут быстро.
Теперь, после огромного опыта во фронтенд-разработке и фреймворках, таких как Angular.js Vue.js, React и Ember.js, позвольте мне объяснить, почему я считаю Vue.js лучшим.
Сегодня мы создаем очень простое приложение как на React, так и на Vue.js. Выглядит это примерно так:
Давайте углубимся в код. Реагируйте, вы на первом месте. Это проект, созданный с помощью ; Здесь я немного видоизменил. create-react-appApp.js
import { useState } from 'react';
function App() {
const [isMagicalAnswerVisible, setIsMagicalAnswerVisible] = useState(false)
return (
<div className="App">
<p className="magicalQuestion">
Which FE framework is the best?
</p>
<button className="magicalButton" onClick={() => setIsMagicalAnswerVisible(true)}>
Find out!
</button>
{isMagicalAnswerVisible && <p className="magicalAnswer">
.....what is life?
</p>}
</div>
);
}
export default App;
Я хорошо знаю React, поэтому могу во всем этом разобраться. Но давайте предположим, что я ничего не знаю о React — только кое-что о разработке в вебе в целом.
Зная это, я хочу знать, что будет отображаться на экране. Когда я смотрю на браузер, я вижу там только стилизованные HTML-элементы. Не JavaScript.
А здесь — все на JavaScript! Как узнать, что на самом деле будет отображаться на экране?
Я вижу, что это возвращает некоторый код, похожий на HTML, но это не HTML. Что это? function App()
Хорошо. Я предполагаю, что эта штука будет рендериться.
Что такое ? Почему я не могу просто использовать class
?
onClick={() => setIsMagicalAnswerVisible(true)}
почему я должен это делать, неужели я не могу просто сделать? О, теперь я получаю некоторые ошибки. Я верну стрелочную функцию, хотя и не знаю почему onClick={setIsMagicalAnswerVisible(true)}
{isMagicalAnswerVisible && <p className=”magicalAnswer”>…..what is life?</p>}
Что это? Что там с фигурными скобками? Что, оператор JS здесь. будет рендерить, если isMagicalAnswerVisible === true
?
Представьте себе огромный компонент. Я хочу видеть то, что я увижу на экране. Но я не могу, потому что мне приходится прокручивать первые 100 строк кода, чтобы найти оператор.return
Я доверяю именованию функций. Я верю, что они делают то, что говорят. Я не хочу сначала вдаваться в детали реализации.
<template>
<p class="magical-question">
Which FE framework is the best?
</p>
<button class="magical-button" @click="findOutMoreAboutThatMagicalFramework">
Find out!
</button>
<p v-if="isMagicalAnswerVisible" class="magical-answer">
.....what is life?
</p>
</template>
<script>
export default {
name: 'App',
data() {
return {
isMagicalAnswerVisible: false
}
},
methods: {
findOutMoreAboutThatMagicalFramework() {
this.isMagicalAnswerVisible = true
}
}
}
</script>
Хм, что я здесь вижу? Ох уж этот шаблон! Думаю, я увижу этот шаблон на экране.
О, хорошо, здесь. Это HTML-файл? class
Хм, вот , а также . Поначалу это звучит немного странно, но на самом деле даже для разрабочкика с небольшим опытом это должно быть очевидно @click
, v-if
И это так просто.
data()
; Что это? Мне нужно будет погуглить. О, это просто состояние компонента.
methods
? Довольно просто.
Я точно вижу, что будет рендериться первым. Я вижу что-то, похожее на HTML.
Я хочу стилизовать свой компонент. Что мне нужно сделать? Я предполагаю, что это то же самое, что и в HTML; Я просто добавлю тег в нижнюю часть файла.
И это работает!
Кривая обучения React может быть огромной, особенно если вы имеете дело с более сложными вещами. Помните времена, когда еще не было Хуков? Так много Render Props, Higher-Order Components и куча других вещей.
Как насчет этого? Я знаю очень многих React-разработчиков, которые понятия не имеют, что происходит за кулисами.this.handleClick = this.handleClick.bind(this)
С другой стороны, с Vue.js все так просто. Это похоже на обновленную версию HTML.
Я так много работал с Vue.js за последние пару месяцев, и количество разочарований минимально.
Я могу сосредоточиться только на реальной проблеме, а не на фактической реализации.
Я все время задаюсь вопросом — как такое возможно? Я усвоил основные знания за 2 недели, и теперь могу построить почти все?
С React все было по-другому. Временами это было очень неприятно. Но я все равно любил его просто потому, что это JavaScript.
Веб состоит из HTML, CSS и JavaScript. Если мы хотим иметь глубокое понимание этого, мы не должны путать себя с утверждением, что все является JavaScript.
С Vue.js у меня есть ощущение, что я получаю гораздо больше общих знаний, связанных с вебом, а не только с Vue.
С React все было наоборот. Вам нужно сломать свое глубокое понимание Интернета, чтобы принять этот образ мышления.
Проблема в том, что веб останется, а React исчезнет. Это не язык программирования, а просто библиотека.
Vue работает как веб. Это набор компонентов, похожих на HTML, генерирующих события, как настоящий Интернет
Да, вы не передаете функцию в качестве входного параметра. Вы перехватываете всплывшее событие, созданное дочерним компонентом.
Так же, как и в реальной сети.
Хорошо, возможно!
Тем не менее, я по-прежнему могу назвать React хорошей технологией, которая продвинула веб разработку на новый уровень. Несмотря на то, что я не согласен с тем, что веб работает только на JavaScript.
Но у меня есть ощущение, что я могу лучше изучить основы с Vue, а также я могу сосредоточиться на реальной бизнес-проблеме, а не на реализации.
Независимо от того, являетесь ли вы новичком во Vue или хотите усовершенствовать свои навыки, в этом руководстве рассматриваются основные техники от базового до продвинутого, все с использованием Composition API. Давайте начнем!
Прежде чем мы перейдем к методам оптимизации, давайте разберемся, почему производительность имеет значение. Быстрое, отзывчивое приложение обеспечивает лучший пользовательский опыт, улучшает рейтинг SEO и может повысить вовлеченность и удержание пользователей.
Использование маршрутизатора для отложенной загрузки компонентов:
const routes = [
{
path: '/about',
component: () => import('./components/About.vue')
}
]
С помощью Composition API можно динамически импортировать компоненты в функции установки:
import { defineAsyncComponent } from 'vue'
export default {
setup() {
const About = defineAsyncComponent(() => import('./components/About.vue'))
return { About }
}
}
Этот метод гарантирует, что компонент загружается только тогда, когда пользователь переходит к маршруту ‘/about’, тем самым уменьшая начальный размер пакета и сокращая время загрузки About
Несмотря на то, что и те, и другие управляют видимостью элементов, они делают это по-разному. v-if
добавляет или удаляет элементы из модели DOM, что требует большей производительности. В отличие от этого, v-show
просто переключает свойство CSS, что делает его более эффективным для элементов, которые необходимо часто переключать.
<template>
<div>
<button @click="show = !show">Toggle</button>
<div v-show="show">This is a toggled element</div>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const show = ref(false)
return { show }
}
}
</script>
В этом примере он более эффективен, так как позволяет избежать ненужных манипуляций с DOM, тем самым повышая производительность при частом переключении видимости элементов. v-show
При обработке пользовательских входных данных, таких как поисковые запросы или отправка форм, важно отключать или регулировать события, чтобы избежать проблем с производительностью. Debounce откладывает выполнение функции до тех пор, пока не пройдет указанное время с момента ее последнего вызова. Throttle гарантирует, что функция будет выполняться только один раз за указанный интервал.
import { ref } from 'vue'
import debounce from 'lodash/debounce'
export default {
setup() {
const query = ref('')
const search = debounce((value) => {
// Perform search operation
console.log(value)
}, 300)
return { query, search }
}
}
В этом примере функция будет выполняться только через 300 миллисекунд после того, как пользователь перестанет вводить текст, что уменьшит количество вызовов API и повысит производительность search
Реактивные ссылки могут стать узким местом производительности при чрезмерном использовании. Используйте их разумно и отдавайте предпочтение вычисляемым свойствам для производного состояния. Это помогает избежать ненужной реакции и обеспечивает производительность приложения.
import { ref, computed } from 'vue'
export default {
setup() {
const items = ref([1, 2, 3, 4, 5])
const evenItems = computed(() => items.value.filter(item => item % 2 === 0))
return { items, evenItems }
}
}
В этом примере это вычисляемое свойство, которое автоматически обновляется при изменениях, но само по себе не является реактивным, что помогает поддерживать производительность.evenItemsitems
Для рендеринга больших списков используйте виртуальную прокрутку, чтобы отобразить только видимые элементы, что значительно повышает производительность. Виртуальная прокрутка особенно полезна при работе с длинными списками или таблицами, где отображение всех элементов одновременно было бы неэффективным.
<template>
<virtual-list :size="50" :remain="10" :items="items">
<template v-slot="{ item }">
<div class="item">{{ item }}</div>
</template>
</virtual-list>
</template>
<script>
import { ref } from 'vue'
import VirtualList from 'vue-virtual-scroll-list'
export default {
components: { VirtualList },
setup() {
const items = ref([...Array(1000).keys()])
return { items }
}
}
</script>
В этом примере отображаются только видимые элементы, что снижает нагрузку на DOM и повышает производительность.
Используйте такие инструменты, как Webpack, чтобы разбить код на более мелкие пакеты, загружая только то, что необходимо. Это особенно полезно для больших приложений, так как позволяет браузеру изначально загружать только основные части приложения и откладывать загрузку других частей до тех пор, пока они не понадобятся.
Настройте Webpack для разделения кода:
// webpack.config.js
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
},
},
}
Эта конфигурация указывает Webpack разделить код на более мелкие фрагменты, которые могут быть загружены по требованию.
Регулярно отслеживайте производительность вашего приложения с помощью таких инструментов, как Vue Devtools, Lighthouse и Webpack Bundle Analyzer. Эти инструменты помогают выявить узкие места и области, требующие улучшения.
Оптимизация производительности приложений Vue.js включает в себя сочетание простых и продвинутых методов. Начните с базовых оптимизаций, таких как отложенная загрузка и эффективное использование директив, а затем переходите к промежуточным стратегиям, таким как устранение дребезга и реактивные ссылки. Наконец, реализуйте расширенные методы, такие как виртуальная прокрутка и разделение кода для достижения наилучшей производительности.