Vue 使用History記錄上一頁面的數據


UI

![](https://img2018.cnblogs.com/blog/1504257/201811/1504257-20181102140311509-821423154.jpg) ![](https://img2018.cnblogs.com/blog/1504257/201811/1504257-20181102140318832-1421357415.jpg)

需求

  1. 從列表頁的第二頁進入詳情頁,返回時列表頁仍然顯示在第二頁;
  2. 從列表頁的第二頁進入詳情頁,返回時列表頁的篩選條件仍然存在。

<!--more-->

技術選擇

  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),因為需要灰度上線,萬一有問題,要調整的頁面也只有一個。代碼如下:

&lt;script&gt;
  export default {
    props: {
      openroute: {
        type: Boolean,
        default: () =&gt; (true)
      }
    },
  }
&lt;/script&gt;

分頁組件中存儲頁碼選擇條件&獲取頁碼

&lt;script&gt;
  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 &amp;&amp; location.hash &amp;&amp; location.hash.split("#") &amp;&amp; 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 &amp;&amp; location.hash.split("#") &amp;&amp; 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 &amp;&amp; location.hash.split("#") &amp;&amp; location.hash.split("#")[1]) {
            newPage = Number(location.hash.split("#")[1]);
          } else {
            newPage = 1;
          }
        } else {
          newPage = page;
        }
        //請求數據,獲得結果,傳遞給列表頁面
      }
    }
  }
&lt;/script&gt;

列表頁面獲取選擇條件

目前可能是因為框架設計的問題,沒法在請求數據之前通過Object.assign方式為替換初始變量,所以先這樣處理(笨方法,各位大佬有解決辦法麻煩指導下,謝謝):

&lt;script&gt;
  export default {
    data() {
      return {
        form: {
          aaa: (history.state &amp;&amp; history.state.aaa) ? history.state.aaa : null,
          bbb: (history.state &amp;&amp; history.state.bbb) ? history.state.bbb : null,
          ccc: (history.state &amp;&amp; history.state.ccc) ? history.state.ccc : null
        },
      };
    }
  };
&lt;/script&gt;

已解決,初始變量不需要動,可以通過以下方式實現:

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

分析(這篇文章有源碼分析(<font color='red'>求解答:WebStorm中如何關聯源碼?</font>),很棒):https://www.cnblogs.com/libin...

FAQ

  • 需要使用history.replaceState方式是因為:它不會將更改后的url壓到history棧中,所以不會增加回退和前進的操作步數;
  • 使用history.replaceState方式,可存儲的state大小不能操作640k;
  • 可能存在瀏覽器兼容性問題,請從此處查閱:https://caniuse.com/#feat=his...

Demo Or Source

因為是公司項目,所以目前沒有Demo或源碼

參考文章

原文地址:https://segmentfault.com/a/1190000016876337


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM