其他

全局配置

为组件提供统一的全局化配置。

使用场景

覆盖配置分为两种场景

  • 需要覆盖多个组件公有 Props 配置(例如 timezone、rtl),使用 ConfigProvider
  • 当 ConfigProvider 暴露参数未能满足,希望修改全局修改某个组件的 某类 Props(例如期望将所有Button的 theme 都配置为 solid 或所有 Popover的 position),使用 semiGlobal

ConfigProvider

ConfigProvider 借助 provide / inject 实现,因此它能影响组件树中的子组件。ConfigProvider、ConfigConsumer 丢弃未声明的属性,class、style 等不会落到 DOM 上。

代码演示

如何引入

<script setup lang="ts">
    import { ConfigProvider, ConfigConsumer, useConfig } from '@fibrous/semi-ui-vue';
</script>

基本用法

通过传入 timeZone 参数,用户可以为时间类组件配置时区:

Select Time Zone:




代码
<script setup lang="ts">
    import { ref } from 'vue';
    import { ConfigProvider, DatePicker, Select, TimePicker } from '@fibrous/semi-ui-vue';

    const timeZone = ref('GMT+08:00');
    const defaultTimestamp = 1581599305265;
    const gmtList: string[] = [];
    for (let hourOffset = -11; hourOffset <= 14; hourOffset++) {
        const prefix = hourOffset >= 0 ? '+' : '-';
        gmtList.push(`GMT${prefix}${String(Math.abs(hourOffset)).padStart(2, '0')}:00`);
    }
    // fractional offsets stay fixed all year; an IANA name follows its daylight saving time
    gmtList.push('GMT-03:30', 'GMT+05:45', 'GMT+13:45', 'America/New_York');
</script>

<template>
    <ConfigProvider :timeZone="timeZone">
        <div :style="{ width: '300px' }">
            <h5 :style="{ margin: '10px' }">Select Time Zone:</h5>
            <Select aria-label="时区" :modelValue="timeZone" placeholder="请选择时区" showClear :style="{ width: '300px' }" @select="(value) => (timeZone = String(value))">
                <Select.Option v-for="gmt in gmtList" :key="gmt" :value="gmt">{{ gmt }}</Select.Option>
            </Select>
            <br />
            <br />
            <DatePicker :defaultValue="defaultTimestamp" type="dateTime" @change="(date, dateString) => console.log('DatePicker changed: ', date, dateString)" />
            <br />
            <br />
            <TimePicker :defaultValue="defaultTimestamp" @change="(date, dateString) => console.log('DatePicker changed: ', date, dateString)" />
        </div>
    </ConfigProvider>
</template>

手动获取值

通常情况下,组件内部会自动获取 ConfigProvider 的值自动消费,无需关心。但是一些特殊场景,你可能需要手动获取值来进行其他操作。

使用 ConfigConsumer 的默认作用域插槽获取 ConfigProvider 的值;在子组件的 <script setup> 中也可以调用 useConfig(),它返回 ComputedRef<ContextValue>,没有 ConfigProvider 时为空对象。

{"direction":"ltr","timeZone":"GMT+08:00","responsiveObserve":false,"responsiveMap":{"xs":"(max-width: 575px)","sm":"(min-width: 576px)","md":"(min-width: 768px)","lg":"(min-width: 992px)","xl":"(min-width: 1200px)","xxl":"(min-width: 1600px)"},"screens":{"xs":false,"sm":false,"md":false,"lg":false,"xl":false,"xxl":false}}
代码
<script setup lang="ts">
    import { ConfigConsumer, ConfigProvider, TypographyText } from '@fibrous/semi-ui-vue';
</script>

<template>
    <ConfigProvider timeZone="GMT+08:00">
        <ConfigConsumer #default="value">
            <TypographyText :ellipsis="{ showTooltip: { opts: { style: { minWidth: '1200px' } } } }" :style="{ width: '600px' }">
                {{ JSON.stringify(value) }}
            </TypographyText>
        </ConfigConsumer>
    </ConfigProvider>
</template>

响应式断点监听

ConfigProvider 支持配置响应式断点,并在断点变化时进行订阅回调。

开启监听与自定义断点

  • 通过 responsiveObserve 开启断点监听(建议只在确实需要订阅的场景开启)
  • 通过 responsiveMap 自定义断点(未传入时使用默认断点)
<!-- breakpoint-subscriber.vue -->
<script setup lang="ts">
    import { onBeforeUnmount, onMounted, ref } from 'vue';
    import { TypographyText, useConfig } from '@fibrous/semi-ui-vue';

    const config = useConfig();
    const screens = ref(config.value.screens);
    let unsubscribe: (() => void) | undefined;

    onMounted(() => {
        unsubscribe = config.value.onBreakpoint?.((next) => {
            screens.value = next;
        });
    });
    onBeforeUnmount(() => unsubscribe?.());
</script>

<template>
    <TypographyText>{{ JSON.stringify(screens) }}</TypographyText>
</template>
<script setup lang="ts">
    import { ConfigProvider } from '@fibrous/semi-ui-vue';
    import BreakpointSubscriber from './breakpoint-subscriber.vue';

    const responsiveMap = {
        xs: '(max-width: 575px)',
        sm: '(min-width: 576px)',
        md: '(min-width: 768px)',
        lg: '(min-width: 992px)',
        xl: '(min-width: 1200px)',
        xxl: '(min-width: 1600px)',
    };
</script>

<template>
    <ConfigProvider responsiveObserve :responsiveMap="responsiveMap">
        <BreakpointSubscriber />
    </ConfigProvider>
</template>

订阅 API

onBreakpoint 支持两种签名,均会返回取消订阅函数:

  • onBreakpoint((screens) => void):回调拿到完整的 screens 映射
  • onBreakpoint(['md', 'lg'], (screen, match) => void):只监听指定断点,回调拿到单个断点变化

RTL/LTR

全局配置 direction 可以改变组件的文本方向。

rtl 表示从右到左 (类似希伯来语或阿拉伯语), ltr 表示从左到右 (类似中文、英语等大部分语言)。显式传入的 direction 与外层不同时(含最外层),ConfigProvider 会在内容外包一层带 dir 属性的 div。组件的 RTL 样式用 :dir(rtl) 匹配,跟随最近的祖先 dir 属性;弹层根元素按 ConfigProvider 的 direction 输出 dir。页面自己在 <html> 等元素上设置 dir="rtl" 时,页面内的组件样式按 RTL 显示,但键盘方向、弹层位置等逻辑只读 ConfigProvider 的 direction,ConfigProvider 内的弹层与 Table 也按它的 direction(默认 ltr)显示,因此仍需同时设置 direction="rtl"。

特殊组件:

  • Modal,Notification,Toast 的命令式调用需要通过 prop 传 direction。
  • 如果你想对有方向性的 Icon 做 RTL 国际化,需要自己单独进行处理。我们认为对 Icon 进行 RTL 会让它变得难以理解和维护。其他组件内的 icon Semi 已经做了 RTL 适配。
  • Table 的树形数据暂不支持 RTL(Chrome、Safari 浏览器表现与 Firefox 表现不同),固定列支持 RTL。

Vue 的命令式调用读不到 ConfigProvider(它是组件级 provide),需要跟随方向时在选项里传 direction,或改用 Modal.useModal()、Toast.useToast()、Notification.useNotification(),它们返回的 Holder 组件渲染在哪里,就继承哪里的 ConfigProvider。

Buttons



Input





Prefix


Suffix


0/100


多选框
禁用的多选框
禁用的多选框










Navigation




Finished
This is a description.
2
In Progress
This is a description.
3
Waiting
This is a description.

Finished
This is a description
In Process
This is a description
3
Waiting
This is a description

Display

XZ5
YB5
LX5
YZ
HW
XM

grey tag
blue tag
ghost tag
solid tag
red tag
green tag
orange tag
teal tag
violet tag
white tag

I am Popover
I am Tooltip

  • 审核中
    2019-07-14 10:35
  • 发布成功
    2019-06-13 16:17
  • 审核失败
    2019-05-14 18:34

Feedback





I am loading...

Here are some texts.

And more texts on the way.

代码
<script setup lang="ts">
    import { h, ref, type CSSProperties } from 'vue';
    import { IconCamera, IconChevronDown, IconEdit, IconList, IconSidebar, IconVigoLogo } from '@fibrous/semi-icons-vue';
    import {
        Avatar,
        Badge,
        Breadcrumb,
        Button,
        ButtonGroup,
        Cascader,
        Checkbox,
        Col,
        ConfigProvider,
        DatePicker,
        Input,
        Modal,
        Nav,
        Notification,
        Pagination,
        Popover,
        Radio,
        Rating,
        Row,
        Select,
        Spin,
        Steps,
        Switch,
        Tag,
        TextArea,
        TimePicker,
        Timeline,
        Toast,
        Tooltip,
        TypographyText,
        type NavItemConfig,
    } from '@fibrous/semi-ui-vue';

    const direction = ref<'ltr' | 'rtl'>();
    const flexStyle: CSSProperties = { display: 'flex', marginBottom: '32px', flexWrap: 'wrap' };
    const titleStyle = { margin: '50px 0 16px 0' };
    const rowStyle = { margin: '16px 10px' };
    const badgeStyle = {
        width: '42px',
        height: '42px',
        borderRadius: '4px',
        display: 'inline-block',
    };
    const tagStyle = { marginRight: '8px', marginBottom: '8px' };
    const buttonStyle = { ...tagStyle };
    const opts = () => ({
        title: 'Hi,Bytedance',
        content: 'ies dance dance dance',
        duration: 3,
        direction: direction.value,
    });
    const treeData = [
        {
            label: '浙江省',
            value: 'zhejiang',
            children: [
                {
                    label: '杭州市',
                    value: 'hangzhou',
                    children: [
                        { label: '西湖区', value: 'xihu' },
                        { label: '萧山区', value: 'xiaoshan' },
                        { label: '临安区', value: 'linan' },
                    ],
                },
                {
                    label: '宁波市',
                    value: 'ningbo',
                    children: [
                        { label: '海曙区', value: 'haishu' },
                        { label: '江北区', value: 'jiangbei' },
                    ],
                },
            ],
        },
    ];
    const navItems = [
        { itemKey: 'user', text: 'Option1' },
        { itemKey: 'union', text: 'Option2' },
        { itemKey: 'approve-management', text: 'Group3', items: ['3-1', '3-2'] },
    ];
    const navIcons = { user: IconEdit, union: IconCamera, 'approve-management': IconList };
    const navIconOf = (item: NavItemConfig) => navIcons[item.itemKey as keyof typeof navIcons];
    const vigoNotice = (color?: string) => Notification.info({ ...opts(), icon: h(IconVigoLogo, color ? { style: { color } } : null) });
</script>

<template>
    <div>
        <div :style="{ marginBottom: '20px' }">
            <ButtonGroup>
                <Button @click="direction = 'ltr'">LTR</Button>
                <Button @click="direction = 'rtl'">RTL</Button>
            </ButtonGroup>
        </div>
        <ConfigProvider :direction="direction">
            <Row>
                <h3 :style="titleStyle">Buttons</h3>
            </Row>
            <Row :style="rowStyle">
                <Button loading :style="{ marginRight: '8px' }" theme="solid">加载</Button>
                <Button :style="{ marginRight: '8px' }" theme="solid">
                    <template #icon>
                        <IconSidebar />
                    </template>
                    收起
                </Button>
                <Button iconPosition="right" :style="{ marginRight: '8px' }" theme="solid">
                    <template #icon>
                        <IconChevronDown />
                    </template>
                    展开选项
                </Button>
                <br />
                <br />
                <ButtonGroup>
                    <Button>拷贝</Button>
                    <Button>查询</Button>
                    <Button>剪切</Button>
                </ButtonGroup>
            </Row>
            <Row>
                <h3 :style="titleStyle">Input</h3>
            </Row>
            <Row :gutter="16" :style="rowStyle">
                <Col :span="12">
                    <Input aria-label="输入框" placeholder="输入框" />
                    <br />
                    <br />
                    <Input aria-label="禁用的输入框" disabled placeholder="输入框" />
                    <br />
                    <br />
                    <Input aria-label="带前缀的输入框" showClear>
                        <template #prefix>Prefix</template>
                    </Input>
                    <br />
                    <br />
                    <Input aria-label="带后缀的输入框" showClear>
                        <template #suffix>
                            <TypographyText strong :style="{ margin: '0 8px' }" type="secondary">Suffix</TypographyText>
                        </template>
                    </Input>
                    <br />
                    <br />
                    <TextArea aria-label="文本框" :maxCount="100" placeholder="文本框" />
                    <br />
                    <br />
                    <div :style="flexStyle">
                        <Switch aria-label="已开启的开关" defaultChecked :style="{ marginRight: '8px' }" />
                        <Switch aria-label="已关闭的开关" :style="{ marginRight: '8px' }" />
                        <Switch aria-label="禁用的开关" defaultChecked disabled :style="{ marginRight: '8px' }" />
                    </div>
                    <div :style="flexStyle">
                        <Checkbox defaultChecked :style="{ marginRight: '8px' }">多选框</Checkbox>
                        <Checkbox defaultChecked disabled :style="{ marginRight: '8px' }">禁用的多选框</Checkbox>
                        <Checkbox disabled :style="{ marginRight: '8px' }">禁用的多选框</Checkbox>
                    </div>
                    <div :style="{ ...flexStyle, marginBottom: 0 }">
                        <Radio defaultChecked :style="{ marginRight: '8px' }">单选框</Radio>
                        <Radio defaultChecked disabled :style="{ marginRight: '8px' }">禁用的单选框</Radio>
                        <Radio disabled :style="{ marginRight: '8px' }">禁用的单选框</Radio>
                    </div>
                </Col>
                <Col :span="12">
                    <DatePicker :style="{ width: '100%' }" @change="(_date, dateString) => console.log(dateString)" />
                    <br />
                    <br />
                    <TimePicker :style="{ width: '100%' }" />
                    <br />
                    <br />
                    <Select aria-label="选择器-单选" placeholder="选择器-单选" :style="{ width: '100%' }">
                        <Select.Option value="abc">抖音</Select.Option>
                        <Select.Option value="hotsoon">火山</Select.Option>
                        <Select.Option disabled value="pipixia">皮皮虾</Select.Option>
                        <Select.Option value="xigua">西瓜视频</Select.Option>
                    </Select>
                    <br />
                    <br />
                    <Select aria-label="选择器-禁用" disabled placeholder="选择器-禁用" :style="{ width: '100%' }">
                        <Select.Option value="abc">抖音</Select.Option>
                        <Select.Option value="hotsoon">火山</Select.Option>
                        <Select.Option disabled value="pipixia">皮皮虾</Select.Option>
                        <Select.Option value="xigua">西瓜视频</Select.Option>
                    </Select>
                    <br />
                    <br />
                    <Select aria-label="选择器-多选" multiple placeholder="选择器-多选" :style="{ width: '100%' }">
                        <Select.Option value="abc">抖音</Select.Option>
                        <Select.Option value="hotsoon">火山</Select.Option>
                        <Select.Option disabled value="pipixia">皮皮虾</Select.Option>
                        <Select.Option value="xigua">西瓜视频</Select.Option>
                    </Select>
                    <br />
                    <br />
                    <Cascader placeholder="级联选择器" :style="{ width: '100%' }" :treeData="treeData" />
                </Col>
            </Row>
            <Row>
                <h3 :style="titleStyle">Navigation</h3>
            </Row>
            <Row :style="rowStyle">
                <Breadcrumb>
                    <Breadcrumb.Item>Semi-ui</Breadcrumb.Item>
                    <Breadcrumb.Item>Breadcrumb</Breadcrumb.Item>
                    <Breadcrumb.Item>Default</Breadcrumb.Item>
                </Breadcrumb>
                <Nav :items="navItems" mode="horizontal">
                    <template #icon="{ item }">
                        <component :is="navIconOf(item)" />
                    </template>
                </Nav>
                <br />
                <br />
                <Pagination showSizeChanger :total="80" />
                <br />
                <Steps :current="1">
                    <Steps.Step>
                        <template #title>Finished</template>
                        <template #description>This is a description.</template>
                    </Steps.Step>
                    <Steps.Step>
                        <template #title>In Progress</template>
                        <template #description>This is a description.</template>
                    </Steps.Step>
                    <Steps.Step>
                        <template #title>Waiting</template>
                        <template #description>This is a description.</template>
                    </Steps.Step>
                </Steps>
                <br />
                <Steps :current="1" status="error">
                    <Steps.Step>
                        <template #title>Finished</template>
                        <template #description>This is a description</template>
                    </Steps.Step>
                    <Steps.Step>
                        <template #title>In Process</template>
                        <template #description>This is a description</template>
                    </Steps.Step>
                    <Steps.Step>
                        <template #title>Waiting</template>
                        <template #description>This is a description</template>
                    </Steps.Step>
                </Steps>
            </Row>
            <Row>
                <h3 :style="titleStyle">Display</h3>
            </Row>
            <Row :style="rowStyle">
                <div :style="{ display: 'flex' }">
                    <div :style="{ padding: '8px' }">
                        <Badge :count="5" theme="solid">
                            <Avatar color="blue" shape="square" :style="badgeStyle">XZ</Avatar>
                        </Badge>
                    </div>
                    <div :style="{ padding: '8px' }">
                        <Badge :count="5" theme="light">
                            <Avatar color="cyan" shape="square" :style="badgeStyle">YB</Avatar>
                        </Badge>
                    </div>
                    <div :style="{ padding: '8px' }">
                        <Badge :count="5" theme="inverted">
                            <Avatar color="indigo" shape="square" :style="badgeStyle">LX</Avatar>
                        </Badge>
                    </div>
                    <div :style="{ padding: '8px' }">
                        <Badge dot theme="solid">
                            <Avatar color="light-blue" shape="square" :style="badgeStyle">YZ</Avatar>
                        </Badge>
                    </div>
                    <div :style="{ padding: '8px' }">
                        <Badge dot theme="light">
                            <Avatar color="teal" shape="square" :style="badgeStyle">HW</Avatar>
                        </Badge>
                    </div>
                    <div :style="{ padding: '8px', borderRadius: '4px', backgroundColor: 'var(--semi-color-fill-0)' }">
                        <Badge dot theme="inverted">
                            <Avatar color="green" shape="square" :style="badgeStyle">XM</Avatar>
                        </Badge>
                    </div>
                </div>
                <br />
                <div>
                    <Tag color="grey" :style="tagStyle">grey tag</Tag>
                    <Tag color="blue" :style="tagStyle">blue tag</Tag>
                    <Tag color="blue" :style="tagStyle" type="ghost">ghost tag</Tag>
                    <Tag color="blue" :style="tagStyle" type="solid">solid tag</Tag>
                    <Tag color="red" :style="tagStyle">red tag</Tag>
                    <Tag color="green" :style="tagStyle">green tag</Tag>
                    <Tag color="orange" :style="tagStyle">orange tag</Tag>
                    <Tag color="teal" :style="tagStyle">teal tag</Tag>
                    <Tag color="violet" :style="tagStyle">violet tag</Tag>
                    <Tag color="white" :style="tagStyle">white tag</Tag>
                </div>
                <br />
                <div :style="{ display: 'flex', alignItems: 'center' }">
                    <Popover :style="{ padding: '8px' }">
                        <Tag :style="{ marginRight: '8px' }">I am Popover</Tag>
                        <template #content>hi semi-design</template>
                    </Popover>
                    <Tooltip>
                        <Tag :style="{ marginRight: '8px' }">I am Tooltip</Tag>
                        <template #content>hi semi-design</template>
                    </Tooltip>
                    <Rating :defaultValue="3" size="small" :style="{ marginRight: '8px' }" />
                </div>
                <br />
                <Timeline>
                    <Timeline.Item type="ongoing">
                        <template #time>2019-07-14 10:35</template>
                        审核中
                    </Timeline.Item>
                    <Timeline.Item type="success">
                        <template #time>2019-06-13 16:17</template>
                        发布成功
                    </Timeline.Item>
                    <Timeline.Item type="error">
                        <template #time>2019-05-14 18:34</template>
                        审核失败
                    </Timeline.Item>
                </Timeline>
            </Row>
            <Row>
                <h3 :style="titleStyle">Feedback</h3>
            </Row>
            <Row :style="rowStyle">
                <Button :style="buttonStyle" type="primary" @click="Notification.success(opts())"> 成功信息的通知 </Button>
                <Button :style="buttonStyle" @click="Notification.info(opts())">提示信息的通知</Button>
                <Button :style="buttonStyle" type="warning" @click="Notification.warning(opts())"> 警告信息的通知 </Button>
                <Button :style="buttonStyle" type="danger" @click="Notification.error(opts())">失败信息的通知</Button>
                <Button aria-label="Vigo 图标通知" :style="buttonStyle" @click="vigoNotice()">
                    <template #icon>
                        <IconVigoLogo />
                    </template>
                </Button>
                <Button aria-label="粉色 Vigo 图标通知" :style="buttonStyle" @click="vigoNotice('pink')">
                    <template #icon>
                        <IconVigoLogo />
                    </template>
                </Button>
                <br />
                <Button :style="buttonStyle" type="primary" @click="Modal.success(opts())">成功信息的弹窗</Button>
                <Button :style="buttonStyle" @click="Modal.info(opts())">提示信息的弹窗</Button>
                <Button :style="buttonStyle" type="warning" @click="Modal.warning(opts())">警告信息的弹窗</Button>
                <Button :style="buttonStyle" type="danger" @click="Modal.error(opts())">失败信息的弹窗</Button>
                <br />
                <Button :style="buttonStyle" type="primary" @click="Toast.success(opts())">成功信息的提示</Button>
                <Button :style="buttonStyle" @click="Toast.info(opts())">提示信息的提示</Button>
                <Button :style="buttonStyle" type="warning" @click="Toast.warning(opts())">警告信息的提示</Button>
                <Button :style="buttonStyle" type="danger" @click="Toast.error(opts())">失败信息的提示</Button>
                <br />
                <br />
                <Spin>
                    <template #tip>I am loading...</template>
                    <div
                        :style="{
                            backgroundColor: 'var(--semi-color-primary-light-default)',
                            border: '1px solid var(--semi-color-primary)',
                            borderRadius: '4px',
                            padding: '16px 10px',
                        }"
                    >
                        <p>Here are some texts.</p>
                        <p>And more texts on the way.</p>
                    </div>
                </Spin>
            </Row>
        </ConfigProvider>
    </div>
</template>

嵌套使用

ConfigProvider 可以嵌套。内层只覆盖显式传入的属性,没传的属性(direction、locale、timeZone、getPopupContainer、responsiveObserve、responsiveMap)继承外层。属性值为 undefined 视为没传;locale={null} 是显式传入,会清除外层的 locale,交给其内部的 LocaleProvider 或默认语言。

direction 为 rtl 的 ConfigProvider 内可以用 direction="ltr" 把子树切回从左到右,内层组件的逻辑和样式都按 ltr 处理。

外层:locale = en-US,timeZone = Asia/Tokyo,direction = ltr
内层只传 timeZone,其余继承外层:locale = en-US,timeZone = 8,direction = ltr
代码
<script setup lang="ts">
    import en_US from '@fibrous/semi-foundation/locale/source/en_US';
    import { ConfigConsumer, ConfigProvider } from '@fibrous/semi-ui-vue';
</script>

<template>
    <ConfigProvider direction="ltr" :locale="en_US" timeZone="Asia/Tokyo">
        <ConfigConsumer #default="{ locale, timeZone, direction }">
            <div :style="{ margin: '8px' }">
                外层:locale = {{ locale?.code ?? '未设置' }},timeZone = {{ String(timeZone) }},direction =
                {{ direction }}
            </div>
        </ConfigConsumer>
        <ConfigProvider :timeZone="8">
            <ConfigConsumer #default="{ locale, timeZone, direction }">
                <div :style="{ margin: '8px' }">内层只传 timeZone,其余继承外层:locale = {{ locale?.code ?? '未设置' }},timeZone = {{ String(timeZone) }},direction = {{ direction }}</div>
            </ConfigConsumer>
        </ConfigProvider>
    </ConfigProvider>
</template>

API 参考

ConfigProvider

Props

属性说明类型默认值
direction文本方向,可选 ltr 或 rtl。未传时继承外层 ConfigProvider,最外层默认为 ltr。"ltr" | "rtl"undefined
timeZone时间类组件使用的时区:数字(距 UTC 的小时偏移)、GMT±HH:MM 字符串或 IANA 标识。数字和 GMT 写法是全年固定的偏移。未传时继承外层。string | numberundefined
locale多语言配置,优先级高于 LocaleProvider。未传时继承外层 ConfigProvider;没有 ConfigProvider 设置时由 LocaleProvider 决定,两者都没有时使用 zh_CN。传 null 清除外层的 locale。Locale | nullundefined
getPopupContainer返回弹层容器的函数,只影响仍通过 Portal 渲染的 Modal、SideSheet、ImagePreview,容器需要设置 position: relative。未传时继承外层,最外层为 document.body。Type(() => HTMLElement)undefined
responsiveObserve是否开启响应式断点监听。关闭时不注册任何 matchMedia 监听;开启后在首次订阅时注册,无订阅时注销。未传时继承外层,最外层为 false。booleanundefined
responsiveMap自定义响应式断点,key 为 xs、sm、md、lg、xl、xxl,value 为 media query 字符串。按内容比较,内联写对象不会重新注册监听;未传时继承外层,最外层使用 defaultResponsiveMap。ResponsiveMapundefined

Events

事件说明回调参数
无

Slots

插槽说明作用域参数
default受该配置影响的内容。显式传入的 direction 与外层不同时(含最外层),内容外包一层带 dir 属性的 div。any

Exposes

名称说明类型
无

ConfigProvider.defaultResponsiveMap 与具名导出 defaultResponsiveMap 是默认断点配置。locale 的用法同 LocaleProvider 中 locale 参数的用法。

ConfigConsumer

Props

属性说明类型默认值
无

Events

事件说明回调参数
无

Slots

插槽说明作用域参数
default作用域插槽,参数为当前生效的配置(ContextValue);在 ConfigProvider 内还包含 screens 与 onBreakpoint,没有 ConfigProvider 时为空对象。ContextValue

Exposes

名称说明类型
无

useConfig

useConfig(): ComputedRef<ContextValue> 返回当前生效的配置,没有 ConfigProvider 时为空对象。ContextValue 包含上表的 direction、timeZone、locale、getPopupContainer、responsiveObserve、responsiveMap,以及只读的 screens(各断点的命中情况)和 onBreakpoint(订阅函数,见上文「订阅 API」)。

时区标识

  • 数字,例如 1、-9.5,代表距离 UTC 的时间偏移,单位为小时,可以为负数或小数;
  • 字符串,例如GMT-09:30、GMT+08:00这样的以 "GMT" 开头的表征偏移字符串,也可以为 IANA 标识,如Asia/Shanghai、America/Los_Angeles等。

数字和 GMT-09:30 这类写法表示全年固定的偏移,不随夏令时变化。例如 -3.5 和 GMT-03:30 全年都是 UTC-03:30,时间格式中的时区名(z)显示为 GMT-03:30。

需要跟随某个地区的夏令时,请使用 IANA 标识。这里可以查看 IANA 标识列表,以及时区是否有夏令时。

FAQ

  • ConfigProvider中没有提供全局自定义prefix classname的功能,有类似需求如何实现(例如SDK中使用了Semi,期望打包的dom样式不带.semi-xx前缀,以免被宿主的全局 CSS 影响)?
    • 由于 prefixCls 需要同时被组件层的 js/css 消费,Semi 将此开关放在了webpack plugin的配置项中,而不是作为ConfigProvider的配置项。
    • 如果你使用webpack,请在SemiWebpackPlugin的参数中进行配置
# webpack配置示例
const SemiWebpackPlugin = require('@fibrous/semi-webpack-plugin').default;
module.exports = {
+    plugins: [new SemiWebpackPlugin({ prefixCls: 'imes' })],
}

semiGlobal

除了 ConfigProvider外,你还可以通过 semiGlobal 配置覆盖全局组件的默认 Props。

在 semiGlobal.config.overrideDefaultProps 可配置组件默认 Props。非函数类型的默认值在实例首次缺省该属性时读取并缓存;函数类型的默认值(如 getPopupContainer)由各组件在需要时读取,时机因组件而异。全局配置不是响应式的,修改它不会让已创建的实例更新。因此建议在创建应用之前设置,放在站点入口处。需要为单个 app 使用独立的配置时,用 app.provide(semiGlobalKey, { config: { overrideDefaultProps } }),semiGlobalKey 同样从 @fibrous/semi-ui-vue 导入。

id、insetLabelId、wrapperId、addonId、extraId 这类每个实例唯一的属性不能经全局默认值设置:类型里没有这些键,运行时也忽略。

比如下方配置就是将所有的 Button 默认设置为 warning,Select 默认开启 filter 等

import { semiGlobal } from '@fibrous/semi-ui-vue';

semiGlobal.config.overrideDefaultProps = {
    Button: {
        type: 'warning',
    },
    Select: {
        filter: true,
    },
    Tooltip: {
        trigger: 'click',
    },
};