Skip to content

Commit 72cd980

Browse files
authored
Merge pull request #981 from ac666666666/issue-956
docs: 解决Issue #956 (增加 exportparts 的例子,且补充到文档里)
2 parents e70ed66 + 0f29e41 commit 72cd980

File tree

5 files changed

+442
-11
lines changed

5 files changed

+442
-11
lines changed

package-lock.json

Lines changed: 10 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"dependencies": {
3-
"omi": "^7.6.17"
3+
"omi": "^7.7.13"
44
}
55
}

packages/omi/README.CN.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<p align="center"><img src="https://omijs.github.io/home/assets/logo.svg" alt="omi" width="100"/></p>
2+
<h2 align="center">Omi - Web Components 框架</h2>
3+
4+
- 📶 基于 [reactive-signal](https://github.com/Tencent/omi/tree/master/packages/reactive-signal)**Signal** 驱动响应式编程
5+
- 🧱 [TDesign Web Components](https://github.com/TDesignOteam/tdesign-web-components)
6+
- 💗 [100+ OMI 模板](https://omi.cdn-go.cn/templates/latest/) & [OMI 模板源码](https://github.com/Tencent/omi/tree/master/packages/omi-templates)
7+
- 🐲 [OMI 表单](https://omi.cdn-go.cn/form/latest/docs/) & [OMI 表单演练场](https://omi.cdn-go.cn/form/latest/play/) & [Lucide Omi 图标](https://github.com/omijs/lucide-omi)
8+
-**小巧**体积,**快速**性能
9+
- 🌐 你需要的一切:**Web Components****JSX**、函数组件、路由、Suspense、指令、Tailwindcss...
10+
- 💒 利用 **Constructable Stylesheets** 轻松管理和共享样式
11+
12+
## ExportParts - 样式化嵌套组件
13+
14+
Omi 支持 Web Components 的 `exportparts` 属性,允许将嵌套组件的 CSS parts 暴露给外部进行样式化。这使得在保持样式封装的同时,实现强大的组件组合。
15+
16+
### 基本用法
17+
18+
```tsx
19+
import { render, tag, Component, h } from 'omi'
20+
21+
// 内部组件定义 CSS parts
22+
@tag('inner-button')
23+
class InnerButton extends Component {
24+
static css = `
25+
.btn {
26+
padding: 10px 20px;
27+
border: 2px solid #007bff;
28+
background: #007bff;
29+
color: white;
30+
border-radius: 4px;
31+
cursor: pointer;
32+
}
33+
`
34+
35+
render() {
36+
return (
37+
<button class="btn" part="button">
38+
<span part="icon">🚀</span>
39+
<span part="text">{this.props.children}</span>
40+
</button>
41+
)
42+
}
43+
}
44+
45+
// 容器组件使用 exportparts
46+
@tag('card-component')
47+
class CardComponent extends Component {
48+
static css = `
49+
.card {
50+
border: 1px solid #ddd;
51+
padding: 20px;
52+
border-radius: 8px;
53+
}
54+
55+
/* 通过 ::part() 样式化嵌套组件 */
56+
inner-button::part(button) {
57+
background: #28a745;
58+
border-color: #28a745;
59+
}
60+
`
61+
62+
render() {
63+
return (
64+
<div class="card" part="card">
65+
{/* 导出嵌套组件的 parts */}
66+
<inner-button exportparts="button, icon, text">
67+
Click me
68+
</inner-button>
69+
</div>
70+
)
71+
}
72+
}
73+
74+
// 父组件可以样式化导出的 parts
75+
@tag('app-container')
76+
class AppContainer extends Component {
77+
static css = `
78+
/* 样式化从嵌套组件导出的 parts */
79+
card-component::part(button) {
80+
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
81+
border: none;
82+
border-radius: 25px;
83+
}
84+
85+
card-component::part(icon) {
86+
animation: spin 2s linear infinite;
87+
}
88+
89+
@keyframes spin {
90+
from { transform: rotate(0deg); }
91+
to { transform: rotate(360deg); }
92+
}
93+
`
94+
95+
render() {
96+
return <card-component />
97+
}
98+
}
99+
```
100+
101+
### 核心特性
102+
103+
- **Part 定义**: 使用 `part="part-name"` 属性定义组件中可样式化的部分
104+
- **Part 导出**: 使用 `exportparts="part1, part2"` 暴露嵌套组件的 parts
105+
- **外部样式化**: 使用 `component::part(part-name)` 选择器从外部样式化 parts
106+
- **Part 重命名**: 使用 `exportparts="internal-name:external-name"` 重命名导出的 parts
107+
108+
### 高级示例
109+
110+
完整的工作示例请参考 [`exportparts-example.tsx`](./examples/exportparts-example.tsx),演示了:
111+
- 多层组件嵌套
112+
- Part 重命名和别名
113+
- 复杂样式化场景
114+
- 动画和悬停效果
115+
116+
## 在 Vue 中使用 Omi 组件
117+
118+
```vue
119+
<template>
120+
<h1>{{ msg }}</h1>
121+
122+
<my-counter @change="change" :count="count" />
123+
<p>
124+
【Omi 组件】
125+
</p>
126+
127+
<div class="card">
128+
<button type="button" @click="count++">count is {{ count }}</button>
129+
<p>
130+
【Vue 组件】
131+
</p>
132+
</div>
133+
134+
</template>
135+
```
136+
137+
## 许可证
138+
139+
MIT © Tencent

packages/omi/README.md

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,110 @@ define('my-app', class extends withTwind(Component) {
245245
})
246246
``` -->
247247

248+
## ExportParts - Styling Nested Components
249+
250+
Omi supports the Web Components `exportparts` attribute, allowing nested component CSS parts to be exposed for external styling. This enables powerful component composition while maintaining style encapsulation.
251+
252+
### Basic Usage
253+
254+
```tsx
255+
import { render, tag, Component, h } from 'omi'
256+
257+
// Inner component defines CSS parts
258+
@tag('inner-button')
259+
class InnerButton extends Component {
260+
static css = `
261+
.btn {
262+
padding: 10px 20px;
263+
border: 2px solid #007bff;
264+
background: #007bff;
265+
color: white;
266+
border-radius: 4px;
267+
cursor: pointer;
268+
}
269+
`
270+
271+
render() {
272+
return (
273+
<button class="btn" part="button">
274+
<span part="icon">🚀</span>
275+
<span part="text">{this.props.children}</span>
276+
</button>
277+
)
278+
}
279+
}
280+
281+
// Container component uses exportparts
282+
@tag('card-component')
283+
class CardComponent extends Component {
284+
static css = `
285+
.card {
286+
border: 1px solid #ddd;
287+
padding: 20px;
288+
border-radius: 8px;
289+
}
290+
291+
/* Style nested components via ::part() */
292+
inner-button::part(button) {
293+
background: #28a745;
294+
border-color: #28a745;
295+
}
296+
`
297+
298+
render() {
299+
return (
300+
<div class="card" part="card">
301+
{/* Export nested component parts */}
302+
<inner-button exportparts="button, icon, text">
303+
Click me
304+
</inner-button>
305+
</div>
306+
)
307+
}
308+
}
309+
310+
// Parent component can style exported parts
311+
@tag('app-container')
312+
class AppContainer extends Component {
313+
static css = `
314+
/* Style parts exported from nested components */
315+
card-component::part(button) {
316+
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
317+
border: none;
318+
border-radius: 25px;
319+
}
320+
321+
card-component::part(icon) {
322+
animation: spin 2s linear infinite;
323+
}
324+
325+
@keyframes spin {
326+
from { transform: rotate(0deg); }
327+
to { transform: rotate(360deg); }
328+
}
329+
`
330+
331+
render() {
332+
return <card-component />
333+
}
334+
}
335+
```
336+
337+
### Core Features
338+
339+
- **Part Definition**: Use `part="part-name"` attribute to define styleable parts within components
340+
- **Part Export**: Use `exportparts="part1, part2"` to expose nested component parts
341+
- **External Styling**: Use `component::part(part-name)` selector to style parts from outside
342+
- **Part Renaming**: Use `exportparts="internal-name:external-name"` to rename exported parts
343+
344+
### Advanced Example
345+
346+
For a complete working example, see [`exportparts-example.tsx`](./examples/exportparts-example.tsx), which demonstrates:
347+
- Multi-level component nesting
348+
- Part renaming and aliasing
349+
- Complex styling scenarios
350+
- Animations and hover effects
351+
248352
## Define Cross Framework Component
249353

250354
The case of using Omi component in Vue is as follows:
@@ -328,13 +432,13 @@ const change = (e) => {
328432
329433
<my-counter @change="change" :count="count" />
330434
<p>
331-
【Omi】
435+
【Omi Component
332436
</p>
333437
334438
<div class="card">
335439
<button type="button" @click="count++">count is {{ count }}</button>
336440
<p>
337-
【Vue】
441+
【Vue Component
338442
</p>
339443
</div>
340444

0 commit comments

Comments
 (0)