@creekjs/web-components 1.0.15 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,54 +1,54 @@
1
1
 
2
2
  
3
- > @creekjs/web-components@1.0.14 father:build /Users/ernestwang/Documents/code-resoorce/creek/packages/web-components
3
+ > @creekjs/web-components@1.0.15 father:build /Users/ernestwang/Documents/code-resoorce/creek/packages/web-components
4
4
  > father build
5
5
 
6
6
  info - Clean output directories
7
7
  info - Bundless for src directory to cjs format
8
8
  event - Bundless CreekConfigContext.tsx to dist/creek-config-provider/CreekConfigContext.js (with declaration)
9
- event - Bundless useViewportHeight.tsx to dist/creek-hooks/useViewportHeight.js (with declaration)
10
- event - Bundless type.ts to dist/creek-table/type.js (with declaration)
11
- event - Bundless useIndexColumn.tsx to dist/creek-table/hooks/useIndexColumn.js (with declaration)
12
- event - Bundless NotFoundPage.tsx to dist/creek-layout/Exception/NotFoundPage.js (with declaration)
13
- event - Bundless useTableOptions.tsx to dist/creek-table/hooks/useTableOptions.js (with declaration)
9
+ event - Bundless index.tsx to dist/creek-config-provider/index.js (with declaration)
10
+ event - Bundless ModalHelper.tsx to dist/creek-hooks/useApp/ModalHelper.js (with declaration)
11
+ event - Bundless index.ts to dist/creek-hooks/index.js (with declaration)
12
+ event - Bundless index.tsx to dist/creek-hooks/useApp/index.js (with declaration)
13
+ event - Bundless index.tsx to dist/creek-icon/index.js (with declaration)
14
14
  event - Bundless types.ts to dist/creek-hooks/useApp/types.js (with declaration)
15
- event - Bundless useEllipsisColumns.tsx to dist/creek-table/hooks/useEllipsisColumns.js (with declaration)
16
15
  event - Bundless DrawerHelper.tsx to dist/creek-hooks/useApp/DrawerHelper.js (with declaration)
17
- event - Bundless useElementDistance.tsx to dist/creek-table/hooks/useElementDistance.js (with declaration)
18
- event - Bundless useLayoutSettingsStore.ts to dist/creek-layout/useLayoutSettingsStore.js (with declaration)
16
+ event - Bundless useViewportHeight.tsx to dist/creek-hooks/useViewportHeight.js (with declaration)
17
+ event - Bundless FullScreen.tsx to dist/creek-layout/ActionRender/FullScreen.js (with declaration)
18
+ event - Bundless CreekI18nProvider.tsx to dist/creek-config-provider/CreekI18nProvider.js (with declaration)
19
+ event - Bundless index.tsx to dist/creek-layout/ActionRender/index.js (with declaration)
19
20
  event - Bundless UserInfo.tsx to dist/creek-layout/ActionRender/UserInfo.js (with declaration)
20
21
  event - Bundless NotFound.tsx to dist/creek-layout/Exception/NotFound.js (with declaration)
21
22
  event - Bundless index.tsx to dist/creek-layout/Exception/index.js (with declaration)
22
- event - Bundless scrollbar.ts to dist/creek-style/scrollbar.js (with declaration)
23
- event - Bundless index.tsx to dist/creek-table/components/index.js (with declaration)
23
+ event - Bundless NotFoundPage.tsx to dist/creek-layout/Exception/NotFoundPage.js (with declaration)
24
24
  event - Bundless index.ts to dist/creek-style/index.js (with declaration)
25
- event - Bundless index.tsx to dist/creek-layout/ActionRender/index.js (with declaration)
26
- event - Bundless useTableScrollHeight.tsx to dist/creek-table/hooks/useTableScrollHeight.js (with declaration)
25
+ event - Bundless LayoutSettings.tsx to dist/creek-layout/ActionRender/LayoutSettings.js (with declaration)
26
+ event - Bundless index.tsx to dist/creek-layout/index.js (with declaration)
27
+ event - Bundless index.tsx to dist/creek-page-container/index.js (with declaration)
28
+ event - Bundless useLayoutSettingsStore.ts to dist/creek-layout/useLayoutSettingsStore.js (with declaration)
29
+ event - Bundless scrollbar.ts to dist/creek-style/scrollbar.js (with declaration)
27
30
  event - Bundless DensityIcon.tsx to dist/creek-table/components/DensityIcon.js (with declaration)
31
+ event - Bundless index.tsx to dist/creek-loading/index.js (with declaration)
28
32
  event - Bundless index.tsx to dist/creek-locale-button/index.js (with declaration)
33
+ event - Bundless index.tsx to dist/creek-table/components/index.js (with declaration)
34
+ event - Bundless useElementDistance.tsx to dist/creek-table/hooks/useElementDistance.js (with declaration)
29
35
  event - Bundless useAdaptiveToolBar.tsx to dist/creek-table/hooks/useAdaptiveToolBar.js (with declaration)
30
- event - Bundless CreekI18nProvider.tsx to dist/creek-config-provider/CreekI18nProvider.js (with declaration)
31
- event - Bundless ModalHelper.tsx to dist/creek-hooks/useApp/ModalHelper.js (with declaration)
36
+ event - Bundless useIndexColumn.tsx to dist/creek-table/hooks/useIndexColumn.js (with declaration)
37
+ event - Bundless EllipsisTooltip.tsx to dist/creek-table/components/EllipsisTooltip.js (with declaration)
38
+ event - Bundless useAutoWidthColumns.tsx to dist/creek-table/hooks/useAutoWidthColumns.js (with declaration)
39
+ event - Bundless useEllipsisColumns.tsx to dist/creek-table/hooks/useEllipsisColumns.js (with declaration)
40
+ event - Bundless useTableOptions.tsx to dist/creek-table/hooks/useTableOptions.js (with declaration)
41
+ event - Bundless index.ts to dist/creek-table/hooks/index.js (with declaration)
32
42
  event - Bundless index.tsx to dist/creek-table/index.js (with declaration)
33
- event - Bundless zh_CN.ts to dist/locales/zh_CN.js (with declaration)
34
- event - Bundless FullScreen.tsx to dist/creek-layout/ActionRender/FullScreen.js (with declaration)
35
- event - Bundless index.ts to dist/creek-hooks/index.js (with declaration)
36
- event - Bundless CollapseButton.tsx to dist/creek-layout/CollapseButton.js (with declaration)
43
+ event - Bundless useTableScrollHeight.tsx to dist/creek-table/hooks/useTableScrollHeight.js (with declaration)
44
+ event - Bundless type.ts to dist/creek-table/type.js (with declaration)
37
45
  event - Bundless index.tsx to dist/index.js (with declaration)
46
+ event - Bundless SearchTable.tsx to dist/creek-table/SearchTable.js (with declaration)
47
+ event - Bundless zh_CN.ts to dist/locales/zh_CN.js (with declaration)
38
48
  event - Bundless en_US.ts to dist/locales/en_US.js (with declaration)
39
- event - Bundless index.tsx to dist/creek-page-container/index.js (with declaration)
40
- event - Bundless index.tsx to dist/creek-config-provider/index.js (with declaration)
41
- event - Bundless useAutoWidthColumns.tsx to dist/creek-table/hooks/useAutoWidthColumns.js (with declaration)
42
- event - Bundless index.tsx to dist/creek-hooks/useApp/index.js (with declaration)
43
- event - Bundless index.tsx to dist/creek-loading/index.js (with declaration)
44
- event - Bundless index.tsx to dist/creek-keep-alive/index.js (with declaration)
45
- event - Bundless index.tsx to dist/creek-icon/index.js (with declaration)
49
+ event - Bundless CollapseButton.tsx to dist/creek-layout/CollapseButton.js (with declaration)
46
50
  event - Bundless useStatusColumns.tsx to dist/creek-table/hooks/useStatusColumns.js (with declaration)
47
- event - Bundless SearchTable.tsx to dist/creek-table/SearchTable.js (with declaration)
48
- event - Bundless LayoutSettings.tsx to dist/creek-layout/ActionRender/LayoutSettings.js (with declaration)
49
- event - Bundless index.ts to dist/creek-table/hooks/index.js (with declaration)
50
- event - Bundless EllipsisTooltip.tsx to dist/creek-table/components/EllipsisTooltip.js (with declaration)
51
- event - Bundless index.tsx to dist/creek-layout/index.js (with declaration)
52
51
  event - Bundless useResizableColumns.tsx to dist/creek-table/hooks/useResizableColumns.js (with declaration)
52
+ event - Bundless index.tsx to dist/creek-keep-alive/index.js (with declaration)
53
53
  event - Generate declaration files...
54
- event - Transformed successfully in 6931 ms (45 files)
54
+ event - Transformed successfully in 3562 ms (45 files)
@@ -38,6 +38,8 @@ var CreekKeepAlive = (props) => {
38
38
  const [tabItems, setTabItems] = (0, import_react.useState)([]);
39
39
  const [activeKey, setActiveKey] = (0, import_react.useState)("");
40
40
  const [cachedPages, setCachedPages] = (0, import_react.useState)({});
41
+ const outletRef = (0, import_react.useRef)(outlet);
42
+ outletRef.current = outlet;
41
43
  const isPathExcluded = (path) => {
42
44
  return exclude.some((item) => {
43
45
  if ((0, import_lodash.isString)(item)) {
@@ -58,7 +60,7 @@ var CreekKeepAlive = (props) => {
58
60
  }
59
61
  return {
60
62
  ...prev,
61
- [currentPath]: outlet
63
+ [currentPath]: outletRef.current
62
64
  };
63
65
  });
64
66
  setTabItems((prev) => {
@@ -81,7 +83,7 @@ var CreekKeepAlive = (props) => {
81
83
  }
82
84
  return newItems;
83
85
  });
84
- }, [location.pathname, outlet, getTabTitle, maxTabCount]);
86
+ }, [location.pathname, getTabTitle, maxTabCount]);
85
87
  (0, import_react.useEffect)(() => {
86
88
  }, []);
87
89
  const closeTab = (0, import_ahooks.useMemoizedFn)((targetKey) => {
@@ -168,7 +170,7 @@ var CreekKeepAlive = (props) => {
168
170
  items: tabItems.map((item) => ({
169
171
  ...item,
170
172
  label: renderTabLabel(item),
171
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { height: "100%", display: activeKey === item.key ? "block" : "none" }, children: !isPathExcluded(item.key) || activeKey === item.key ? cachedPages[item.key] : null }, item.key)
173
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { height: "100%", display: activeKey === item.key ? "block" : "none" }, children: activeKey === item.key ? outlet : !isPathExcluded(item.key) ? cachedPages[item.key] : null }, item.key)
172
174
  }))
173
175
  }
174
176
  ) });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/creek-keep-alive/index.tsx"],
4
- "sourcesContent": ["import { useMemoizedFn } from 'ahooks';\nimport { Dropdown, MenuProps, Tabs } from 'antd';\nimport { isRegExp, isString, omit } from 'lodash';\nimport React, { useEffect, useState } from 'react';\nimport { useLocation, useNavigate, useOutlet } from 'react-router-dom';\n\nimport { useT } from '@creekjs/i18n/react';\n\nexport interface CreekKeepAliveProps {\n /**\n * 不需要缓存的路径\n */\n exclude?: (string | RegExp)[];\n /**\n * 自定义Tab标题获取方法\n */\n getTabTitle?: (pathname: string) => React.ReactNode;\n /**\n * Tabs的样式\n */\n tabBarStyle?: React.CSSProperties;\n /**\n * 最大缓存数量,默认为 20\n */\n maxTabCount?: number;\n}\n\ninterface TabItem {\n key: string;\n label: React.ReactNode;\n closable?: boolean;\n}\n\nexport const CreekKeepAlive: React.FC<CreekKeepAliveProps> = (props) => {\n const { exclude = [], getTabTitle, tabBarStyle, maxTabCount = 20 } = props;\n\n const t = useT();\n const outlet = useOutlet();\n const location = useLocation();\n const navigate = useNavigate();\n\n const [tabItems, setTabItems] = useState<TabItem[]>([]);\n const [activeKey, setActiveKey] = useState<string>('');\n const [cachedPages, setCachedPages] = useState<Record<string, React.ReactNode>>({});\n\n // 判断是否不需要缓存\n const isPathExcluded = (path: string) => {\n return exclude.some((item) => {\n if (isString(item)) {\n return item === path;\n }\n if (isRegExp(item)) {\n return item.test(path);\n }\n return false;\n });\n };\n\n // 初始化或路由变化时更新\n useEffect(() => {\n const currentPath = location.pathname;\n setActiveKey(currentPath);\n\n // 更新页面内容缓存\n setCachedPages((prev) => {\n if (prev[currentPath]) {\n return prev;\n }\n return {\n ...prev,\n [currentPath]: outlet,\n };\n });\n\n // 更新 Tab 列表\n setTabItems((prev) => {\n if (prev.find((i) => i.key === currentPath)) {\n // 更新现有 tab 的 closable 状态(只有最后一个 tab 时不可关闭)\n const updated = prev.map((i) => ({ ...i, closable: prev.length > 1 }));\n return updated;\n }\n const title = getTabTitle?.(currentPath) || currentPath;\n const newItems = [...prev, { key: currentPath, label: title, closable: prev.length > 0 }];\n\n // 更新所有 tab 的 closable 状态:只有1个 tab 时全部不可关闭\n if (newItems.length === 1) {\n newItems[0].closable = false;\n }\n\n // 超过最大数量限制\n if (newItems.length > maxTabCount) {\n // 找到第一个可以关闭的 Tab(非首页、非当前页)\n // 这里策略是移除最早加入的那个可关闭 Tab。prev[0] 是最早的。\n // 但要注意不要移除当前页(currentPath),虽然 currentPath 是刚加进去的,但在极端情况下(比如 max=1)\n // 简单策略:移除第一个 closable 且 key !== currentPath 的 item\n const indexToRemove = newItems.findIndex((item) => item.closable && item.key !== currentPath);\n if (indexToRemove !== -1) {\n const itemToRemove = newItems[indexToRemove];\n // 顺便移除缓存\n setCachedPages((currentCached) => omit(currentCached, [itemToRemove.key]));\n newItems.splice(indexToRemove, 1);\n }\n }\n return newItems;\n });\n }, [location.pathname, outlet, getTabTitle, maxTabCount]);\n\n // 清理不需要缓存的页面\n useEffect(() => {\n // 监听路由离开\n // 这里比较 tricky,因为 useEffect 拿到的 activeKey 已经是新的了\n // 我们需要知道\"上一个\"路径\n // 简化处理:每次 render 时,检查 pages 里哪些是不需要缓存且不处于 active 状态的,将其移除?\n // 但如果在 setState 里做会导致死循环。\n // 另一种策略:不缓存 = 离开时销毁。\n // 我们可以在 pages 渲染时控制。\n }, []);\n\n const closeTab = useMemoizedFn((targetKey: string) => {\n const targetIndex = tabItems.findIndex((item) => item.key === targetKey);\n const newTabItems = tabItems.filter((item) => item.key !== targetKey);\n\n // 移除缓存\n setCachedPages((prev) => omit(prev, [targetKey]));\n setTabItems(newTabItems);\n\n // 如果关闭的是当前页,跳转到临近页\n if (targetKey === activeKey) {\n if (newTabItems.length > 0) {\n // 尝试跳到右边,没有则左边\n const nextIndex = targetIndex >= newTabItems.length ? newTabItems.length - 1 : targetIndex;\n const nextKey = newTabItems[nextIndex].key;\n navigate(nextKey);\n }\n }\n });\n\n const closeOtherTabs = useMemoizedFn((currentKey: string) => {\n const currentTab = tabItems.find((item) => item.key === currentKey);\n if (!currentTab) return;\n const newTabItems = [{ ...currentTab, closable: false }];\n setTabItems(newTabItems);\n\n const keepKeys = newTabItems.map((i) => i.key);\n setCachedPages((prev) => {\n const newCachedPages: Record<string, React.ReactNode> = {};\n keepKeys.forEach((k) => {\n if (prev[k]) newCachedPages[k] = prev[k];\n });\n return newCachedPages;\n });\n\n if (activeKey !== currentKey) {\n navigate(currentKey);\n }\n });\n\n const closeRightTabs = useMemoizedFn((currentKey: string) => {\n const currentIndex = tabItems.findIndex((i) => i.key === currentKey);\n const rightItems = tabItems.slice(currentIndex + 1);\n const rightKeys = rightItems.map((i) => i.key);\n\n const newTabItems = tabItems.filter((i) => !rightKeys.includes(i.key));\n setTabItems(newTabItems);\n\n setCachedPages((prev) => omit(prev, rightKeys));\n\n if (rightKeys.includes(activeKey)) {\n navigate(currentKey);\n }\n });\n\n const handleTabEdit = (targetKey: React.MouseEvent | React.KeyboardEvent | string, action: 'add' | 'remove') => {\n if (action === 'remove' && isString(targetKey)) {\n closeTab(targetKey);\n }\n };\n\n const handleTabClick = (key: string) => {\n navigate(key);\n };\n\n const renderTabLabel = (item: TabItem) => {\n const menuItems: MenuProps['items'] = [\n {\n key: 'close',\n label: t('creek-keep-alive.index.guanBiDangQian', '关闭当前'),\n disabled: tabItems.length <= 1,\n onClick: () => closeTab(item.key),\n },\n {\n key: 'closeOthers',\n label: t('creek-keep-alive.index.guanBiQiTa', '关闭其他'),\n onClick: () => closeOtherTabs(item.key),\n },\n {\n key: 'closeRight',\n label: t('creek-keep-alive.index.guanBiYouCe', '关闭右侧'),\n onClick: () => closeRightTabs(item.key),\n },\n ];\n\n return (\n <Dropdown menu={{ items: menuItems }} trigger={['contextMenu']}>\n <span>{item.label}</span>\n </Dropdown>\n );\n };\n\n return (\n <div className=\"creek-keep-alive\">\n <Tabs\n activeKey={activeKey}\n type=\"editable-card\"\n hideAdd\n onChange={handleTabClick}\n onEdit={handleTabEdit}\n tabBarStyle={{ margin: 0, ...tabBarStyle }}\n items={tabItems.map((item) => ({\n ...item,\n label: renderTabLabel(item),\n children: (\n <div key={item.key} style={{ height: '100%', display: activeKey === item.key ? 'block' : 'none' }}>\n {/* 如果是不缓存的页面,且不是当前页,则不渲染(销毁) */}\n {/* 如果是缓存页面,或者是当前页,则渲染 */}\n {!isPathExcluded(item.key) || activeKey === item.key ? cachedPages[item.key] : null}\n </div>\n ),\n }))}\n />\n </div>\n );\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { useMemoizedFn } from 'ahooks';\nimport { Dropdown, MenuProps, Tabs } from 'antd';\nimport { isRegExp, isString, omit } from 'lodash';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useLocation, useNavigate, useOutlet } from 'react-router-dom';\n\nimport { useT } from '@creekjs/i18n/react';\n\nexport interface CreekKeepAliveProps {\n /**\n * 不需要缓存的路径\n */\n exclude?: (string | RegExp)[];\n /**\n * 自定义Tab标题获取方法\n */\n getTabTitle?: (pathname: string) => React.ReactNode;\n /**\n * Tabs的样式\n */\n tabBarStyle?: React.CSSProperties;\n /**\n * 最大缓存数量,默认为 20\n */\n maxTabCount?: number;\n}\n\ninterface TabItem {\n key: string;\n label: React.ReactNode;\n closable?: boolean;\n}\n\nexport const CreekKeepAlive: React.FC<CreekKeepAliveProps> = (props) => {\n const { exclude = [], getTabTitle, tabBarStyle, maxTabCount = 20 } = props;\n\n const t = useT();\n const outlet = useOutlet();\n const location = useLocation();\n const navigate = useNavigate();\n\n const [tabItems, setTabItems] = useState<TabItem[]>([]);\n const [activeKey, setActiveKey] = useState<string>('');\n const [cachedPages, setCachedPages] = useState<Record<string, React.ReactNode>>({});\n\n // 用 ref 存储 outlet,避免 outlet 引用变化导致 useEffect 无限循环\n const outletRef = useRef(outlet);\n outletRef.current = outlet;\n\n // 判断是否不需要缓存\n const isPathExcluded = (path: string) => {\n return exclude.some((item) => {\n if (isString(item)) {\n return item === path;\n }\n if (isRegExp(item)) {\n return item.test(path);\n }\n return false;\n });\n };\n\n // 初始化或路由变化时更新\n useEffect(() => {\n const currentPath = location.pathname;\n setActiveKey(currentPath);\n\n // 更新页面内容缓存\n setCachedPages((prev) => {\n if (prev[currentPath]) {\n return prev;\n }\n return {\n ...prev,\n [currentPath]: outletRef.current,\n };\n });\n\n // 更新 Tab 列表\n setTabItems((prev) => {\n if (prev.find((i) => i.key === currentPath)) {\n // 更新现有 tab 的 closable 状态(只有最后一个 tab 时不可关闭)\n const updated = prev.map((i) => ({ ...i, closable: prev.length > 1 }));\n return updated;\n }\n const title = getTabTitle?.(currentPath) || currentPath;\n const newItems = [...prev, { key: currentPath, label: title, closable: prev.length > 0 }];\n\n // 更新所有 tab 的 closable 状态:只有1个 tab 时全部不可关闭\n if (newItems.length === 1) {\n newItems[0].closable = false;\n }\n\n // 超过最大数量限制\n if (newItems.length > maxTabCount) {\n // 找到第一个可以关闭的 Tab(非首页、非当前页)\n // 这里策略是移除最早加入的那个可关闭 Tab。prev[0] 是最早的。\n // 但要注意不要移除当前页(currentPath),虽然 currentPath 是刚加进去的,但在极端情况下(比如 max=1)\n // 简单策略:移除第一个 closable 且 key !== currentPath 的 item\n const indexToRemove = newItems.findIndex((item) => item.closable && item.key !== currentPath);\n if (indexToRemove !== -1) {\n const itemToRemove = newItems[indexToRemove];\n // 顺便移除缓存\n setCachedPages((currentCached) => omit(currentCached, [itemToRemove.key]));\n newItems.splice(indexToRemove, 1);\n }\n }\n return newItems;\n });\n }, [location.pathname, getTabTitle, maxTabCount]);\n\n // 清理不需要缓存的页面\n useEffect(() => {\n // 监听路由离开\n // 这里比较 tricky,因为 useEffect 拿到的 activeKey 已经是新的了\n // 我们需要知道\"上一个\"路径\n // 简化处理:每次 render 时,检查 pages 里哪些是不需要缓存且不处于 active 状态的,将其移除?\n // 但如果在 setState 里做会导致死循环。\n // 另一种策略:不缓存 = 离开时销毁。\n // 我们可以在 pages 渲染时控制。\n }, []);\n\n const closeTab = useMemoizedFn((targetKey: string) => {\n const targetIndex = tabItems.findIndex((item) => item.key === targetKey);\n const newTabItems = tabItems.filter((item) => item.key !== targetKey);\n\n // 移除缓存\n setCachedPages((prev) => omit(prev, [targetKey]));\n setTabItems(newTabItems);\n\n // 如果关闭的是当前页,跳转到临近页\n if (targetKey === activeKey) {\n if (newTabItems.length > 0) {\n // 尝试跳到右边,没有则左边\n const nextIndex = targetIndex >= newTabItems.length ? newTabItems.length - 1 : targetIndex;\n const nextKey = newTabItems[nextIndex].key;\n navigate(nextKey);\n }\n }\n });\n\n const closeOtherTabs = useMemoizedFn((currentKey: string) => {\n const currentTab = tabItems.find((item) => item.key === currentKey);\n if (!currentTab) return;\n const newTabItems = [{ ...currentTab, closable: false }];\n setTabItems(newTabItems);\n\n const keepKeys = newTabItems.map((i) => i.key);\n setCachedPages((prev) => {\n const newCachedPages: Record<string, React.ReactNode> = {};\n keepKeys.forEach((k) => {\n if (prev[k]) newCachedPages[k] = prev[k];\n });\n return newCachedPages;\n });\n\n if (activeKey !== currentKey) {\n navigate(currentKey);\n }\n });\n\n const closeRightTabs = useMemoizedFn((currentKey: string) => {\n const currentIndex = tabItems.findIndex((i) => i.key === currentKey);\n const rightItems = tabItems.slice(currentIndex + 1);\n const rightKeys = rightItems.map((i) => i.key);\n\n const newTabItems = tabItems.filter((i) => !rightKeys.includes(i.key));\n setTabItems(newTabItems);\n\n setCachedPages((prev) => omit(prev, rightKeys));\n\n if (rightKeys.includes(activeKey)) {\n navigate(currentKey);\n }\n });\n\n const handleTabEdit = (targetKey: React.MouseEvent | React.KeyboardEvent | string, action: 'add' | 'remove') => {\n if (action === 'remove' && isString(targetKey)) {\n closeTab(targetKey);\n }\n };\n\n const handleTabClick = (key: string) => {\n navigate(key);\n };\n\n const renderTabLabel = (item: TabItem) => {\n const menuItems: MenuProps['items'] = [\n {\n key: 'close',\n label: t('creek-keep-alive.index.guanBiDangQian', '关闭当前'),\n disabled: tabItems.length <= 1,\n onClick: () => closeTab(item.key),\n },\n {\n key: 'closeOthers',\n label: t('creek-keep-alive.index.guanBiQiTa', '关闭其他'),\n onClick: () => closeOtherTabs(item.key),\n },\n {\n key: 'closeRight',\n label: t('creek-keep-alive.index.guanBiYouCe', '关闭右侧'),\n onClick: () => closeRightTabs(item.key),\n },\n ];\n\n return (\n <Dropdown menu={{ items: menuItems }} trigger={['contextMenu']}>\n <span>{item.label}</span>\n </Dropdown>\n );\n };\n\n return (\n <div className=\"creek-keep-alive\">\n <Tabs\n activeKey={activeKey}\n type=\"editable-card\"\n hideAdd\n onChange={handleTabClick}\n onEdit={handleTabEdit}\n tabBarStyle={{ margin: 0, ...tabBarStyle }}\n items={tabItems.map((item) => ({\n ...item,\n label: renderTabLabel(item),\n children: (\n <div key={item.key} style={{ height: '100%', display: activeKey === item.key ? 'block' : 'none' }}>\n {/* 当前激活页渲染实时outlet,非激活页渲染缓存 */}\n {activeKey === item.key\n ? outlet\n : !isPathExcluded(item.key)\n ? cachedPages[item.key]\n : null}\n </div>\n ),\n }))}\n />\n </div>\n );\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_react"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@creekjs/web-components",
3
- "version": "1.0.15",
3
+ "version": "1.0.16",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "keywords": [],
@@ -1,7 +1,7 @@
1
1
  import { useMemoizedFn } from 'ahooks';
2
2
  import { Dropdown, MenuProps, Tabs } from 'antd';
3
3
  import { isRegExp, isString, omit } from 'lodash';
4
- import React, { useEffect, useState } from 'react';
4
+ import React, { useEffect, useRef, useState } from 'react';
5
5
  import { useLocation, useNavigate, useOutlet } from 'react-router-dom';
6
6
 
7
7
  import { useT } from '@creekjs/i18n/react';
@@ -43,6 +43,10 @@ export const CreekKeepAlive: React.FC<CreekKeepAliveProps> = (props) => {
43
43
  const [activeKey, setActiveKey] = useState<string>('');
44
44
  const [cachedPages, setCachedPages] = useState<Record<string, React.ReactNode>>({});
45
45
 
46
+ // 用 ref 存储 outlet,避免 outlet 引用变化导致 useEffect 无限循环
47
+ const outletRef = useRef(outlet);
48
+ outletRef.current = outlet;
49
+
46
50
  // 判断是否不需要缓存
47
51
  const isPathExcluded = (path: string) => {
48
52
  return exclude.some((item) => {
@@ -68,7 +72,7 @@ export const CreekKeepAlive: React.FC<CreekKeepAliveProps> = (props) => {
68
72
  }
69
73
  return {
70
74
  ...prev,
71
- [currentPath]: outlet,
75
+ [currentPath]: outletRef.current,
72
76
  };
73
77
  });
74
78
 
@@ -103,7 +107,7 @@ export const CreekKeepAlive: React.FC<CreekKeepAliveProps> = (props) => {
103
107
  }
104
108
  return newItems;
105
109
  });
106
- }, [location.pathname, outlet, getTabTitle, maxTabCount]);
110
+ }, [location.pathname, getTabTitle, maxTabCount]);
107
111
 
108
112
  // 清理不需要缓存的页面
109
113
  useEffect(() => {
@@ -221,9 +225,12 @@ export const CreekKeepAlive: React.FC<CreekKeepAliveProps> = (props) => {
221
225
  label: renderTabLabel(item),
222
226
  children: (
223
227
  <div key={item.key} style={{ height: '100%', display: activeKey === item.key ? 'block' : 'none' }}>
224
- {/* 如果是不缓存的页面,且不是当前页,则不渲染(销毁) */}
225
- {/* 如果是缓存页面,或者是当前页,则渲染 */}
226
- {!isPathExcluded(item.key) || activeKey === item.key ? cachedPages[item.key] : null}
228
+ {/* 当前激活页渲染实时outlet,非激活页渲染缓存 */}
229
+ {activeKey === item.key
230
+ ? outlet
231
+ : !isPathExcluded(item.key)
232
+ ? cachedPages[item.key]
233
+ : null}
227
234
  </div>
228
235
  ),
229
236
  }))}