keep-alive + vuex делают кешированные страницы гибкими

Vue.js

представлять

При использовании vue + vue-router для разработки SPA вы когда-нибудь сталкивались с такой ситуацией: когда мы переключаемся между страницей списка и страницей сведений, если страница списка не кэшируется, это будет вызывать каждый раз возврат со страницы сведений , страница со списком перезагрузится. Как показано ниже:

Внимательные друзья обнаружили, что при возврате на страницу списка со страницы сведений страница списка перегружается, и это явно нехорошо.В это время мы можем кэшировать страницу списка.

keep-alive реализует кэширование страниц

Не все страницы в нашем проекте нужно кэшировать, поэтому вот два метода кэширования по требованию:

метод первый:

Во-первых, настройте метаполе при определении маршрута и настройте поле KeepAlive в качестве маркера того, кэшируется ли страница:

routes:[{
    path: '/search',
    name: 'search',
    component: search,
    meta: {
        title: '搜索列表页',
        keepAlive: true // 标记列表页需要被缓存
    }
},
{
    path: '/detail',
    name: 'detail',
    component: detail,
    meta: {
        title: '详情页',
        // 详情页不需要做缓存,所以不加keepAlive标记
    }
}]

из-за<keep-alive>Компоненты не поддерживают директивы v-if, поэтому мы используем две в App.vue.<router-view>Способ записи через поле keepAlive текущего маршрута, чтобы определить, кэшировать ли страницу:

<div id="app">
    <keep-alive>
        <router-view v-if="$route.meta.keepAlive" />
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive" />
</div>

Метод два

использовать<keep-alive>который предоставилexcludeилиincludeвариант, здесь мы используемexclude, в App.vue:

<div id="app">
    <keep-alive exclude="detail">
        <router-view />
    </keep-alive>
</div>

Следует отметить, что вы должны добавить к компоненту страницы соответствующее имя, например, в detail.vue:

<script>
export default {
    name: 'detail', // 这个name要和keep-alive中的exclude选项值一致
    ...
}
</script>

Это означает, что все страницы в проекте будут кэшироваться, кроме компонента страницы, имя которого — detail.

Оптимизация особого случая:

Если страница сведений также сделалаkeep-alive, то при переключении страницы списка и страницы сведений положение прокрутки может влиять друг на друга.Routerпредоставить экземплярscrollBehaviorметод:

export default new Router({
    scrollBehavior (to, from, savedPosition) {
    	if (savedPosition) {
    		return savedPosition
    	} else {
    		return { x: 0, y: 0 }
    	}
    },
    routes: [...],
})

Показать результаты

Эффект вроде бы очень хороший, и кеширование страницы списка реализовано. Но на самом деле это не гибко, например, когда вы возвращаетесь на домашнюю страницу, а затем входите на страницу поиска, поскольку никакой обработки не было сделано, страница поиска все еще находится в предыдущем состоянии:

Тем не менее, я надеюсь, что всякий раз, когда я захожу на страницу поиска с главной страницы, данные страницы должны быть сброшены обратно в исходное состояние.Есть ли какой-либо способ гибко контролировать, нужно ли сбрасывать данные страницы? В этот раз мне на ум пришла библиотека управления состоянием в экосистеме vue.vuex.

Сделайте страницы более гибкими с помощью vuex

анализ спроса:Нам нужен глобальный флаг, чтобы контролировать, нужно ли сбрасывать данные каждый раз, когда вводится страница кеша, простоvuexможет сделать это.

vex вверх

Установить

npm install vuex --save

настроить vuex

Чтобы облегчить дальнейшее обслуживание, можно создать каталог хранилища для хранения кода модуля vuex Структура каталога относится к следующему рисунку:

state.js:

const state = {
    refreshSearch: true // 标记是否刷新搜索页
}

export default state

mutation.js

const matutaions = {
    setRefreshSearch(state, flag) {
        state.refreshSearch = flag
    }
}
  
export default matutaions

index.js

import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'

Vue.use(Vuex)

export default new Vuex.Store({
    state,
    mutations
})

В файле ввода main.js:

import store from './store' //这里是指向store目录中的index.js
new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app')

Таким образом, мы эквивалентны созданию тега с vuex, чтобы определить, нужно ли сбрасывать страницу.

Произвольно сбросить данные на вашей кешированной странице

где сбросить

keep-aliveКомпонент имеет уникальный хук жизненного циклаactivated().activated()Будет вkeep-aliveвызывается каждый раз при активации компонента, аcreated()Он будет вызываться только один раз при создании и не будет вызываться при повторной активации. Так что здесь нам нужноactivated()Hook для сброса данных нашей страницы.

Сброс, если вы хотите сбросить в активированном ()

здесь, чтобы использоватьvuexсерединаrefreshSearchфлаг, чтобы определить, требуется ли сброс

search.vue: (это страница, которую необходимо кэшировать)

<script>
import {mapState, mapMutations} from 'vuex' //vuex提供的映射函数,用来简化代码的
export default {
    activated() {
        if (this.refreshSearch) {
            // 若为true,则执行重置页面等相关操作
            this.fetchData();
        } else {
            this.reset(true);
        }
    },
    methods:{
        fetchData() {
            // 获取页面数据
        },
        ...mapMutations({
            reset: 'setRefreshSearch' // 将 `this.reset()` 映射为 `this.$store.commit('setRefreshSearch')`
        })
    },
    computed: {
        ...mapState([
            'refreshSearch' // 映射 this.refreshSearch 为 this.$store.state.refreshSearch
        ]),
    }
}
</script>

Когда мы переходим со страницы поиска на страницу сведений, мы хотим, чтобы страница поиска кэшировалась, просто установите флаг в значение false:

methods: {
    goDetail() {
        this.reset(false) // 这样返回搜索页的时候,搜索页就不会重置数据了
        this.$router.push({path: '/detail'})
    },
    ...mapMutations({
        reset: 'setRefreshSearch'
    })
}

Когда мы переходим на страницу поиска с домашней страницы, мы хотим, чтобы данные страницы поиска сбрасывались, просто установите флаг в значение true:

methods: {
    goSearch() {
        this.reset(true) // 这样去搜索页时数据就会被重置了
        this.$router.push({path: '/search'})
    },
    ...mapMutations({
        reset: 'setRefreshSearch'
    })
}

Предварительный просмотр эффекта

Суммировать

В этой статье описывается использование по запросуkeep-alive, а с помощьюvuexконтролироватьkeep-aliveНужно ли сбрасывать и обновлять данные страницы компонента, надеюсь, это вам поможет.

Прикрепленный связанный портал знаний:
поддержка встроенного компонента vue

поведение прокрутки vue-router

Крюк жизненного цикла активирован

библиотека управления состоянием vuex