Мемоизация — это техника оптимизации, при которой результаты вычислений сохраняются для последующего использования, что предотвращает повторное выполнение ресурсоёмких операций. В контексте Quasar Framework и Vue.js мемоизация особенно полезна при работе с вычисляемыми свойствами, сложными фильтрами и компонентами, зависящими от больших массивов данных.
В Vue 3, на котором базируется Quasar, мемоизация
реализуется через computed и
watchEffect, а также с помощью сторонних
утилит, таких как lodash.memoize. Главная
цель — хранить результаты функций и возвращать их при одинаковых входных
данных, минимизируя нагрузку на реактивную систему.
В Quasar вычисляемые свойства (computed) автоматически
кэшируют результат до тех пор, пока не изменятся их зависимости:
import { ref, computed } from 'vue';
const numbers = ref([1, 2, 3, 4, 5]);
const sum = computed(() => {
console.log('Вычисляем сумму');
return numbers.value.reduce((acc, val) => acc + val, 0);
});
В этом примере, даже если к sum обращаются несколько раз
в шаблоне, функция reduce выполняется только тогда, когда
изменяется numbers.value. Ключевой момент:
реактивная зависимость определяет, когда кэш нужно сбросить.
lodash.memoizeДля функций, которые не являются вычисляемыми свойствами, мемоизацию
можно реализовать через
lodash.memoize:
import memoize from 'lodash.memoize';
const heavyCalculation = (num) => {
console.log('Выполняем тяжёлое вычисление');
return num * 2;
};
const memoizedCalculation = memoize(heavyCalculation);
console.log(memoizedCalculation(5)); // Выполняется функция
console.log(memoizedCalculation(5)); // Берётся из кэша
Такой подход эффективен при сложных вычислениях, которые вызываются многократно с одними и теми же аргументами. Важно помнить, что кэш хранится в памяти до очистки или перезапуска приложения.
Компоненты Quasar, например QTable,
часто обрабатывают большие массивы данных. Мемоизация функций
сортировки, фильтрации и пагинации позволяет избежать лишнего пересчёта
при каждом рендере:
import { computed, ref } from 'vue';
import memoize from 'lodash.memoize';
const items = ref([
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 },
]);
const filterByAge = memoize((age) => {
console.log('Фильтруем по возрасту');
return items.value.filter(item => item.age >= age);
});
const filteredItems = computed(() => filterByAge(28));
Здесь функция filterByAge выполняется один раз для
каждого уникального значения age. При повторном
использовании того же аргумента результат берётся из кэша.
При работе с реактивными объектами и массивами следует учитывать, что мемоизация по ссылке может не сработать, если объект изменился. В таких случаях используют глубокое клонирование или сериализацию аргументов:
const deepMemoize = (fn) => {
const cache = new Map();
return (arg) => {
const key = JSON.stringify(arg);
if (cache.has(key)) return cache.get(key);
const result = fn(arg);
cache.set(key, result);
return result;
};
};
const processData = deepMemoize((data) => data.map(x => x * 2));
Это гарантирует, что результат будет корректно кэшироваться даже при изменении вложенных свойств объектов.
Для асинхронных функций мемоизация требует отдельного подхода, так как возвращается промис:
import memoize from 'lodash.memoize';
const fetchData = async (id) => {
const response = await fetch(`/api/data/${id}`);
return response.json();
};
const memoizedFetch = memoize(async (id) => fetchData(id));
memoizedFetch(1).then(data => console.log(data));
memoizedFetch(1).then(data => console.log(data)); // Берётся из кэша
Важно: кэш хранит промис, а не его результат, что предотвращает повторные запросы при одновременных вызовах.
Мемоизация в Quasar сочетает возможности Vue 3 реактивности и стандартные методы кэширования, создавая гибкую систему оптимизации вычислений. Ее правильное использование значительно повышает производительность приложений без снижения читаемости кода.