Как сохранить scroll position vue?

255
29 сентября 2018, 06:10

Всем привет. К примеру есть страницы page1 и page2. На странице page1 есть ссылка которая введет на страницу page2, она находится на расстояние 1000px от топа. А на странице page2 есть кнопка, которая возвращает пользователя на страницу page1. Как после того как мы нажимаем на кнопку на странице page2 для перехода на страницу page1 вернуть нас на то же самое расстояние от топа?

Читал про функцию scrollBehavior, но откуда vue будет знать, откуда и на какой странице сохранять scroll position?

Answer 1

Так как у Вас на page1 данные приходят с сервера и рендерятся каждый раз в v-for, то очевидно, что scroll position запоминаться не будет. Могу предложить Вам такой метод решения данной проблемы - создать сервис, который будет кешировать эти данные, чтобы каждый раз, переходя на page1, не обращаться к БД, он должен быть синглтоном:

// cache.service.js
export class CacheService {
    constructor() {
        this.cache = {};
    }
    mutateCache(key, value) {
        this.cache = {
            ...this.cache,
            [key]: value
        };
    }
    getCache() {
        return this.cache;
    }
}

Создаем "псевдо dependency injection", то есть инжектор, который будет инициализировать нужные нам сервисы только при первом доступе, эдакой lazy map:

// di.js
import { CacheService } from './cache.service';
const injector = new WeakMap();
injector.set(CacheService, {
    value: null,
    factory: () => new CacheService()
});
export function getDependency(ctor) {
    const entry = injector.get(ctor);
    if (entry.factory) {
        const factory = entry.factory;
        entry.factory = null;
        entry.value = factory();
    }
    return entry.value;
}

В компоненте page1 нам достаточно 1 раз получить данные с сервера и закешировать их:

<script>
import { getDependency } from './path-to/di.js';
import { CacheService } from './path-to/cache-service.js';
export default {
    data() {
        return {
            someData: []
        };
    },
    mounted() {
        const service = getDependency(CacheService);
        const cache = service.getCache();
        if (!cache.someData) {
            makeSomeApiCall().then((someData) => {
                this.$data.someData = someData;
                service.mutateCache('someData', this.$data.someData);
            });
        } else {
            this.$data.someData = cache.someData;
        }
    }
};
</script>

Вариант с использованием vuex:

yarn add vue@3.0.1

Создаем папку store и подключаем плагин:

// store/index.js
import Vuex, { Store } from 'vuex';
Vue.use(Vuex);
export const store = new Store({
    state: {
        someData: []
    },
    mutations: {
        setData(state, { someData }) {
            state.someData = someData;
        }
    }
});

Передаем store параметром в конструктор Vue при создании приложения:

import { store } from './path-to/store';
new Vue({
    ...,
    ...,
    store,
    render: (h) => ....
}).$mount('#app');

Теперь можем напрямую использовать в компоненте через свойство $store:

<template>
    <div class="page-1">
        <div v-for="data in someData">{{ data }}</div>
    </div>
</template>
<script>
import { store } from './path-to/store';
export default {
    computed: {
        someData: () => this.$store.state.someData
    },
    mounted() {
        if (this.$store.state.someData.length > 0) {
            return;
        }
        makeSomeApiCall().then((someData) => {
            this.$store.commit('setData', { someData });
        });
    }
};
</script>
READ ALSO
Все комбинации элементов массивов

Все комбинации элементов массивов

Мне нужно получить всевозможные комбинации элементов массивовНапример, есть массив а(1,2,3), б(4,5,6), с(7,8)

299
Принцип работы Array.prototype.concat()

Принцип работы Array.prototype.concat()

Для скрипта в Adobe Photoshop, есть диалоговое окно с элементами выбора и управления:

349
Сокращение объема кода по работе с табами (скрытие/отображение)

Сокращение объема кода по работе с табами (скрытие/отображение)

Есть табы, которые скрыты, при клике по элементу с нужным атрибутом, таб появляетсяКак такой код, можно сократить? Причём, чем короче получится,...

258