1. 程式人生 > >Vue 頁面狀態保持頁面間資料傳輸的一種方法

Vue 頁面狀態保持頁面間資料傳輸的一種方法

如果大家覺得有用,更多的模組請點選檢視

vue router給我們提供了兩種頁面間傳遞引數的方式:

// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})

// 帶查詢引數,變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
複製程式碼

下面介紹一下vue-viewplus 一個簡化Vue應用開發的工具庫中的引數棧模組params-stack.js

該外掛為Vue例項提供了一個$vp

屬性,模組提供了一系列api,來做自己的頁面引數方式:

// 跳轉頁面,並傳遞引數
this.$vp.psPageNext('/Demo/PageStack/Page2', {
  params: {
    phoneNumb: '15111111111'
  }
})
複製程式碼

這一點和vue router給我們提供的傳遞方式類似,並且目前還不支援query: { plan: 'private' }傳遞url引數,但是我們為什麼還要做這個模組:

  • 提供一個來管理棧內所有頁面的引數,方便頁面在回退的時候,拿到對應頁面的快取引數;即一般我們使用vue router的時候每個頁面的引數(除了使用url引數),在做統一返回鍵處理的時候,都不太方便進行頁面狀態恢復,而如果我們提供了一個棧,在頁面入棧的時候,將當前頁面的引數儲存,在下一個頁面點選返回按鈕回到當前頁面的時候我們再從引數棧恢復引數,這樣就能實現客戶端開發中具有的這一特性;
  • 該引數棧也支援快取->自動恢復,vuex state和session storage兩級儲存保證引數棧不會被頁面重新整理而導致頁面引數丟失
  • 也為了統一程式設計方式

並且,當前模組提供的引數傳遞方式,和vue router給我們提供了兩種頁面間傳遞引數的方式,並不衝突,可以互補使用。

只不過目前外掛的引數棧並沒有管理vue router幫我們傳遞的引數;

vuex state 引數棧儲存示例:

image-20181030213140848

session storage 引數棧二級儲存示例:

image-20181030213007933

示例

模擬一個簡單表單提交流程

image-20181030180125629

圖 詳見原始碼example專案中當前模組示例

  • 表單錄入頁面(簡稱:Page1)
<template>
  <group title="模擬手機號充值 - 堆疊底-第一頁" label-width="5em" class="bottom-group">
    <box gap="10px 10px">
      <x-input title="手機號" v-model="dataParams.phoneNumb"></x-input>
    </box>
    <box gap="10px 10px">
      <x-button plain @click.native="submit()">點選充值</x-button>
      <x-button plain @click.native="modify()">修改引數棧內參數物件</x-button>
    </box>
  </group>
</template>

<script type="text/ecmascript-6">
import demoMixin from '../demo-mixin'
import { XInput } from 'vux'
// 1.引數棧模組提供的一個**混入**元件,方便頁面元件簡化引數棧的api操作和開發,詳見下面的`paramsStack mixin`說明
import { paramsStack } from 'vue-viewplus'

export default {
	// 2.使用`paramsStack mixin`
  mixins: [paramsStack, demoMixin],
  components: {
    XInput
  },
  data() {
    return {
      // 3.【可選】`paramsStack mixin`中定義的`data`屬性,聲明當前頁面元件是引數棧的棧底,噹噹前頁面被點選返回彈出的時候,外掛會檢測這個屬性,如果為true,就清空引數棧
      // isStackBottom: true,
      // 4.自定義需要傳遞到下一個頁面的引數
      dataParams: {
        phoneNumb: ''
      }
    }
  },
  methods: {
    submit() {
      this.$vp.psPageNext('/Demo/PageStack/Page2', {
        params: this.dataParams
      })
    }
  },
  created() {
    // 【可選】類似第三步
    // this.isStackBottom = true
    // 5.解析回傳引數
    if (!_.isEmpty(this.backParams)) {
	    this.dataParams.phoneNumb = this.backParams.phoneNumb
    	this.$vp.toast(`通過 backParams.phoneNumb 預填寫頁面`)
    }
  }
}
</script>
複製程式碼
  • 表單確認頁面(簡稱:Page2)
<template>
  <group label-width="15em" class="bottom-group">
    <form-preview header-label="請確認訂單資訊" :body-items="list" ></form-preview>
    <x-input title="請輸出充值金額" v-model="dataParams.amount" style="margin-top: 10px"></x-input>
    <box gap="10px 10px">
      <flexbox>
        <flexbox-item>
          <x-button type="default" @click.native="replace()">確認</x-button>
        </flexbox-item>
        <flexbox-item>
          <x-button type="default" @click.native="bck()">返回(回傳引數)</x-button>
        </flexbox-item>
      </flexbox>
    </box>
  </group>
</template>

<script type="text/ecmascript-6">
import demoMixin from '../demo-mixin'
import { paramsStack } from 'vue-viewplus'
import { XInput, FormPreview, Flexbox, FlexboxItem } from 'vux'

export default {
  mixins: [paramsStack, demoMixin],
  components: {
    FormPreview,
    Flexbox,
    FlexboxItem,
    XInput
  },
  data() {
    return {
    // 1. 回顯上一個頁面錄入的手機號
      list: [
        {
          label: '手機號',
          value: ''
        }
      ],
      // 2. 自定義需要傳遞到下一個頁面的引數
      dataParams: {
        phoneNumb: '',
        amount: '50元'
      }
    }
  },
  methods: {
    /**
     * 4.提交表單方式1
     * 如果需要下一個頁面點選返回,任然要回顯當前頁面,就呼叫該方法
     * /
    next() {
      this.$vp.psPageNext('/Demo/PageStack/Page4', { params: this.dataParams })
    },
    /**
     * 4.提交表單方式2
     * 一般確認頁面都無需被“保留”,故這裡使用`this.$vp.psPageReplace`介面完成跳轉,底層將會使用
     * `router.replace({location})`完成跳轉
     */
    replace() {
      this.$vp.psPageReplace('/Demo/PageStack/Page4', {params: this.dataParams})
    },
    bck() {
      this.$vp.psPageGoBack({
      	// 3.設定回傳引數
        backParams: {
          phoneNumb: '13222222222'
        }
      })
    }
  },
  created() {
    this.list[0].value = this.params.phoneNumb
    this.dataParams.phoneNumb = this.params.phoneNumb
  }
}
</script>
複製程式碼
  • 表單結果頁面(簡稱:Page4)
<template>
  <div>
    <msg title="操作成功" :description="description" :buttons="buttons"></msg>
  </div>

</template>

<script type="text/ecmascript-6">
  import demoMixin from '../demo-mixin'
  import { paramsStack } from 'vue-viewplus'
  import { FormPreview, Msg } from 'vux'

  export default {
    mixins: [paramsStack, demoMixin],
    components: {
      FormPreview,
      Msg
    },
    data() {
      return {
        description: '',
        buttons: [{
          type: 'primary',
          text: '在做一筆',
          onClick: ((that) => {
            return () => {
              // 返回棧頂頁面
              that.$vp.psPageGoBack()
            }
          })(this)
        }, {
          type: 'default',
          text: '完成',
          onClick: ((that) => {
            return () => {
              // 返回指定頁面,並清空引數棧
              // that.$vp.psPageGoBack({
              //   backPopPageNumbs: -2,
              //   clearParamsStack: true
              // })
              that.$vp.psPageNext('/Demo', {
                clearParamsStack: true,
                backState: true
              })
            }
          })(this)
        }]
      }
    },
    created() {
      this.description = `${this.params.phoneNumb} 成功充值 ${this.params.amount}`
    }
  }
</script>
複製程式碼

paramsStack mixin

以上3個頁面都集成了paramsStack mixin,定義如下:


/**
 * 引數棧mixin物件
 * <p>
 *   方便頁面元件繼承之後操作引數棧
 * @type {Object}
 */
export const paramsStackMixin = {
  data() {
    return {
      /**
       * 宣告該頁面是棧底部
       */
      isStackBottom: false
    }
  },
  computed: {
    ...mapGetters([
      /**
       * 檢視`vuex#vplus.paramsStack[top-length]`棧頂引數
       */
      'params'
    ]),
    /**
     * 檢視`vuex#vplus.backParams`回傳引數
     */
    backParams() {
      return this.$store.state[MODULE_NAME].backParams
    },
    /**
     * 檢視`vuex#vplus.backState`是否是出棧|是否是返回狀態
     */
    backState() {
      return this.$store.state[MODULE_NAME].backState
    }
  },
  methods: {
    ...mapMutations([
      /**
       * 入棧
       */
      'pushParams',
      /**
       * 修改棧頂引數
       */
      'modifyParams',
      /**
       * 出棧
       */
      'popParams',
      /**
       * 清空引數棧
       */
      'clearParamsStack',
      /**
       * 設定是否是出棧|是否是返回狀態(點選返回頁面)
       */
      'setBackState'
    ])
  },
  // 導航離開該元件的對應路由時呼叫
  beforeRouteLeave(to, from, next) {
    if (this.backState && this.isStackBottom) {
      this.clearParamsStack()
    }
    next()
  }
}
複製程式碼

配置

沒有個性化配置,可以檢視全域性通用配置

API介面

restoreParamsStack

/**
   * $vp.restoreParamsStack()
   * 恢復外掛中`vuex#$vp.paramsStack` && vuex#$vp.backParams` && vuex#$vp.backState`引數棧所用狀態
   * <p>
   * 在當前模組重新安裝的時候,一般對應就是外掛初始化和頁面重新整理的時候
   */
  restoreParamsStack()
複製程式碼

psModifyBackState

/**
   * $vp.psModifyBackState(bckState)
   * <p>
   * 設定`vuex#vplus.backState`返回狀態
   * @param {Boolean} [backState=false]
   */
  psModifyBackState(bckState)
複製程式碼

psClearParamsStack

/**
   * $vp.psClearParamsStack()
   * <p>
   * 清空引數棧
   */
  psClearParamsStack()
複製程式碼

psPageNext

/**
   * $vp.(location[, {params = {}, clearParamsStack = false, backState = false} = {}])
   * <p>
   * 頁面導航
   * @param location router location物件
   * @param {Object} [params={}] 向下一個頁面需要傳遞的引數
   * @param {Boolean} [clearParamsStack=false] 在進行頁面導航的時候,是否清空引數棧,預設為false
   * @param {Boolean} [backState=false] 設定`vuex#vplus.backState`返回狀態,預設為false
   */
  psPageNext(location, {params = {}, clearParamsStack = false, backState = false} = {})
複製程式碼

psPageReplace

/**
   * $vp.(location[, {params = {}, isPop = true} = {}])
   * <p>
   * 頁面導航(基於Router),移除上一個頁面
   * <p>
   *   將會出棧頂物件,並重新設定`params`為引數棧的棧頂引數
   *   注:在呼叫該方法的頁面,必須是要呼叫`ParamsStack#psPageNext`導航的頁面,因為需要保證“彈棧”操作無誤,
   *   又或者設定`isPop`為false
   * @param location router location物件
   * @param {Object} [params={}] 向下一個頁面需要傳遞的引數
   * @param {Boolean} [isPop=false] 是否pop當前頁面的引數後在進行頁面跳轉,預設為true,防止當前頁面
   * 不是通過`ParamsStack#psPageNext`導航過來的,但是由需要使用當前方法
   */
  psPageReplace(location, {params = {}, isPop = true} = {})
複製程式碼

psPageGoBack

/**
   * $vp.psPageGoBack({backParams = {}, clearParamsStack = false, backPopPageNumbs = -1} = {})
   * <p>
   * 頁面回退
   * @param {Object} backParams 設定回傳引數
   * @param {Boolean} clearParamsStack 是否清空引數棧
   * @param {Number} backPopPageNumbs 出棧頁面數
   */
  psPageGoBack({backParams = {}, clearParamsStack = false, backPopPageNumbs = -1} = {})
複製程式碼