vueComponent / pro-components

easy use `Ant Design Vue` layout
MIT License
532 stars 215 forks source link

[Question] Help 有没有遇到过pro-layout 默认插槽中使用RouterView,而RouterView再使用插槽渲染当前页面对应组件,组件会渲染两次的情况? #251

Open YTT-TTY opened 1 year ago

YTT-TTY commented 1 year ago

🧐 问题描述 Problem Description

有没有遇到过pro-layout 默认插槽中使用RouterView,而RouterView再使用插槽渲染当前页面对应组件,组件会渲染两次的情况?

💻 示例代码 Sample code

const BasicLayout = defineComponent({ setup(props, { slots }) { const multiTabState = useMultiTabStateProvider(); const { layoutConfig, locale, collapsed, selectedKeys, openKeys, menuData, breadcrumb, sideWidth } = useMenuState(multiTabState);

    const breadcrumbRender = ({ route, params, routes }: Breadcrumb) => (
        routes.indexOf(route) === routes.length - 1 ? <span> {route.breadcrumbName}</span>
            : <RouterLink to={{ path: route.path, params }}>{route.breadcrumbName}</RouterLink>
    )

    return () => (
        <ProLayout
            logo={`${process.env.VUE_APP_PUBLIC_PATH}logo.png`}
            locale={locale}
            {...layoutConfig}
            menuData={menuData}
            v-models={[
                [collapsed.value, 'collapsed'],
                [selectedKeys.value, 'selectedKeys'],
                [openKeys.value, 'openKeys'],
            ]}
            breadcrumb={{ routes: breadcrumb.value }}
            v-slots={{
                default: () => <>
                    {SettingConfig.multiTab && <MultiTab fixed={SettingConfig.multiTabFixed} />}

                    <div class={[{ 'ant-layout-content-has-multiTab': SettingConfig.multiTab }]}>
                        <RouterView
                            // TODO优化:会渲染两次
                            v-slots={{
                                default: ({ Component, route }: RouterViewSlot) => (

                                    h(Component)

                                )
                            }}
                        />
                    </div>

                </>,
                breadcrumbRender: ({ route, params, routes }: Breadcrumb) => breadcrumbRender({ route, params, routes }),
                rightContentRender: () => <RightContent />
            }}
        />
    )
}

});

🚑 其他信息 Other information

组件对应代码以及浏览器打印渲染信息

code 页面

lolarun commented 1 year ago

首先,个人建议还是用SFC吧,这TSX写得太碎了.... 其次,定位问题建议使用“最小化”原则,即:新建一个“干净”的项目,并引入最少元素。已经说过无数次了,就是不听。

新建项目,使用这个BasicLayout.tsx,即可验证ProLayout的默认插槽中使用RouterView,并不会引发渲染两次的问题。

import { defineComponent, h, type VNode } from 'vue';
import { RouterView } from 'vue-router';
import ProLayout from '@ant-design-vue/pro-layout';

export default defineComponent({
  setup() {
    return () => (
      <ProLayout>
        <RouterView
          v-slots={{
            default: ({ Component }: { Component: VNode }) => h(Component),
          }}
        />
      </ProLayout>
    );
  },
});

最后,多次渲染理的问题大多数是因为状态(响应式数据)发生了变化,建议尝试将多页签相关的代码注释后再试一下,或者直接watch一下SettingConfig

唉,就这?

YTT-TTY commented 1 year ago

我创建一个“干净”的项目,并引入了最少元素,还是会打印出来两遍啊

lolarun commented 1 year ago

https://github.com/lolarun/codesandbox

Sandbox preview