单页应用后退不刷新方案(vue & react)试一下有惊喜

发布时间:2022-07-04 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了单页应用后退不刷新方案(vue & react)试一下有惊喜脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

引言

前进刷新,后退不刷新,是一个类似app页面的特点,要在单页web应用中做后退不刷新,却并非一件易事。

为什么麻烦

spa的渲染原理(以vue为例):url的更改触发onHashChange/pushstate/popState/replaceState,通过url中的pathName去匹配路由中定义的组件,加载进来并实例化渲染在项目的出口router-view中。

换言之,一个实例的解析渲染意味着另外一个实例的销毁,因为渲染出口只有一个。

keep-alive为什么不行?因为keep-alive的原理是将实例化后的组件存储起来,当下次url匹配到了改组件时,优先从存储里面取。

但是vue只提供了入存储的方式,没提供删存储的方式,所以没法实现“前进刷新”。

有一种方案是手动根据to和From去做前进后退判断,这种判断不能应对复杂的跳转逻辑可维护性也很差

有坑的社区方案(以vue为例)

vue-page-stackvue-navigation

这两个方案都有明显缺点:前者不支持嵌套路由,在一些场景下会出现url变化,页面完全无反应的情况,后者存在类似的bug。并且这两种方案侵入性都很强,因为他们都是基于vue-router的魔改。并且会在url中增加无意义的多余字段(stackID)

目前不错的方案

现在有一个可行且简单的方案:嵌套子路由 + 叠页面

叠页面的灵感:原生应用中的webview in webview,多页应用中的window in window

要在spa中实现后退不刷新,本质是要实现多实例共存

这个方案的核心在于:通过嵌套子路由实现多实例共存,通过css的absolute实现视觉上的页面堆叠

上效果图

 

单页应用后退不刷新方案(vue & react)试一下有惊喜

 

 

 

 

 

vue中的实现

在routes配置文件中:

import Home from "../views/Home.vue";const routes = [  {    path"/home",    name"Home",    component: Home,    children: [      {        path"sub",        component: @H_36_@R_512_2621@@() =>          import(/* webpackChunkName: "sub" */ "../views/Sub.vue"),      },    ],  },];export default routes;

主页:

<template>  <div class="home">    <input v-model="inputValue" />    <h3>{{ inputValue }}</h3>    <button @click="handleToSub">to sub</button>    <router-view @reload="handleReload" />  </div></template><script>export default {  name"Home",  data() {    return {      inputValue"",    };  },  methods: {    handleToSub() {      // 注意路由格式,是基于上一个路由/home下面的sub,不是独立的/sub      this.$router.push("/home/sub");    },    handleReload(val) {      // 这里可以做一些重新获取数据的操作,比如在详情页修改数据,返回后重新拉取列表      console.LOG("reload", val);    },  },  mounted() {    // 子页面返回,不会重新跑生命周期    console.log("mounted");  },};</script><style scoPEd>.home {  posITion: relative;}</style>

子页面:

<template>  <div class="sub">    <h1>This is Sub page</h1>  </div></template><script>export default {  beforedestroy() {    // 可以传自定义参数,如果没需要,也可以不做    this.$emit("reload", 123);  },};</script><style scoped>.sub {  position: absolute;  left0;  top0;  width100%;  height100%;  background-color#fff;}</style>

react中的实现

在routes中:

import { Route } from "react-router-dom";const Routes = () => {  return (    <>      {/* 这里不能加exact,因为要先匹配父页面再匹配子页面 */}      <Route path="/home" component={lazy(() => import("../views/Home"))} />    </>  );};export default Routes;

主页:

import React, { useEffect, useState } from "react";import { Route, useHistory } from "react-router-dom";import styled from "styled-components";import Sub from "./Sub";const HomeContainer = styled.div`  position: relative;`;const Home: React.fc = () => {  const [inputValue, setInputValue] = useState("");  const history = useHistory();  const handleToSub = () => {    history.push("/home/sub");  };  const handleReload = (val: number) => {    console.log("reload", val);  };  useEffect(() => {    console.log("mounted");  }, []);  return (    <HomeContainer>      <input        value={inputValue}        onChange={(e) => setInputValue(e.target.value)}      />      <h3>{inputValue}</h3>      <button onClick={handleToSub}>to sub</button>      <Route        path="/home/sub"        component={() => <Sub handleReload={handleReload} />}      />    </HomeContainer>  );};export default Home;

子页面:

import React from "react";import styled from "styled-components";const SubContainer = styled.div`  position: absolute;  left: 0;  top: 0;  width: 100%;  height: 100%;  background-color: #fff;`;type SubPRops = {  handleReload(val: number) => void;};const Sub: React.FC<SubProps> = ({ handleReload }) => {  useEffect(() => {      return () => handleReload(123);  }, []);  return (    <SubContainer>      <h1>This is Sub page</h1>    </SubContainer>  );};export default Sub;

题外

在前司的核心项目“平安好车主”中,我就在部分h5新项目用了该方案,在线上经受住了170w+访问量的考验。目前在Shopee也在推行这种h5方案,由于逻辑简单,得到了不少同事的认可和使用。比如常见的:列表页存在搜索条件,进入详情页再返回。 大家可以试用一下,会有惊喜的。

该方案的优点

  • 实现简单,无侵入式修改,几乎0逻辑;
  • 子页面可以单独提供出去,供三方接入;
  • 完全的多实例共存,后退不刷新;
  • 可以像父子组件一样通信,监听子页面离开;

缺点

路由格式需要做改造,必须做成嵌套关系,对url有一定要求。

github地址

https://github wangt.cc /zhangnan24/no-refresh-back-vue

脚本宝典总结

以上是脚本宝典为你收集整理的单页应用后退不刷新方案(vue & react)试一下有惊喜全部内容,希望文章能够帮你解决单页应用后退不刷新方案(vue & react)试一下有惊喜所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。