Оптимизация производительности приложений Vue.js — забота каждого фронтенд-разработчика.
В этой статье я поделюсь 10 советами по оптимизации Vue.js, которые вам нужно знать начинающему или опытному пользователю интерфейса. Я надеюсь, что эти советы помогут вам, изучаете ли вы Vue.js или уже используете его в разработке приложений.
1. Установите key
в v-for
🔗 Ссылка на документ: https://vuejs.org/api/built-in-directives.html#v-for
Использование key
в v-for
очень важно, поскольку позволяет Vue лучше отслеживать состояние и позицию каждого элемента.
Когда порядок элементов изменяется, отсутствие key
приводит к снижению производительности, поскольку Vue необходимо повторно сгенерировать элементы. Чтобы корректно установить key
, вы можете извлечь уникальный атрибут из данных в качестве значения ключа. Вот пример кода:
<template v-for="(item, index) in items" :key="item.id"> <div>{{ item.title }}</div> </template>
Если нет такого уникального свойства, как item.id
, рассмотрите возможность использования index
в качестве значения key
.
Обратите внимание, что вы не должны использовать index
в качестве значения key
, когда вам нужно добавить или удалить данные, так как это может вызвать исключения для данных страницы.
2. Правильно используйте v-if
и v-show
🔗 Ссылка на документ: https://vuejs.org/guide/essentials/conditional.html#v-if-vs-v-show
И v-if
, и v-show
могут управлять отображением и скрытием элементов, но они используются в разных сценариях.
v-if
подходит для сценариев, где требуется частое переключение, когда прослушиватели событий и дочерние компоненты внутри компонента уничтожаются и перестраиваются;v-show
используется в сценариях, где не требуется частое переключение, и отображается независимо от начальных условий, за исключением того, что свойство CSSdisplay
управляющего элемента определяет, отображается он или нет;
В целом, v-if
имеет более высокие накладные расходы на переключение, а v-show
имеет более высокие начальные накладные расходы на рендеринг. Поэтому, если требуется частое переключение, предпочтительнее v-show
; если условия привязки редко меняются во время выполнения, более подходящим является v-if
. Вот пример кода:
<!-- Use v-if --> <template v-if="show"> <div>{{ message }}</div> </template> <!-- Use v-show --> <template> <div v-show="show">{{ message }}</div> </template>
3. Используйте KeepAlive для кэширования состояния компонента по мере необходимости.
🔗 Ссылка на документ: https://vuejs.org/guide/built-ins/keep-alive.html#keepalive
KeepAlive
— это встроенный компонент, который кэширует состояние компонентов, чтобы избежать дублирования рендеринга и повысить скорость отклика страницы. Кэширует удаленные экземпляры компонентов при динамическом переключении между несколькими компонентами.
Однако, если KeepAlive
используется неправильно, это может привести к утечке памяти и другим проблемам. Поэтому при использовании KeepAlive
нужно знать сценарии его использования и своевременно уничтожать кешированные компоненты. Вот пример кода:
<template> <keep-alive> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> </template>
Кроме того, KeepAlive
также поддерживает настройку maximum number of cached instances
для ограничения максимального количества экземпляров компонентов, которые можно кэшировать. Если количество кэшированных экземпляров вот-вот превысит указанное максимальное число, кэшированные экземпляры, к которым не было доступа в течение длительного времени, будут уничтожены, чтобы освободить место для новых экземпляров.
Вот пример кода:
<KeepAlive :max="10"> <component :is="activeComponent" /> </KeepAlive>
4. Своевременное уничтожение событий
🔗 Ссылка на документ: https://vuejs.org/api/composition-api-lifecycle.html#onbeforeunmount
Компоненты, использующие прослушиватели событий, таймеры и асинхронные операции, необходимо вовремя уничтожать, чтобы предотвратить утечку памяти.
В Vue3 предусмотрена функция setup
, и вы можете использовать хук onBeforeUnmount
для уничтожения событий и других ресурсов. Вот пример кода:
import { onBeforeUnmount } from "vue"; export default { setup() { let timer; const startTimer = () => { timer = setInterval(() => { console.log("timer is running"); }, 1000); }; const stopTimer = () => { clearInterval(timer); }; onBeforeUnmount(() => { stopTimer(); }); return { startTimer, stopTimer, }; }, };
5. Обратите внимание на оптимизацию объема
Vue3 относительно большой и нуждается в оптимизации по размеру. Этого можно добиться, настроив инструмент упаковки так, чтобы он упаковывал только необходимые модули, добавляя сторонние библиотеки по запросу и т. д.
В качестве альтернативы вы можете использовать инструменты оптимизации на основе Tree Shaking, такие как PurgeCSS, Babel Minify и UglifyJS, для дальнейшего сжатия кода. Вот пример кода:
// vue.config.js module.exports = { configureWebpack: { optimization: { splitChunks: { chunks: "all", minSize: 20000, maxSize: 0, minChunks: 1, maxAsyncRequests: 30, maxInitialRequests: 30, automaticNameDelimiter: "~", cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, }, }, };
6. Использование EventBus для разделения бизнеса
EventBus обеспечивает связь между компонентами и отделяет их друг от друга. Вы также можете использовать инструменты глобального управления состоянием, такие как Vuex, для достижения этой цели.
При использовании EventBus необходимо обращать внимание на присвоение имен событиям и стараться избегать прослушивания одного и того же события несколькими компонентами. Вот пример кода:
// event-bus.js import mitt from "mitt"; export const eventBus = mitt(); // component.js export default { mounted() { eventBus.on("foo", this.handleFoo); }, methods: { handleFoo() { // do something }, }, beforeUnmount() { eventBus.off("foo", this.handleFoo); }, }; // other-component.js export default { mouted() { eventBus.emit("foo"); }, };
7. Использование динамических компонентов для решения проблемы перегрузки if-else
Когда логика if-else
слишком сложна, для ее реализации можно использовать динамические компоненты, чтобы избежать раздувания кода и ухудшения читабельности. Использование динамических компонентов может сделать код более четко организованным, повторно использовать компоненты и избежать избыточности кода. Вот пример кода:
<template> <component :is="componentName"></component> </template> <script> import Foo from "./Foo.vue"; import Bar from "./Bar.vue"; export default { data() { return { componentName: "", }; }, mounted() { if (condition) { this.componentName = "Foo"; } else { this.componentName = "Bar"; } }, components: { Foo, Bar, }, }; </script>
8. Отложенная загрузка с асинхронными компонентами
🔗 Ссылка на документ: https://vuejs.org/guide/components/async.html#async-components
Асинхронные компоненты обеспечивают отложенную загрузку, сокращение времени загрузки компонентов и повышение скорости отклика страницы. Vue3 изначально поддерживает асинхронную загрузку компонентов, чего можно добиться с помощью синтаксиса import()
. Примеры кода следующие:
import { defineAsyncComponent } from "vue"; const AsyncComp = defineAsyncComponent(() => import("./Foo.vue"));
9. Сокращение вычислений с использованием computed
и watch
🔗 Ссылка на документ: https://vuejs.org/api/reactivity-core.html
Использование computed
и watch
может уменьшить избыточную визуализацию или повторяющиеся вычисления.
computed
может кэшировать результаты вычислений, чтобы при изменении ответных данных заново вычислялись только зависимые данные. watch
может прослушивать изменения в одном или нескольких реагирующих источниках данных и выполнять соответствующие действия, чтобы избежать ручного прослушивания изменений данных.
Ниже приведен пример кода:
<template> <div>{{ fullName }}</div> </template> <script> export default { data() { return { firstName: "John", lastName: "Doe", }; }, computed: { fullName() { return this.firstName + " " + this.lastName; }, }, watch: { firstName(newValue, oldValue) { console.log("firstName", newValue, oldValue); }, lastName(newValue, oldValue) { console.log("lastName", newValue, oldValue); }, }, }; </script>
10. Оптимизация слотов прицела с помощью v-slot
🔗 Ссылка на документ: https://vuejs.org/api/built-in-directives.html#v-slot
Слот области (также известный как именованный слот) может передавать данные от родительского компонента к дочернему компоненту и отображать дочерний компонент. Однако, когда в слотах области видимости слишком много контента, это может затруднить сопровождение кода. Следовательно, синтаксис v-slot
(называемый slot-scope
в Vue2) можно использовать для оптимизации слотов области действия.
v-slot
позволяет определить имя слота области действия в шаблоне, что делает код более явным и легким для чтения. Ниже приведен пример кода:
<!-- In Vue 3 --> <template> <my-component> <template v-slot:title="{ name }"> {{ name }}'s Title </template> </my-component> </template> <!-- In Vue 2 --> <my-component> <template slot-scope="{ name }"> {{ name }}'s Title </template> </my-component>
Используя v-slot
, мы можем указать имя и содержимое слотов областей в шаблоне и избежать путаницы компонентов.
Краткое содержание
Мы надеемся, что 10 советов по оптимизации, представленных в этой статье, помогут читателям лучше понять Vue.js и создавать более эффективные и надежные веб-приложения.