Реф, который сам сохраняется
Для сохранения в localStorage всегда нужны одни и те же строки: прочитать сохранённое при создании рефа и сохранять его с помощью watch при каждом изменении. С композаблом вы напишете их только один раз:
import { ref, watch } from "vue";
export function useLocalStorage(key, initial) {
const saved = localStorage.getItem(key);
const value = ref(saved === null ? initial : JSON.parse(saved));
watch(
value,
(newValue) => {
localStorage.setItem(key, JSON.stringify(newValue));
},
{ deep: true },
);
return value;
}Тогда каждому значению, которое должно сохраняться, хватит одной строки:
const name = useLocalStorage("name", "");
const order = useLocalStorage("order", []);Как это работает:
- У композабла два параметра:
key— имя, под которым он сохраняет, иinitial— значение, с которого нужно начать, пока ничего не сохранено. Благодаря им одна и та же функция сохраняет имя под ключом"name", а заказ — под ключом"order". - Он возвращает один реф, а не объект, поэтому разбирать нечего: после
const name = useLocalStorage("name", "");переменнаяname— это реф, готовый к использованию вv-modelили{{ name }}. watchвнутри принадлежит вызову: каждый вызов следит за своим рефом и сохраняет его под своим ключом.{ deep: true }нужен для того, чтобы сохранялся иpush()в массив, как вы знаете из урока «Вычисляемые значения и наблюдатели».JSON.stringify()иJSON.parse()работают с текстом, с числами, а также сtrueиfalse, так что композабл может сохранить что угодно.
Компонент ничего этого не видит. Он работает с name и order, как с любым другим рефом, а они сохраняются сами.
Задание
- 1
В
useLocalStorage.jsнапишитеuseLocalStorage(key, initial), как показано выше. ВApp.vueимпортируйте его и используйте для имени:const name = useLocalStorage("name", "");. Проверьте: введите своё имя и нажмите «Запустить». Имя останется на месте. - 2
Используйте его и для заказа, с ключом
orderи пустым массивом в качестве начального значения. Закажите что-нибудь и нажмите «Запустить»: заказ останется. А кнопкаОчистить заказочистит его насовсем.