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入门·图片对象(无刷新变换图片)\滚动图像
Oct 01 Javascript
JS图片无缝滚动(简单利于使用)
Jun 17 Javascript
javascript对话框使用方法(警告框 javascript确认框 提示框)
Jan 07 Javascript
JavaScript获取页面中第一个锚定文本的方法
Apr 03 Javascript
jQuery插件ajaxFileUpload实现异步上传文件效果
Apr 14 Javascript
引用jquery框架后出错的解决方法
Aug 09 Javascript
Jquery根据浏览器窗口改变调整大小的方法
Feb 07 Javascript
用vue和node写的简易购物车实现
Apr 25 Javascript
Ionic + Angular.js实现图片轮播的方法示例
May 21 Javascript
JavaScript设计模式之观察者模式实例详解
Jan 16 Javascript
判断JavaScript中的两个变量是否相等的操作符
Dec 21 Javascript
js基于canvas实现时钟组件
Feb 07 Javascript
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
espresso double下 咖啡粉超细时 饼压力对咖啡的影响
2021/03/03 冲泡冲煮
thinkphp3查询mssql数据库乱码解决方法分享
2014/02/11 PHP
PHP函数func_num_args用法实例分析
2015/12/07 PHP
Bootstrap+PHP实现多图上传功能实例详解
2018/04/08 PHP
基于jQuery实现表格数据的动态添加与统计的代码
2011/01/31 Javascript
javascript学习笔记(十八) 获得页面中的元素代码
2012/06/20 Javascript
jQuery后代选择器用法实例
2014/12/23 Javascript
JavaScript中字符串(string)转json的2种方法
2015/06/25 Javascript
原生javascript实现自动更新的时间日期
2016/02/12 Javascript
Javascrip实现文字跳动特效
2016/11/27 Javascript
nodejs服务搭建教程 nodejs访问本地站点文件
2017/04/07 NodeJs
websocket+node.js实现实时聊天系统问题咨询
2017/05/17 Javascript
深入理解Angularjs中$http.post与$.post
2017/05/19 Javascript
Angular中点击li标签实现更改颜色的核心代码
2017/12/08 Javascript
vue页面跳转后返回原页面初始位置方法
2018/02/11 Javascript
JavaScript显式数据类型转换详解
2019/03/18 Javascript
vue 父组件中调用子组件函数的方法
2019/06/06 Javascript
在vue中把含有html标签转为html渲染页面的实例
2019/10/28 Javascript
node.js制作一个简单的登录拦截器
2020/02/10 Javascript
Vue路由切换页面不更新问题解决方案
2020/07/10 Javascript
使用webpack和rollup打包组件库的方法
2021/02/25 Javascript
[49:41]NB vs NAVI Supermajor小组赛A组 BO3 第一场 6.2
2018/06/03 DOTA
[00:09]DOTA2全国高校联赛 精彩活动引爆全场
2018/05/30 DOTA
使用Python获取CPU、内存和硬盘等windowns系统信息的2个例子
2014/04/15 Python
使用Django连接Mysql数据库步骤
2019/01/15 Python
Django实现网页分页功能
2019/10/31 Python
HTML5本地存储之Database Storage应用介绍
2013/01/06 HTML / CSS
卡骆驰德国官方网站:Crocs德国
2019/03/29 全球购物
类和结构的区别
2012/08/15 面试题
python+selenium小米商城红米K40手机自动抢购的示例代码
2021/03/24 Python
中专生自我鉴定
2013/12/17 职场文书
司法局火灾防控方案
2014/06/05 职场文书
开展党的群众路线教育实践活动工作总结
2014/11/05 职场文书
退休教师追悼词
2015/06/23 职场文书
2015大一新生军训感言
2015/08/01 职场文书
基于nginx实现上游服务器动态自动上下线无需reload的实现方法
2021/03/31 Servers