Vue 页面状态保持页面间数据传输的一种方法(推荐)


Posted in Javascript onNovember 01, 2018

如果大家觉得有用,更多的模块请 点击查看

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 参数栈存储示例:

Vue 页面状态保持页面间数据传输的一种方法(推荐)

session storage 参数栈二级存储示例:

Vue 页面状态保持页面间数据传输的一种方法(推荐)

示例

模拟一个简单表单提交流程

Vue 页面状态保持页面间数据传输的一种方法(推荐)

图 详见源码 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} = {})
Javascript 相关文章推荐
使用JavaScript switch case 另类写法
Mar 14 Javascript
js过滤数组重复元素的方法
Sep 05 Javascript
JavaScript基础知识之数据类型
Aug 06 Javascript
html a标签-超链接中confirm方法使用介绍
Jan 04 Javascript
单击某一段文字改写文本颜色
Jun 06 Javascript
javascript的函数作用域
Nov 12 Javascript
jquery取消事件冒泡的三种方法(推荐)
May 28 Javascript
js选择器全面解析
Jun 27 Javascript
微信小程序开发探究
Dec 27 Javascript
JS 中document.write()的用法和清空的原因浅析
Dec 04 Javascript
vue页面切换项目实现转场动画的方法
Nov 12 Javascript
jQuery实现动态加载瀑布流
Sep 01 jQuery
JS 音频可视化插件Wavesurfer.js的使用教程
Oct 31 #Javascript
微信小程序实现留言板
Oct 31 #Javascript
Angular父子组件通过服务传参的示例方法
Oct 31 #Javascript
JS中通过url动态获取图片大小的方法小结(两种方法)
Oct 31 #Javascript
微信小程序实现留言功能
Oct 31 #Javascript
微信小程序签到功能
Oct 31 #Javascript
vue+element-ui实现表格编辑的三种实现方式
Oct 31 #Javascript
You might like
15个小时----从修改程序到自己些程序
2006/10/09 PHP
一周学会PHP(视频)Http下载
2006/12/12 PHP
thinkphp路由规则使用示例详解和伪静态功能实现(apache重写)
2014/02/24 PHP
CI框架中集成CKEditor编辑器的教程
2014/06/09 PHP
PHP开发框架kohana3 自定义路由设置示例
2014/07/14 PHP
php 利用socket发送HTTP请求(GET,POST)
2015/08/24 PHP
Laravel 解决composer相关操作提示php相关异常的问题
2019/10/23 PHP
PHP中用Trait封装单例模式的实现
2019/12/18 PHP
php框架CI(codeigniter)自动加载与自主创建对象操作实例分析
2020/06/06 PHP
jQuery选择器的工作原理和优化分析
2011/07/25 Javascript
设置checkbox为只读(readOnly)的两种方式
2013/10/11 Javascript
html文本框提示效果的示例代码
2014/06/28 Javascript
详解JavaScript基本类型和引用类型
2015/12/09 Javascript
JQuery对ASP.NET MVC数据进行更新删除
2016/07/13 Javascript
原生js图片轮播效果实现代码
2016/10/19 Javascript
jQuery为DOM动态追加事件的方法
2017/02/16 Javascript
JavaScript实现的超简单计算器功能示例
2017/12/23 Javascript
从零开始实现Vue简单的Toast插件
2018/12/03 Javascript
vue实现路由懒加载及组件懒加载的方式
2019/06/11 Javascript
恢复百度云盘本地误删的文件脚本(简单方法)
2017/10/21 Python
解决python 输出是省略号的问题
2018/04/19 Python
Python调用scp向服务器上传文件示例
2019/12/22 Python
基于django micro搭建网站实现加水印功能
2020/05/22 Python
pandas数据处理之绘图的实现
2020/06/15 Python
CSS3的文字阴影—text-shadow的使用方法
2012/12/25 HTML / CSS
纯css3(无图片/js)制作的几个社交媒体网站的图标
2013/03/21 HTML / CSS
CSS实现雨滴动画效果的实例代码
2019/10/08 HTML / CSS
印度在线购物网站:Paytmmall
2019/07/24 全球购物
介绍一下Transact-SQL中SPACE函数的用法
2015/09/01 面试题
如果Session Bean得Remove方法一直都不被调用会怎么样
2012/07/14 面试题
大四本科生的自我评价
2013/12/30 职场文书
2015年保安个人工作总结
2015/04/02 职场文书
幼儿园教师岗位职责
2015/04/02 职场文书
2015大学迎新晚会策划书
2015/07/16 职场文书
Python实现列表拼接和去重的三种方式
2021/07/02 Python
Win10 和 Win11可以共存吗? win10/11产品生命周期/服务更新介绍
2021/11/21 数码科技