【项目-喵内0∞0记账-meowney-08】功能扩展包 DLC-页面会话保存sessionStorage + 路由守卫
大纲
[toc]
Vue文档中的路由守卫
路由守卫:主要用来通过 跳转 或 取消 的方式,操控导航逻辑
- 全局路由守卫
- 全局 前置守卫
router.beforeEach(to, from, next) => {...}) - 全局 解析守卫
router.beforeResolve(to, from, next) => {...}) - 全局 后置钩子
router.afterEach(to, from,) => {...}) - 后置钩子不接受 next 函数
- 全局 前置守卫
- 单个路由,路由独享守卫
- 在路由配置
./src/router/index.ts(js)上直接定义路由列表中每个路由对象中的属性beforeEnter: (to, from,) => {...}, - 路由独享的守卫
beforeEnter - 与全局前置守卫的方法参数是一样的
- 在路由配置
- 组件级
- 在组件内直接定义
- 组件内守卫 配置属性
beforeRouteEnter(to, from, next) {...}beforeRouteUpdate(to, from,) {...}beforeRouteLeave(to, from,) {...}
- 完整的导航解析流程
导航解析流程:
- ① 触发导航 ->
- ②
beforeRouteLeave(失活的组件内调用)-> - ③ 全局
beforeEach-> - ④
beforeRouteUpdate(复用的组件内调用)-> - ⑤
beforeEnter(路由配置里调用)-> - ⑥ 异步路由组件 ->
- ⑦
beforeRouteEnter(被激活的组件里调用)-> - ⑧ 全局
beforeResolve-> 确认导航 -> - ⑨ 全局
afterEach-> 触发 DOM 更新 - ⑩ 调用回调函数,
beforeRouteEnter守卫,传给next({})中的回调函数- 创建好的组件实例
vm作为回调函数的参数传入next({vm=>(...)})
- 创建好的组件实例
url查询参数的改变并 不会触发 进入/离开的 导航守卫
- 使用
watch: {...}观察$route(to, from) {...}对象来应对这些变化 - 使用
beforeRouteUpdate的组件内守卫
sessionStorage 页面会话保存
需要暂存页面数据的组件
Money.vue./store/modules/moneySessionStore.ts
Tags.vueFormItem.vueTabs.vueNumpad.vueNumpadOutput.vueNumpadButton.vue
修改Money.vue
为了暂存用户输入的数据,当用户切换页面,触发导航守卫钩子,将数据存到
sessionStorage中1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91<script lang="ts"> // 路由 import {NavigationGuardNext, Route} from 'vue-router'; // 框架组件 import ... // 页面模块组件 import ... // 数据 import ... @Component({ components: {HeaderBar, Tabs, FormItem, Tags, Numpad, DateGetter}, beforeRouteEnter(to: Route, from: Route, next: NavigationGuardNext): void { next(vm => { // 通过 `vm` 访问组件实例 代替this vm.$store.commit('loadMoneySessionStore'); // 读取 session 数据 }); }, beforeRouteLeave(to: Route, from: Route, next: NavigationGuardNext): void { this.$store.commit('saveMoneySessionStore'); next(); } }) export default class Money extends Vue { // data record: RecordItem = { tags: [], tips: '', type: '-', amount: 0, createdAt: dayjs((new Date()).toISOString()).format('YYYY-MM-DD'), }; sessionSelectedTags ? = this.$store.state.moneySessionStore.tagsStore; recordTypeList = recordTypeList; checkoutResult = false; emptyTags = false; // computed get recordList() { return this.$store.state.recordStore.recordList as RecordItem[]; } // methods updatePickedTags(selectedTags: Tag[]) { this.emptyTags = false; // 记录 选中的标签 this.record.tags = selectedTags; // 页面暂存 session selectedTags this.$store.commit('updateTagsStore', selectedTags); } deselectTags(deselect: boolean) {/*...*/} checkoutRecord() {/*...*/} alertInform(caseName: 'case1' | 'case2' | 'case3') {/*...*/} saveRecord() {/*...*/} reset() {/*...*/} submit() {/*...*/} } </script> <template> <Layout class-prefix="layout" class="layout-content"> <HeaderBar :header-title="'记账'" :hasIcon="false"> </HeaderBar> <Tags @update:selectedTags="updatePickedTags" :sessionSelectedTags="sessionSelectedTags" :is-deselect-tags="emptyTags" class="tags"/> <FormItem class="form-item" field-name="备注" placeholder="在这里输入备注" type="text" :inputValue.sync="record.tips"/> <FormItem class="form-item" field-name="日期" placeholder="在这里选择日期" type="date" :inputValue.sync="record.createdAt"/> <div class="datePicker"> <date-getter></date-getter> </div> <Tabs :data-source="recordTypeList" :type.sync="record.type" class="fuckAnt-tabs"/> <Numpad :amount.sync="record.amount" @submit="submit" @update:deselectTags="deselectTags" @checkZero="alertInform('case3')" :is-reset="checkoutResult"/> </Layout> </template>分别需要保存数据: 标签
tagsStore、备注tipsStore、日期dateStore、收支类型typeStore、金额amountStore关闭页面,自动清除
sessionStorage数据
./store/modules/moneySessionStore.ts
|
|
类型声明
custom.d.ts
|
|
修改Tags.vue
|
|
- 在
mounted阶段读取session信息,之后渲染页面 - 页面数据改变,写入相应的
session数据
修改FormItem.vue
|
|
- 在
mounted阶段读取session信息,之后渲染页面 - 页面数据改变,写入相应的
session数据
修改Tabs.vue
|
|
- 在
mounted阶段读取session信息,之后渲染页面 - 页面数据改变,写入相应的
session数据
Numpad.vue
|
|
NumpadOutput.vueNumpadButton.vue
NumpadOutput.vue
|
|
- 在
mounted阶段读取session信息,之后渲染页面 - 页面数据改变,写入相应的
session数据
参考
跳转页面 路由守卫钩子 暂存页面数据
组件内路由守卫 使用vue-property-decorator 类组件 TS装饰器
Money.vue添加组件内的路由守卫
Money.vue
|
|
- 组件内的路由守卫放在
@Component选项中,分别有beforeRouteEnter|beforeRouteLeave|beforeRouteUpate- TS所需参数和类型为
beforeRouteEnter(to: Route, from: Route, next: NavigationGuardNext): void - 类型由
import {NavigationGuardNext, Route} from 'vue-router';得到
beforeRouteEnter- 在渲染该组件的对应路由被
confirm前调用 - 不!能!获取组件实例
this beforeRouteEnter守卫 不能 访问this- 可由
next(vm=>{})中vm的代替 - 即通过传一个回调
vm=>{}给next来访问组件实例 - 在导航被确认的时候执行回调,并且把组件实例
vm作为回调方法的参数代替this - 因为当守卫执行前,组件实例还没被创建
- 守卫在导航确认前被调用,因此即将登场的新组件还没被创建
- 在渲染该组件的对应路由被
beforeRouteLeave- 在当前路由改变,但是该组件被复用时调用
- 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候
- 由于会渲染同样的 Foo 组件,因此组件实例会被复用
- 而这个钩子就会在这个情况下被调用
- 可以访问组件实例
this
beforeRouteUpate- 导航离开该组件的对应路由时调用
- 可以访问组件实例
this
参考
- Vue-Router组件内的守卫
- Vue TypeScript Handbook 类风格的组件
- vue + typescript 类组件教程
- Vue 导航守卫
- 基于类的 Vue 组件
- Vue Typescript example: Build a CRUD Application
- Vue Property Decorator github
- Vue Class Component Additional Hooks
- VUE 集成TypeScript之vue-router重构
使用vuex-ts-decorators TS Class 组件 状态管理
Money.vue
|
|
·未完待续·
参考文章
相关文章
- 无