-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(TextHighlight): 新增 TextHighlight 文本高亮组件 (#740)
* feat: 优化mark样式 * feat: 优化mark样式,解决本地冲突 --------- Co-authored-by: blankzhang <blankzhang@blankzhangdeMac-mini.local>
- Loading branch information
1 parent
2642e2d
commit f3634c5
Showing
13 changed files
with
287 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { withInstall } from '../_util/withInstall'; | ||
import type { SFCWithInstall } from '../_util/interface'; | ||
import TextHighlight from './text-highlight'; | ||
|
||
export { textHighlightProps } from './props'; | ||
export type { TextHighlightProps } from './props'; | ||
|
||
type TextHighlightType = SFCWithInstall<typeof TextHighlight>; | ||
export const FTextHighlight = withInstall<TextHighlightType>( | ||
TextHighlight as TextHighlightType, | ||
); | ||
|
||
export default FTextHighlight; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import type { ComponentObjectPropsOptions, PropType } from 'vue'; | ||
import type { ExtractPublicPropTypes } from '../_util/interface'; | ||
|
||
export const textHighlightProps = { | ||
// 高亮内容,数组 | ||
searchValues: { | ||
type: Array as PropType<string[]>, | ||
default: (): string[] => [], | ||
}, | ||
// 严格模式,是否严格大小写 | ||
strict: { | ||
type: Boolean, | ||
default: false, | ||
}, | ||
} as const satisfies ComponentObjectPropsOptions; | ||
|
||
// 组件暴露给外部的 props 类型 | ||
export type TextHighlightProps = ExtractPublicPropTypes< | ||
typeof textHighlightProps | ||
>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
@import '../../style/themes/index'; | ||
@import '../../style/mixins/index'; | ||
|
||
@text-highlight: ~'@{cls-prefix}-text-highlight'; | ||
|
||
.@{text-highlight} { | ||
.highlight { | ||
font-size: inherit; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import '../../style'; | ||
import './index.less'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import { | ||
Text, | ||
type VNode, | ||
type VNodeTypes, | ||
defineComponent, | ||
isVNode, | ||
} from 'vue'; | ||
import { isArray, isObject, isString } from 'lodash-es'; | ||
import getPrefixCls from '../_util/getPrefixCls'; | ||
import { useTheme } from '../_theme/useTheme'; | ||
import FText from '../text'; | ||
import { textHighlightProps } from './props'; | ||
|
||
const prefixCls = getPrefixCls('text-highlight'); | ||
|
||
export default defineComponent({ | ||
name: 'FTextHighlight', | ||
props: textHighlightProps, | ||
setup(props, { slots }) { | ||
useTheme(); | ||
|
||
const createRegExp = (value: string): RegExp => { | ||
const flags = props.strict ? 'g' : 'gi'; | ||
return new RegExp(`(${value})`, flags); | ||
}; | ||
|
||
// 判断是否相等 | ||
const judgeEqual = (word: string, text: string): boolean => { | ||
return ( | ||
(props.strict && text === word) | ||
|| (!props.strict && text.toLowerCase() === word.toLowerCase()) | ||
); | ||
}; | ||
|
||
// 渲染高亮的部分 | ||
const renderHighLight = (part: string): VNode => { | ||
return ( | ||
<FText tag="mark" class="highlight"> | ||
{part} | ||
</FText> | ||
); | ||
}; | ||
|
||
// 渲染文本 | ||
const renderText = (text: string): (string | VNode)[] => { | ||
let parts: (string | VNode)[] = [text]; | ||
props.searchValues.forEach((value) => { | ||
const regExp = createRegExp(value); | ||
parts = parts.reduce((result: (string | VNode)[], part) => { | ||
if (isString(part)) { | ||
const split = part.split(regExp); | ||
return result.concat( | ||
split.map((txt: string) => { | ||
return judgeEqual(value, txt) | ||
? renderHighLight(txt) | ||
: txt; | ||
}), | ||
); | ||
} else { | ||
return [...result, part]; | ||
} | ||
}, [] as (string | VNode)[]); | ||
}); | ||
return parts; | ||
}; | ||
|
||
// 渲染节点 | ||
const renderNode = (node: VNode): VNode => { | ||
// 节点的标签 | ||
const NodeType = node.type as VNodeTypes; | ||
let children; | ||
|
||
// 处理children | ||
if (isArray(node.children)) { | ||
// 如果是数组,对每个子节点进行处理 | ||
children = node.children.map((child) => { | ||
// 如果子节点是字符串,使用 renderText 函数处理 | ||
if (isString(child)) { | ||
return renderText(child); | ||
} else if (isVNode(child)) { | ||
// 如果子节点是 VNode,递归使用 renderNode 函数处理 | ||
return renderNode(child); | ||
} else { // 如果子节点既不是字符串也不是 VNode,直接返回它 | ||
return child; | ||
} | ||
}); | ||
} else if (isString(node.children)) { | ||
// node.children 是字符串,使用 renderText 函数处理 | ||
children = renderText(node.children); | ||
} else { | ||
// 如果 node.children 既不是数组也不是字符串,直接返回它 | ||
children = node.children; | ||
} | ||
|
||
if (NodeType === Text) { | ||
// 如果是纯文本,渲染一个空标签 | ||
return <span {...node.props}>{children}</span>; | ||
} else if (isString(NodeType)) { | ||
// 字符串(对应 HTML 标签名) | ||
return <NodeType {...node.props}>{children}</NodeType>; | ||
} else if (isObject(NodeType)) { | ||
// 用户自定义的组件对象 | ||
const ChildComponent = NodeType as any; | ||
const child = node.children as any; | ||
const childSlots | ||
= child && child.default ? child.default() : []; | ||
return ( | ||
<ChildComponent {...node.props}> | ||
{childSlots.map(renderNode)} | ||
</ChildComponent> | ||
); | ||
} | ||
}; | ||
|
||
// 渲染内容 | ||
const renderContent = () => { | ||
if (!slots.default) { | ||
return ''; | ||
} | ||
// 遍历内容的所有节点 | ||
return slots.default().map(renderNode); | ||
}; | ||
|
||
return () => <div class={prefixCls}>{renderContent()}</div>; | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<template> | ||
<FSpace> | ||
<FForm :labelWidth="80"> | ||
<FFormItem label="严格模式:"> | ||
<FSwitch v-model="strict"> | ||
<template #active> 开 </template> | ||
<template #inactive> 关 </template> | ||
</FSwitch> | ||
</FFormItem> | ||
<FFormItem label="高亮词:"> | ||
<FInput | ||
v-model="str" | ||
placeholder="空格分隔" | ||
@change="strChange" | ||
></FInput> | ||
</FFormItem> | ||
</FForm> | ||
</FSpace> | ||
<FSpace> | ||
<FTextHighlight :searchValues="searchValues" :strict="strict"> | ||
<FText> | ||
This is text mixed icon | ||
<BellOutlined /> | ||
and component | ||
<FButton>Button</FButton> | ||
and | ||
<FText>a subtext</FText> | ||
. | ||
</FText> | ||
<div class="text">This is the string for the div wrap.</div> | ||
This is a plain text string. | ||
</FTextHighlight> | ||
</FSpace> | ||
</template> | ||
|
||
<script setup> | ||
import { ref } from 'vue'; | ||
import { BellOutlined } from '@fesjs/fes-design/icon'; | ||
const searchValues = ref([]); | ||
const str = ref(''); | ||
const strChange = () => { | ||
searchValues.value = str.value.split(' '); | ||
}; | ||
const strict = ref(false); | ||
</script> | ||
|
||
<style> | ||
.text { | ||
font-size: 30px; | ||
margin: 10px 0px; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# TextHighlight 文本高亮 | ||
|
||
用于高亮文本中的指定文字 | ||
|
||
## 组件注册 | ||
|
||
```js | ||
import { FTextHighlight } from '@fesjs/fes-design'; | ||
|
||
app.use(FTextHighlight); | ||
``` | ||
|
||
## 代码演示 | ||
|
||
### 基础用法 | ||
|
||
:::demo | ||
base.vue | ||
::: | ||
|
||
## TextHighlight Props | ||
|
||
| 属性 | 说明 | 类型 | 默认值 | | ||
| ------------ | ---------------------------- | --------------- | ------- | | ||
| searchValues | 搜索内容 | `Array<string>` | `[]` | | ||
| strict | 严格模式,是否区分大小写匹配 | `boolean` | `false` | | ||
|
||
## TextHighlight slots | ||
|
||
| slot 名称 | 说明 | | ||
| --------- | -------------- | | ||
| default | 用户的文本内容 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters