面试官:如何实现在浏览商品时,进入详情,再返回,列表刷新,滚动条还在之前的位置?

哈喽,大家好,今天的文章有uncle13提供。

有这样一个场景题:

在浏览商品时,点击商品详情,然后返回,要求列表刷新,同时滚动条还在之前的位置,怎么实现?

一、基本方法

思路:

  1. 在点击商品详情进入商品详情页之前,记录当前滚动条的位置。
  2. 当从商品详情页返回列表页时,触发列表的刷新操作。
  3. 在列表刷新完成后,将之前记录的滚动条位置重新设置回去。
// 记录当前滚动条位置
var scrollPosition = window.scrollY;
// 点击商品详情进入详情页的操作
function gotoProductDetails(productId{
  // 保存当前滚动条位置
  sessionStorage.setItem('scrollPosition', scrollPosition);
  // 其他跳转逻辑...
}

// 从商品详情页返回列表页的操作
function goBackToList({
  // 触发列表刷新操作
  refreshList();
  // 恢复之前的滚动条位置
  var savedScrollPosition = sessionStorage.getItem('scrollPosition');
  window.scrollTo(0, savedScrollPosition);
}

// 列表刷新操作
function refreshList({
  // 刷新列表的逻辑...
}

使用sessionStorage来存储和恢复滚动条位置。当用户点击商品详情时,我们记录当前的滚动条位置,然后在返回列表页时,首先触发列表的刷新操作,然后再将之前记录的滚动条位置重新设置回去。

二、Vue框架实现

在Vue框架中实现这个功能可以使用Vue Router和VueX技术。

  1. 首先,你需要在Vue项目中使用Vue Router进行路由管理。确保你有正确设置了商品详情页和列表页的路由。

  2. 在进入商品详情页之前,你可以使用VueX来存储当前滚动条位置。

// main.js

import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';

new Vue({
  router,
  store,
  renderh => h(App)
}).$mount('#app');
  1. 当从商品详情页返回列表页时,你可以触发列表的刷新操作,并使用VueX来获取之前存储的滚动条位置并将其重新设置回去。
<!-- ProductDetail.vue -->

<template>
<div>
<!-- 商品详情页内容 -->
<button @click="goBack">返回</button>
</div>
</template>

<script>
export default {
methods: {
goBack() {
this.$store.dispatch('saveScrollPosition', window.scrollY);
this.$router.push('/list'); // 返回列表页
}
}
}
</script>
<!-- List.vue -->

<template>
<div>
<!-- 列表页内容 -->
</div>
</template>

<script>
export default {
mounted() {
this.$store.dispatch('restoreScrollPosition');
// 触发列表的刷新操作
// ...
}
}
</script>
  1. 在VueX store 中保存和恢复滚动条位置。
// store/index.js

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    scrollPosition0
  },
  mutations: {
    SET_SCROLL_POSITION(state, position) {
      state.scrollPosition = position;
    }
  },
  actions: {
    saveScrollPosition({ commit }, position) {
      commit('SET_SCROLL_POSITION', position);
    },
    restoreScrollPosition({ state }) {
      window.scrollTo(0, state.scrollPosition);
    }
  }
});

利用Vue Router来管理页面跳转,使用了VueX来存储和恢复滚动条位置。当用户点击商品详情页面时,使用saveScrollPosition action来保存当前滚动条位置,在返回列表页时,再使用restoreScrollPosition action来恢复之前的滚动条位置

三、keep-alive实现

使用Vue框架中的keep-alive组件可以在列表刷新时保持滚动条的位置。

<!-- App.vue -->

<template>
<div id="app">
<router-view v-slot="{ Component }">
<keep-alive :include="['List']">
<component :is="Component" />
</keep-alive>
</router-view>
</div>
</template>

<script>
export default {
name: 'App'
};
</script>
<!-- List.vue -->

<template>
<div>
<!-- 列表页内容 -->
</div>
</template>

<script>
export default {
name: 'List',
beforeRouteLeave (to, from, next) {
const scrollPosition = window.scrollY;
this.$store.commit('SET_SCROLL_POSITION', { component: 'List', position: scrollPosition });
next();
},
updated() {
const scrollPosition = this.$store.state.scrollPositions['List'];
if (scrollPosition !== undefined) {
window.scrollTo(0, scrollPosition);
}
}
};
</script>
// store/index.js

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    scrollPositions: {}
  },
  mutations: {
    SET_SCROLL_POSITION(state, payload) {
      state.scrollPositions[payload.component] = payload.position;
    }
  }
});

使用keep-alive组件包裹了<router-view>,并设置了其中的List组件为缓存组件。当用户离开List页面时,记录当前滚动条位置并将其保存在Vuex store 中。然后,在List组件更新时,检查是否有之前保存的滚动条位置,并将滚动条位置恢复到之前的状态。

四、React实现

在React中,可以使用useEffect钩子和状态来实现在浏览商品时,点击商品详情然后返回时,列表刷新同时滚动条保持在之前的位置。

import React, { useState, useEffect } from 'react';

const ProductList = () => {
  const [scrollPosition, setScrollPosition] = useState(0);

  useEffect(() => {
    const handleScroll = () => {
      setScrollPosition(window.scrollY);
    };

    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  const goToProductDetails = (productId) => {
    // 保存当前滚动条位置
    setScrollPosition(window.scrollY);
    // 其他跳转逻辑...
  };

  return (
    <div>
      {/* 商品列表内容 */}
      <button onClick={() => goToProductDetails(productId)}>查看详情</button>
    </div>

  );
};

const ProductDetails = ({ goBack }) => {
  return (
    <div>
      {/* 商品详情页内容 */}
      <button onClick={goBack}>返回</button>
    </div>

  );
};

const App = () => {
  const [isListRefreshed, setIsListRefreshed] = useState(false);

  const refreshList = () => {
    // 刷新列表的逻辑...
    setIsListRefreshed(true);
  };

  const goBackToList = () => {
    setIsListRefreshed(false);
    // 其他返回逻辑...
  };

  return (
    <div>
      {isListRefreshed ? (
        <ProductList />
      ) : (
        <ProductDetails goBack={goBackToList} />
      )}
    </div>

  );
};

使用useState来存储滚动条位置以及用于控制列表是否已刷新的状态。还使用了useEffect来监听滚动事件,并在离开页面时保存当前滚动位置。当用户点击商品详情时,保存当前的滚动条位置,然后在返回列表页时,触发列表的刷新操作并将滚动条位置设置回之前的位置。


最后

还没有使用过我们刷题网站(https://fe.ecool.fun/)或者刷题小程序的同学,如果近期准备或者正在找工作,千万不要错过,我们的题库主打无广告和更新快哦~。

老规矩,也给我们团队的辅导服务打个广告。