English | 简体中文
Omi - Web Components 框架
- 📶 信号 Signal 驱动的响应式编程,reactive-signal强力驱动
- 🧱 TDesign Web 组件 & OMI 游乐场
- ⚡ 微小的尺寸,极速的性能
- 💗 目标 100+ 模板 & OMI 模板源码
- 🐲 OMI Form & OMI Form 游乐场 & Lucide Omi 图标
- 🌐 你要的一切都有: Web Components, JSX, Function Components, Router, Suspense, Directive, Tailwindcss…
- 💒 使用 Constructable Stylesheets 轻松管理和共享样式
1234567891011121314151617181920212223242526 import { render, signal, tag, Component, h } from 'omi' const count = signal(0) function add() { count.value++} function sub() { count.value--} @tag('counter-demo')export class CounterDemo extends Component { static css = 'span { color: red; }' render() { return ( <> <button onClick={sub}>-button> <span>{count.value}span> <button onClick={add}>+button> </> ) }}
使用该组件:
123456789101112 import { h } from 'omi'import './counter-demo' render(<counter-demo />, document.body) // 或者import { CounterDemo, Other } from './counter-demo'// 当需要导入其他东西的时候,防止被 tree shakingrender(<CounterDemo />, document.body) // 或者document.body.appendChild(document.createElement('counter-demo'))
安装
1 npm i omi
快速创建 Omi + Vite + TS/JS 项目:
1234 $ npx omi-cli init my-app # 或者创建js项目: npx omi-cli init-js my-app$ cd my-app $ npm start # develop$ npm run build # release
快速创建 Omi + Router + Signal + Suspense + Tailwindcss + Vite + TS 项目:
1234 $ npx omi-cli init-spa my-app $ cd my-app $ npm start # develop$ npm run build # release
包
- 核心包
omi- Omi 框架的实现代码。omi-form- 强大易用且跨框架的表单解决方案。lucide-omi- Lucide 的 Omi 图标**。omiu- 希望打造最好的 web 组件。omi-router- 创建单页应用。omi-cli- 快速创建 Omi + Vite + TS/JS 项目。
- 入门套件 (未发布到 npm)
omi-elements- 官方推出 Tailwind Omi 套件。omi-starter-spa- 快速创建单页应用(SPA),内置了 Omi + OmiRouter + Tailwindcss + TypeScript + Vite + Prettier。omi-starter-ts- 基于 Vite + Omi + TypeScript 的模板。omi-starter-tailwind- 基于 Vite + Omi + TypeScript + Tailwindcss 的模板。omi-starter-js- 基于 Vite + Omi + JavaScript 的模板。omi-vue- Vue SFC + Vite + OMI + OMI-WeUI.
- 组件
omi-weui- Omi 版本的 WeUI。omi-auto-animate- Omi 版本的 @formkit/auto-animate。omi-suspense- 处理异步依赖。
- 指令
omi-transition- 提供进入和离开动画。omi-ripple- 用于为用户界面元素添加涟漪(ripple)效果。当用户与元素交互(例如点击按钮)时,涟漪效果会从交互点开始扩散开来。
- 综合性例子 (未发布到 npm)
snake-game-2tier- 基于 OmiSignalclass 两层架构的贪吃蛇游戏。snake-game-3tier- 基于 Omi 响应是函数三层架构的贪吃蛇游戏。omi-tutorial- Omi 官方教程源代码。
如果你想帮助项目发展,可以先简单地与同行分享!
- [Share via Dev.to](<https://dev.to/new?prefill=---
title: Omi - Web Components Framework
---- Home: omijs.org Github:https://github.com/Tencent/omi - 📶 Signal-driven reactive programming
- 🎉 Tailwind Element Omi UI KIT
- ⚡ Tiny size, Fast performance
- 🌐 Everything you need: Web Components, JSX, Router, Suspense, Directive, Tailwindcss…
- 💯 Both object oriented programming(OOP) and data oriented programming(DOP) are supported
- 💒 Harness Constructable Stylesheets to easily manage and share styles>)
- [Share via Twitter](https://twitter.com/intent/tweet?text=Web Components Framework 🎉http://omijs.org/
Everything you need: Web Components, JSX, Router, Suspense, Directive, Tailwindcss…
Tailwind Element Omi UI KIT> 💯https://omi.cdn-go.cn/elements/latest/)
- Share via Facebook
- Share via LinkedIn
- [Share via Pinterest](https://www.pinterest.com/pin/create/button?url=http://omijs.org/&media=https://repository-images.githubusercontent.com/36606437/66abfcfb-096b-4c9d-a290-77165213e605&description=Omi-Web Componnets Framework)
- [Share via Reddit](https://reddit.com/submit?url=http://omijs.org/&title=web components framework)
- [Share via StumbleUpon](https://www.stumbleupon.com/submit?url=http://omijs.org/&title=web components framework)
- Share via Vkontakte
- [Share via Weibo](https://service.weibo.com/share/share.php?url=https://omijs.org/&title=web components framework)
- [Share via Hackernews](https://news.ycombinator.com/submitlink?u=http://omijs.org/&t=web components framework)
多谢!
使用
TodoApp 使用响应式函数
数据驱动编程
在数据驱动编程中,我们将重点放在数据本身和对数据的操作上,而不是数据所在的对象或数据结构。这种编程范式强调的是数据的变化和流动,以及如何响应这些变化。基于响应式函数的 TodoApp 就是一个很好的例子,它使用了响应式编程的概念,当数据(即待办事项列表)发生变化时,UI 会自动更新以反映这些变化。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 import { render, signal, computed, tag, Component, h } from 'omi' const todos = signal([ { text: 'Learn OMI', completed: true }, { text: 'Learn Web Components', completed: false }, { text: 'Learn JSX', completed: false }, { text: 'Learn Signal', completed: false }]) const completedCount = computed(() => { return todos.value.filter(todo => todo.completed).length}) const newItem = signal('') function addTodo() { // api a,不会重新创建数组 todos.value.push({ text: newItem.value, completed: false }) todos.update() // 非值类型的数据更新需要手动调用 update 方法 // api b, 和上面的 api a 效果一样,但是会创建新的数组 // todos.value = [...todos.value, { text: newItem.value, completed: false }] newItem.value = '' // 值类型的数据更新需会自动 update} function removeTodo(index: number) { todos.value.splice(index, 1) todos.update() // 非值类型的数据更新需要手动调用 update 方法} @tag('todo-list')class TodoList extends Component { onInput = (event: Event) => { const target = event.target as HTMLInputElement newItem.value = target.value } render() { return ( <> <input type="text" /> <button onClick={addTodo}>Addbutton> <ul> {todos.value.map((todo, index) => { return ( <li> <label> <input type="checkbox" checked="{todo.completed}"> { todo.completed = !todo.completed todos.update() }} /> {todo.completed ? <s>{todo.text}s> : todo.text} label> {' '} <button onClick={() => removeTodo(index)}>❌button> li> ) })} ul> <p>Completed count: {completedCount.value}p> </> ) }} render(<todo-list />, document.body)
自动导入 h
vite.config.js:
123456789 import { defineConfig } from 'vite' export default defineConfig({ esbuild: { jsxInject: "import { h } from 'omi'", jsxFactory: "h", jsxFragment: "h.f" }})
你可以在构建时候注入代码,这样就不用手动导出 h。
定义跨框架组件
在 Vue 中使用 Omi component 例子如下:

my-counter.tsx:
12345678910111213141516171819202122232425262728293031323334353637383940 import { tag, Component, h, bind } from 'omi' @tag('my-counter')class MyCounter extends Component<{ count: number }> { static props = { count: { type: Number, default: 0, changed(newValue, oldValue) { this.setState({ count: newValue }) } } } state = { count: 1 } @bind sub() { this.setState({ count: this.state.count - 1 }) this.fire('change', this.state.count) } @bind add() { this.setState({ count: this.state.count + 1 }) this.fire('change', this.state.count) } render() { return ( <> <button onClick={this.sub}>-button> <span>{this.state.count}span> <button onClick={this.add}>+button> </> ) }}
在 Vue3 中使用
12345678910111213 {{ msg }} 【Omi】 count is {{ count }} 【Vue】
如果在 omi 组件中使用:
1 this.fire('count-change', this.state.count)
在 vue 中使用组件监听事件如下:
1 <my-counter @count-change="change" :count="count" />
在 React 中使用
1234567891011121314151617181920212223242526272829303132333435 import { useState, useRef, useEffect } from 'react'import useEventListener from '@use-it/event-listener'import './my-counter' function App() { const [count, setCount] = useState(100) const myCounterRef = useRef(null) useEffect(() => { const counter = myCounterRef.current if (counter) { const handleChange = (evt) => { setCount(evt.detail) } counter.addEventListener('change', handleChange) return () => { counter.removeEventListener('change', handleChange) } } }, []) return ( <> <h1>Omi + Reacth1> <my-counter count={count} ref={myCounterRef}>my-counter> <div> <button onClick={() => setCount((count) => count + 1)}> count is {count} button> div> </> )} export default App
贡献者
License
MIT © Tencent
免责声明 © 2025 - 虚宝阁
本站部分源码来源于网络,版权归属原开发者,用户仅获得使用权。依据《计算机软件保护条例》第十六条,禁止:
- 逆向工程破解技术保护措施
- 未经许可的分发行为
- 去除源码中的原始版权标识
※ 本站源码仅用于学习和研究,禁止用于商业用途。如有侵权, 请及时联系我们进行处理。