Skip to content

Commit

Permalink
feat(tabs): 优化代码风格,修复样式错误
Browse files Browse the repository at this point in the history
  • Loading branch information
vaebe committed Sep 16, 2024
1 parent 3606986 commit f2873ee
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 124 deletions.
22 changes: 11 additions & 11 deletions packages/ccui/ui/tabs/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import type { App } from 'vue';
import Tabs from './src/tabs';
import Tab from './src/components/tab/tab';
import type { App } from 'vue'
import Tab from './src/components/tab/tab'
import Tabs from './src/tabs'

Tabs.install = function (app: App): void {
app.component(Tabs.name, Tabs);
app.component(Tab.name, Tab);
};
app.component(Tabs.name, Tabs)
app.component(Tab.name, Tab)
}

export { Tabs, Tab };
export { Tab, Tabs }

export default {
title: 'Tabs 选项卡',
category: '导航',
status: undefined, // TODO: 组件若开发完成则填入"100%",并删除该注释
install(app: App): void {
app.component(Tabs.name, Tabs);
app.component(Tab.name, Tab);
}
};
app.component(Tabs.name, Tabs)
app.component(Tab.name, Tab)
},
}
18 changes: 9 additions & 9 deletions packages/ccui/ui/tabs/src/components/tab/tab-types.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { ExtractPropTypes, PropType } from 'vue';
import type { ExtractPropTypes, PropType } from 'vue'

export type LabelType = string | number;
export type NameType = string | number;
export type LabelType = string | number
export type NameType = string | number

export const tabProps = {
label: {
type: [String, Number] as PropType<LabelType>,
default: null
default: null,
},
name: {
type: [String, Number] as PropType<NameType>,
default: null
default: null,
},
disabled: {
type: Boolean,
default: false
}
} as const;
default: false,
},
} as const

export type TabProps = ExtractPropTypes<typeof tabProps>;
export type TabProps = ExtractPropTypes<typeof tabProps>
40 changes: 22 additions & 18 deletions packages/ccui/ui/tabs/src/components/tab/tab.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,37 @@
import { defineComponent, inject, onUnmounted } from 'vue';
import { tabsInjectionKey, TabsState } from '../../tabs-types';
import { tabProps, TabProps } from './tab-types';
import './tab.scss';
import { useNamespace } from '../../../../shared/hooks/use-namespace';
import { defineComponent, inject, onUnmounted } from 'vue'
import type { TabsState } from '../../tabs-types'
import { useNamespace } from '../../../../shared/hooks/use-namespace'
import { tabsInjectionKey } from '../../tabs-types'
import type { TabProps } from './tab-types'
import { tabProps } from './tab-types'
import './tab.scss'

export default defineComponent({
name: 'CTab',
props: tabProps,
emits: [],
setup(props: TabProps, { slots }) {
const ns = useNamespace('tab');
const ns = useNamespace('tab')

const tabsState = inject<TabsState>(tabsInjectionKey);
tabsState?.data?.push(props);
tabsState?.slots?.push(slots);
const tabsState = inject<TabsState>(tabsInjectionKey)
tabsState?.data?.push(props)
tabsState?.slots?.push(slots)

// 组件卸载移除 组件props数据缓存
onUnmounted(() => {
if (tabsState) {
tabsState.data = tabsState.data?.filter(
(item) => item.name !== props.name
);
item => item.name !== props.name,
)
}
});
})

return () => {
return props.name === tabsState?.active ? (
<div class={ns.b()}>{slots.default && slots.default()}</div>
) : null;
};
}
});
return props.name === tabsState?.active
? (
<div class={ns.b()}>{slots.default && slots.default()}</div>
)
: null
}
},
})
66 changes: 34 additions & 32 deletions packages/ccui/ui/tabs/src/components/tabs-nav/index.tsx
Original file line number Diff line number Diff line change
@@ -1,72 +1,74 @@
import { defineComponent, inject, computed } from 'vue';
import type {
TabsProps,
TabsState,
} from '../../tabs-types'
import type { TabProps } from '../tab/tab-types'
import { computed, defineComponent, inject } from 'vue'
import { useNamespace } from '../../../../shared/hooks/use-namespace'
import {
tabsInjectionKey,
tabsProps,
TabsProps,
TabsState
} from '../../tabs-types';
import { TabProps } from '../tab/tab-types';
import './tabs-nav.scss';
import { useNamespace } from '../../../../shared/hooks/use-namespace';
} from '../../tabs-types'
import './tabs-nav.scss'

export default defineComponent({
name: 'CTabs-nav',
props: tabsProps,
emits: ['active-tab-change'],
setup(props: TabsProps, { emit }) {
const ns = useNamespace('tabs-nav');
const ns = useNamespace('tabs-nav')

const tabsState = inject<TabsState>(tabsInjectionKey);
const tabsState = inject<TabsState>(tabsInjectionKey)

const navList = computed(() => tabsState?.data || []);
const slotsList = computed(() => tabsState?.slots || []);
const navList = computed(() => tabsState?.data || [])
const slotsList = computed(() => tabsState?.slots || [])

const containerClass = computed(() => {
let cls = ns.b();
let cls = ns.b()
if (props.type) {
cls += `-${props.type}`;
cls += `-${props.type}`
}
return `${cls}--${props.tabPosition}`;
});
return `${cls}--${props.tabPosition}`
})

const getNavItemClass = (item: TabProps) => {
const itemClass = `${containerClass.value}-item`;
const itemActiveClass =
tabsState?.active === item.name ? `${itemClass}-active` : '';
const itemClass = `${containerClass.value}-item`
const itemActiveClass
= tabsState?.active === item.name ? `${itemClass}-active` : ''

return `${itemClass} ${itemActiveClass}`;
};
return `${itemClass} ${itemActiveClass}`
}

const navItemClick = (item: TabProps) => {
if (tabsState) {
// 相同不进行切换
if (tabsState.active === item.name) {
return;
return
}

emit('active-tab-change', item.name);
emit('active-tab-change', item.name)
}
};
}

const navItemDom = computed(() => {
return navList.value.map((item, index) => {
const curSlotTitle = slotsList.value[index];
const curSlotTitle = slotsList.value[index]

return (
<p
class={getNavItemClass(item)}
onClick={() => {
navItemClick(item);
navItemClick(item)
}}
>
{curSlotTitle.title ? curSlotTitle.title() : item.label}
</p>
);
});
});
)
})
})

return () => {
return <div class={containerClass.value}>{navItemDom.value}</div>;
};
}
});
return <div class={containerClass.value}>{navItemDom.value}</div>
}
},
})
6 changes: 5 additions & 1 deletion packages/ccui/ui/tabs/src/components/tabs-nav/tabs-nav.scss
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
border-bottom: 2px solid transparent;

&:first-of-type {
border: 1px solid $ccui-line;
border-left: 1px solid $ccui-line;
border-top-left-radius: $ccui-border-radius;
}

Expand Down Expand Up @@ -237,6 +237,10 @@
background: $ccui-base-bg;
border-right: 1px solid $ccui-line;
border-left: 1px solid $ccui-line;

&:first-of-type {
border-left: unset;
}
}
}

Expand Down
50 changes: 25 additions & 25 deletions packages/ccui/ui/tabs/src/tabs-types.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,64 @@
import type {
ComputedRef,
ExtractPropTypes,
InjectionKey,
PropType,
InjectionKey
} from 'vue';
import { TabProps } from './components/tab/tab-types';
} from 'vue'
import type { TabProps } from './components/tab/tab-types'

export type ModelValueType = string | number;
export type ModelValueType = string | number

export type ITabsType = '' | 'card' | 'border-card';
export type ITabsType = '' | 'card' | 'border-card'

export type ITabPositionType = 'top' | 'right' | 'bottom' | 'left';
export type ITabPositionType = 'top' | 'right' | 'bottom' | 'left'

export type Active = string | number | null;
export type BeforeChangeType = (id: Active) => boolean;
export type Active = string | number | null
export type BeforeChangeType = (id: Active) => boolean

export interface TabsState {
data?: TabProps[];
active: string | number;
slots: any[];
data?: TabProps[]
active: string | number
slots: any[]
}

export const tabsProps = {
modelValue: {
type: [String, Number] as PropType<ModelValueType>,
default: null
default: null,
},
type: {
type: String as () => ITabsType,
default: ''
default: '',
},
customWidth: {
type: String,
default: ''
default: '',
},
cssClass: {
type: String,
default: ''
default: '',
},
beforeChange: {
type: Function as PropType<BeforeChangeType>,
default: null
default: null,
},
tabPosition: {
type: String as () => ITabPositionType,
default: 'top'
}
} as const;
default: 'top',
},
} as const

export type TabsProps = ExtractPropTypes<typeof tabsProps>;
export type TabsProps = ExtractPropTypes<typeof tabsProps>

export interface UseTabsEvent {
onUpdateModelValue: (value: string | number) => void;
onActiveTabChange: (value: string) => void;
onTabChange: (id: string | undefined, type: string) => void;
onUpdateModelValue: (value: string | number) => void
onActiveTabChange: (value: string) => void
onTabChange: (id: string | undefined, type: string) => void
}

/** KTabs 注入 tab 的 key 值 */
export const tabsInjectionKey: InjectionKey<TabsState> = Symbol('CTabs');
export const tabsInjectionKey: InjectionKey<TabsState> = Symbol('CTabs')

export interface UseTabsRender {
tabsClasses: ComputedRef<Record<string, boolean>>;
tabsClasses: ComputedRef<Record<string, boolean>>
}
Loading

0 comments on commit f2873ee

Please sign in to comment.