Vue 使用History记录上一页面的数据

UI

需求

  1. 从列表页的第二页进入详情页,返回时列表页仍然显示在第二页;
  2. 从列表页的第二页进入详情页,返回时列表页的筛选条件仍然存在。

技术选择

  1. 使用vue-router组件,通过this.$router.push({path: path, query: query});方式,将页码选择条件作为参数存储在url中,这种方式在上面的UI设计中是可行的,但是当列表页中包含tab组件时(分页组件是公用的),会因为push的因素(因为push会打开新页面)导致一些问题(PS:也可能是本人技术能力的原因),未实现。
  2. 使用History API(HTML5开始支持),通过history.replaceState方式,将页码作为参数存储在url中,将选择条件存储在history中(尚不清楚数据具体是存储在哪里);通过location.hash方式获取页码;通过history.state方式获取存储的选择条件。

具体实现--技术选择2

开关

为分页组件添加一个开关(openroute),因为需要灰度上线,万一有问题,要调整的页面也只有一个。代码如下:

<script>
  export default {
    props: {
      openroute: {
        type: Boolean,
        default: () => (true)
      }
    },
  }
</script>
复制代码

分页组件中存储页码选择条件&获取页码

<script>
  export default {
    methods: {
      fetchData(page) {
      	//请求参数
        let params = this.params;
        //请求页码
        let newPage;
        //openroute处理
        if (this.openroute) {
          //为url添上#page
          if (page) {
            history.replaceState(params.data, document.title, "#" + page);
          } else {
            if (history.state) {
              if (!history.state.key && location.hash && location.hash.split("#") && location.hash.split("#")[1]) {
                if (JSON.stringify(history.state) !== JSON.stringify(params.data)) { //选择条件变更则请求第一页
                  history.replaceState(params.data, document.title, "#1");
                } else {
                  history.replaceState(params.data, document.title, "#" + location.hash.split("#")[1]);
                }
              } else {
                history.replaceState(params.data, document.title, "#1");
              }
            } else {
              if (location.hash && location.hash.split("#") && location.hash.split("#")[1]) {
                history.replaceState(params.data, document.title, "#" + location.hash.split("#")[1]);
              } else {
                history.replaceState(params.data, document.title, "#1");
              }
            }
          }
          //获取url后面的#page
          if (location.hash && location.hash.split("#") && location.hash.split("#")[1]) {
            newPage = Number(location.hash.split("#")[1]);
          } else {
            newPage = 1;
          }
        } else {
          newPage = page;
        }
        //请求数据,获得结果,传递给列表页面
      }
    }
  }
</script>
复制代码

列表页面获取选择条件

目前可能是因为框架设计的问题,没法在请求数据之前通过Object.assign方式为替换初始变量,所以先这样处理(笨方法,各位大佬有解决办法麻烦指导下,谢谢):

<script>
  export default {
    data() {
      return {
        form: {
          aaa: (history.state && history.state.aaa) ? history.state.aaa : null,
          bbb: (history.state && history.state.bbb) ? history.state.bbb : null,
          ccc: (history.state && history.state.ccc) ? history.state.ccc : null
        },
      };
    }
  };
</script>
复制代码

已解决,初始变量不需要动,可以通过以下方式实现:

created(){
  //获取缓存的数据
  if (history.state) {
    Object.assign(this.form, history.state)
    if (this.form.key) {
      delete this.form.key
    }
  }
},
复制代码

这里记录下:之前以为created方法是在分页组件的watch监听之后执行的,后来发现被误导了(因为之前是通过Object.assign(true, this.form, history.state)方式实现数据赋值的,但是并没有成功)。下面做个小总结:

Object.assign(true, a, b);”和“Object.assign(a, b);”有什么区别?

结论:前者:改a不影响b;后者:改a影响b

分析(这篇文章有源码分析(求解答:WebStorm中如何关联源码?),很棒):www.cnblogs.com/libin-1/p/6…

FAQ

  • 需要使用history.replaceState方式是因为:它不会将更改后的url压到history栈中,所以不会增加回退和前进的操作步数;
  • 使用history.replaceState方式,可存储的state大小不能操作640k;
  • 可能存在浏览器兼容性问题,请从此处查阅:caniuse.com/#feat=histo…

Demo Or Source

因为是公司项目,所以目前没有Demo或源码

参考文章

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我们开始实现一个登录页面。 首先,我们需要创建一个Vue 3的工程。可以使用Vue CLI来创建一个新的Vue 3项目: ``` vue create my-project ``` 然后,我们需要安装一些其他的依赖项: ``` npm install --save axios vue-router ``` 接下来,我们可以开始编写我们的登录页面。首先,我们需要创建一个新的组件,它将包含我们的登录表单。我们可以在组件中使用`<template>`标签来定义我们的模板,使用`<script>`标签来定义我们的逻辑,使用`<style>`标签来定义我们的样式。在这里,我们使用TypeScript来编写我们的代码。 ```vue <template> <form> <div> <label for="username">Username:</label> <input type="text" id="username" v-model="username" /> </div> <div> <label for="password">Password:</label> <input type="password" id="password" v-model="password" /> </div> <button type="submit" @click.prevent="login">Login</button> </form> </template> <script lang="ts"> import { defineComponent } from 'vue'; import axios from 'axios'; export default defineComponent({ data() { return { username: '', password: '', }; }, methods: { async login() { const response = await axios.post('/api/login', { username: this.username, password: this.password, }); if (response.data.success) { // 登录成功,跳转到首页 this.$router.push('/'); } else { // 登录失败,显示错误信息 alert(response.data.error); } }, }, }); </script> <style> form { display: flex; flex-direction: column; align-items: center; } div { margin: 10px 0; } label { display: block; margin-bottom: 5px; } </style> ``` 在这个组件中,我们定义了两个数据属性`username`和`password`,它们将分别绑定到我们的用户名和密码输入框上。我们还定义了一个`login`方法,它将使用Axios来向服务器发送登录请求,并在服务器返回成功时将用户重定向到首页。如果登录失败,我们将显示一个警告框,显示错误信息。 接下来,我们需要在我们的Vue Router中定义一个路由,以便我们可以在浏览器中访问我们的登录页面。在`src/router/index.ts`文件中,我们可以添加以下代码: ```ts import { createRouter, createWebHistory } from 'vue-router'; import Login from '@/views/Login.vue'; const routes = [ { path: '/login', name: 'Login', component: Login, }, ]; const router = createRouter({ history: createWebHistory(), routes, }); export default router; ``` 在这里,我们定义了一个名为`Login`的路由,它将渲染我们之前定义的`Login`组件。我们还使用`createWebHistory`函数来创建一个HTML5历史记录路由,以便我们可以使用浏览器的前进和后退按钮进行导航。 最后,我们需要在我们的入口文件中将Vue Router添加到我们的应用程序中。在`src/main.ts`文件中,我们可以添加以下代码: ```ts import { createApp } from 'vue'; import App from './App.vue'; import router from './router'; createApp(App).use(router).mount('#app'); ``` 在这里,我们使用`createApp`函数创建一个Vue实例,并将我们的Vue Router添加到这个实例中。然后,我们将这个实例挂载到`#app`元素上。 现在我们已经完成了我们的登录页面。我们可以使用`npm run serve`命令来启动我们的开发服务器,并在浏览器中访问`http://localhost:8080/login`来查看我们的登录页面

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值