如何在多标签页切换时自动刷新视图

在日常项目中,常常会遇到多视图(Multi-View)标签的场景,用户在切换不同视图时,可能需要刷新当前活动标签内的视图数据或状态。本文将详细解析下面这段代码,并说明如何利用它在视图切换时刷新对应的视图。

下列代码写在ss-boot里面的main.ts

import { VueOioProvider } from '@kunlun/dependencies';
import { delay } from 'lodash-es';

VueOioProvider(
  {
    ... 自己的配置
  },
  [
    () => {
      setTimeout(() => {
        subscribeRoute(
          (route) => {
            const page = route.segmentParams.page || {};

            // 如果不是表格类型,则不刷新(根据自己的需求判断)
            if (page.viewType !== ViewType.Table) {
              return;
            }

            const { model, action } = page;

            const multiTabsManager = MultiTabsManager.INSTANCE;

            delay(() => {
              const tab = multiTabsManager.getActiveTab();

              if (tab?.key && tab.stack.some((s) => s.parameters?.model === model && s.parameters?.action === action)) {
                multiTabsManager.refresh(tab.key);
              }
            }, 200);
          },
          { distinct: true }
        );
      }, 1000);
    }
  ]
);

1. VueOioProvider 及其作用

首先,代码通过 VueOioProvider 初始化应用程序或组件,并传入两部分参数:

  • 配置对象:可以根据实际业务需求进行自定义配置;
  • 回调函数数组:这里传入了一个匿名函数,用于在应用初始化后执行额外的逻辑

2. 延时执行与路由监听

在回调函数中,使用了 setTimeout 延时 1000 毫秒执行,目的通常是为了确保其他组件或全局状态已经初始化完毕,再开始进行路由监听。

随后,代码调用 subscribeRoute 来监听路由的变化。subscribeRoute 接收两个参数:

  • 回调函数:每次路由变化时都会触发该函数,并将最新的 route 对象传递给它;
  • 配置对象:此处使用 { distinct: true } 来避免重复的触发,提高性能。

3. 判断视图类型

在路由回调函数内部,首先通过 route.segmentParams.page 获取当前页面的配置信息。通过判断 page.viewType 是否等于 ViewType.Table,代码可以确定当前视图是否为“表格类型”:

  • 如果不是表格类型:则直接返回,不做刷新操作;
  • 如果是表格类型:则继续执行后续刷新逻辑。

这种判断机制保证了只有特定类型的视图(例如表格)在切换时才会触发刷新,避免了不必要的操作

4. 多视图标签的刷新逻辑

当确认当前视图为表格类型后,从 MultiTabsManager 中获取当前活动标签:

MultiTabsManager.INSTANCE.getActiveTab() 返回当前活动的标签对象;

如果 key 存在,并且激活的标签内部存储的action跟url一致, 就调用 multiTabsManager.refresh(key) 方法来刷新当前标签内的视图。

Oinone社区 作者:汤乾华原创文章,如若转载,请注明出处:https://doc.oinone.top/frontend/20662.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

(0)
汤乾华的头像汤乾华数式员工
上一篇 2025年3月12日 am10:05
下一篇 2025年3月13日 pm2:56

相关推荐

  • 如何在自有前端工程中使用gql请求?

    场景 客户在个性化程度比较高的h5工程中想使用平台的服务端能力,这个时候需要调用后端的gql请求,此时需要引入平台的请求库依赖 npm的package.json中加入依赖 此文档以4.x举例,使用其他版本的请自行修改版本号 "dependencies": { "@kunlun/request": "~4.3.0", "@kunlun/state": "~4.3.0" } 使用示例 import { HttpClient } from ‘@kunlun/request’ const http = HttpClient.getInstance() http.setBaseURL(”) export const login = (data) => { const gqlBody = `mutation { pamirsUserTransientMutation { login(user: {login: “${data.username}”, password: “${data.password}”}) { broken errorMsg errorCode errorField } } }` return http.mutate(‘user’, gqlBody) } 注意事项 开发环境记得配置oinone请求的路由转发规则,这里以vite.config.js举例 import { defineConfig } from ‘vite’ export default defineConfig({ server: { port: 8088, open: true, proxy: { ‘/pamirs’: { changeOrigin: true, // 服务端请求地址 target: ‘http://127.0.0.1:8091’ } } } })

    2023年11月1日
    1.4K00
  • 自定义前端拦截器

    某种情况下,我们需要通过自定义请求拦截器来做自己的逻辑处理,平台内置了一些拦截器 登录拦截器LoginRedirectInterceptor 重定向到登录拦截器LoginRedirectInterceptor import { UrlHelper, IResponseErrorResult, LoginRedirectInterceptor } from '@kunlun/dependencies'; export class BizLoginRedirectInterceptor extends LoginRedirectInterceptor { /** * 重定向到登录页 * @param response 错误响应结果 * @return 是否重定向成功 */ public redirectToLogin(response: IResponseErrorResult): boolean { if (window.parent === window) { const redirect_url = location.pathname; // 可自定义跳转路径 location.href = `${UrlHelper.appendBasePath('login')}?redirect_url=${redirect_url}`; } else { // iframe页面的跳转 window.open(`${window.parent.location.origin}/#/login`, '_top'); } return true; } } 请求成功拦截器RequestSuccessInterceptor 请求失败拦截器 RequestErrorInterceptor 网络请求异常拦截器 NetworkErrorInterceptor 当我们需要重写某个拦截器的时候,只需要继承对应的拦截器,然后重写里面的方法即可 // 自定义登录拦截器 export class CustomLoginRedirectInterceptor extends LoginRedirectInterceptor{ public error(response: IResponseErrorResult) { // 自己的逻辑处理 return true // 必写 } } // 自定义请求成功拦截器 export class CustomRequestSuccessInterceptor extends RequestSuccessInterceptor{ public success(response: IResponseErrorResult) { // 自己的逻辑处理 return true // 必写 } } // 自定义请求失败拦截器 export class CustomRequestErrorInterceptor extends RequestErrorInterceptor{ public error(response: IResponseErrorResult) { const { errors } = response; if (errors && errors.length) { const notPermissionCodes = [ SystemErrorCode.NO_PERMISSION_ON_MODULE, SystemErrorCode.NO_PERMISSION_ON_VIEW, SystemErrorCode.NO_PERMISSION_ON_MODULE_ENTRY, SystemErrorCode.NO_PERMISSION_ON_HOMEPAGE ]; /** * 用来处理重复的错误提示 */ const executedMessages: string[] = []; for (const errorItem of errors) { const errorCode = errorItem.extensions?.errorCode; if (!notPermissionCodes.includes(errorCode as any)) { const errorMessage = errorItem.extensions?.messages?.[0]?.message || errorItem.message; if (!executedMessages.includes(errorMessage)) { // 自己的逻辑处理 } executedMessages.push(errorMessage); } } } return true; } } // 自定义网络请求异常拦截器…

    前端 2023年11月1日
    1.3K01
  • 树型表格全量加载数据如何处理

    阅读该文档的前置条件 【界面设计器】树形表格 1.前端自定义表格组件 import { ActiveRecord, BaseElementWidget, Condition, Entity, SPI, TableWidget, ViewType } from '@kunlun/dependencies'; @SPI.ClassFactory( BaseElementWidget.Token({ type: ViewType.Table, widget: ['demo-tree-table'] }) ) export class TreeTableWidget extends TableWidget { // 默认展开所有层级 protected getTreeExpandAll() { return true; } // 关闭懒加载 protected getTreeLazy(): boolean { return false; } public async $$loadTreeNodes(condition?: Condition, currentRow?: ActiveRecord): Promise<Entity[]> { // 树表加载数据的方法,默认首次只查第一层的数据,这里去掉这个查询条件的参数condition,这样就会查所有层级数据 return super.$$loadTreeNodes(undefined, currentRow); } } 2. 注册layout import { registerLayout, ViewType } from '@kunlun/dependencies'; const install = () => { registerLayout( ` <view type="TABLE"> <element widget="actionBar" slot="actionBar" slotSupport="action"> <xslot name="actions" slotSupport="action" /> </element> <element widget="demo-tree-table" slot="table"> <element widget="expandColumn" slot="expandRow" /> <xslot name="fields" slotSupport="field" /> <element widget="rowActions" slot="rowActions" slotSupport="action" /> </element> </view> `, { viewType: ViewType.Table, model: "resource.resourceCity", // 变量,需要替换 actionName: "MenuuiMenu6f6005bdddba468bb2fb814a62fa83c6", // 变量,需要替换 } ); }; install();

    2024年8月17日
    1.3K00
  • 前端自定义请求入门版

    在开发过程中,为了满足业务场景、增加灵活性,前端自定义请求不可避免。下面将会从——自定义 mask、自定义表格(表单等)、自定义字段三个实际场景的角度,介绍自定义请求。这篇文章把请求都写在了 ts 中,这样便于继承重写,如果不习惯 ts 的写法,把请求写在 vue 里也是可以的。 1. 自定义 mask mask 组件通常会有一个特点:在不同页面不同模型或不同应用下都展示,与业务模型无关,且往往只需要请求一次。同时可能有精确控制请求体大小的需求,这就很适合采取手写 GraphQL 的方式。 例如,我要重写顶部 mask 中的用户组件,展示用户信息。这个请求就只需请求一次,而且不需要复用,就很适合手写 GraphQL。 这里继承平台的用户组件,然后在代码中写死 GraphQL 发起请求。但是 GraphQL 语句怎么拼呢?我们可以去默认页面,打开浏览器控制台,找到相应的请求,把 GraphQL 语句复制出来,这里复制下默认的用户请求。 http.query 参数的构造、相应结果的获取都能从请求中得到。可以看到我这里精简了请求,只取了用户名。 TS import { SPI, UserWidget, MaskWidget, Widget, http } from '@kunlun/dependencies'; import Test from './Test.vue'; @SPI.ClassFactory(MaskWidget.Token({ widget: 'user' })) export class TestWidget extends UserWidget { public initialize(props) { super.initialize(props); this.setComponent(Test); return this; } // 添加响应式注解,这样能在 vue 中接受到 ts 中的变量 @Widget.Reactive() public testUserInfo: { pamirsUser: { name: string } } | undefined; public async queryUser() { const query = ` { topBarUserBlockQuery { construct(data: {}) { pamirsUser { name } } } } `; const result = await http.query('user', query); this.testUserInfo = result.data['topBarUserBlockQuery']['construct'] as { pamirsUser: { name: string } }; } public mounted() { this.queryUser(); } } VUE <template> <div class="Test"> {{ testUserInfo }} </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; export default defineComponent({ name: 'Test', props: ['testUserInfo'] }); </script> 效果如下: 2. 自定义表格(表单)等视图元素组件 2-1. 自定义表格 2-1-1. 自定义表格自动获取数据 Oinone 提供了前端组件的默认实现。所以生成默认页面的时候,请求数据都是通的,可以看到表格、表单、表单里的字段等组件数据都是能回填的。所以这里继承平台的表格组件,就有了平台表格自动获取数据的能力。 TS import { BaseElementWidget, SPI, TABLE_WIDGET, TableWidget, ViewType } from '@kunlun/dependencies'; import Test from './Test.vue'; @SPI.ClassFactory( BaseElementWidget.Token({ viewType: ViewType.Table, widget:…

    2025年4月17日
    63800
  • 创建与编辑一体化

    在业务操作中,用户通常期望能够在创建页面后立即进行编辑,以减少频繁切换页面的步骤。我们可以充分利用Oinone平台提供的创建与编辑一体化功能,使操作更加高效便捷。 通过拖拽实现表单页面设计 在界面设计器中,我们首先需要设计出对应的页面。完成页面设计后,将需要的动作拖入设计好的页面。这个动作的关键在于支持一个功能,即根据前端传入的数据是否包含id来判断是创建操作还是编辑操作。 动作的属性配置如下: 前端自定义动作 一旦页面配置完成,前端需要对这个动作进行自定义。以下是一个示例的代码: @SPI.ClassFactory( ActionWidget.Token({ actionType: [ActionType.Server], model: '模型', name: '动作的名称' }) ) export class CreateOrUpdateServerActionWidget extends ServerActionWidget { @Widget.Reactive() protected get updateData(): boolean { return true; } } 通过以上步骤,我们实现了一个更智能的操作流程,使用户能够在创建页面的同时进行即时的编辑,从而提高了整体操作效率。这种创建与编辑一体化的功能不仅使操作更加顺畅,同时也为用户提供了更灵活的工作流程。

    2023年11月21日
    1.9K00

Leave a Reply

登录后才能评论