Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
forked fromTencent/omi

Web Components Framework - Web组件框架

License

NotificationsYou must be signed in to change notification settings

XiaoLinZzz/omi

 
 

Repository files navigation

English |简体中文

omi

Omi - Web Components Framework

import{render,signal,tag,Component,h}from'omi'constcount=signal(0)functionadd(){count.value++}functionsub(){count.value--}@tag('counter-demo')exportclassCounterDemoextendsComponent{staticcss='span { color: red; }'render(){return(<><buttononClick={sub}>-</button><span>{count.value}</span><buttononClick={add}>+</button></>)}}

Use this component:

import{h}from'omi'import'./counter-demo'render(<counter-demo/>,document.body)// orimport{CounterDemo,Other}from'./counter-demo'// Prevent tree Shaking when importing other thingsrender(<CounterDemo/>,document.body)// ordocument.body.appendChild(document.createElement('counter-demo'))

Install

npm i omi

To quickly create an Omi + Vite + TS/JS project:

$ npx omi-cli init my-app# or create js project by: npx omi-cli init-js my-app$cd my-app           $ npm start# develop$ npm run build# release

To quickly create an Omi +Router +Signal +Suspense +Tailwindcss + Vite + TS project:

$ npx omi-cli init-spa my-app  $cd my-app           $ npm start# develop$ npm run build# release

Packages

  • Core packages
    • omi - Implementation of omi framework.
    • omi-form - Powerful, simple and cross frameworks form solution.
    • lucide-omi - Lucide icon collection for omi.
    • omiu - Hope to create the best web components. For example, the powerfulvchart andvtable
    • omi-router - Create SPA of omi framework.
    • omi-cli - To quickly create an Omi + Vite + TS/JS project.
  • Starter kits (not published to npm)
    • omi-elements - Tailwind Element Omi UI KIT.
    • omi-starter-spa - A starter repo for building single page app using Omi + OmiRouter + Tailwindcss + TypeScript + Vite + Prettier.
    • omi-starter-ts - A starter repo for building web app or reusable components using Omi in TypeScript base on Vite.
    • omi-starter-tailwind - A starter repo for building web app or reusable components using Omi + Tailwindcss + TypeScript + Vite.
    • omi-starter-js - A starter repo for building web app or reusable components using Omi in JavaScript base on Vite.
    • omi-vue - Vue SFC + Vite + OMI + OMI-WeUI.
  • Components
  • Directives
    • omi-transition - Applying animations when an component is entering and leaving the DOM.
    • omi-ripple - A lightweight component for adding ripple effects to user interface elements.
  • Examples (not published to npm)

If you want to help the project grow, start by simply sharing it with your peers!

Thank you!

Usage

TodoApp with reactivity functions

Data oriented programming

In data-oriented programming, the focus is on the data itself and the operations on the data, rather than the objects or data structures that hold the data. This programming paradigm emphasizes the change and flow of data, and how to respond to these changes. The TodoApp with reactivity functions is a good example of this, using the concepts of reactive programming, where the UI automatically updates to reflect changes in the data (i.e., the to-do list).

import{render,signal,computed,tag,Component,h}from'omi'consttodos=signal([{text:'Learn OMI',completed:true},{text:'Learn Web Components',completed:false},{text:'Learn JSX',completed:false},{text:'Learn Signal',completed:false}])constcompletedCount=computed(()=>{returntodos.value.filter(todo=>todo.completed).length})constnewItem=signal('')functionaddTodo(){// api atodos.value.push({text:newItem.value,completed:false})todos.update()// Trigger UI auto update// api b, same as api a// todos.value = [...todos.value, { text: newItem.value, completed: false }]newItem.value=''// Changing the value type can automatically update the UI}functionremoveTodo(index:number){todos.value.splice(index,1)todos.update()// Trigger UI auto update}@tag('todo-list')classTodoListextendsComponent{onInput=(event:Event)=>{consttarget=event.targetasHTMLInputElementnewItem.value=target.value}render(){return(<><inputtype="text"value={newItem.value}onInput={this.onInput}/><buttononClick={addTodo}>Add</button><ul>{todos.value.map((todo,index)=>{return(<li><label><inputtype="checkbox"checked={todo.completed}onInput={()=>{todo.completed=!todo.completedtodos.update()// Trigger UI auto update}}/>{todo.completed ?<s>{todo.text}</s> :todo.text}</label>{' '}<buttononClick={()=>removeTodo(index)}></button></li>)})}</ul><p>Completed count:{completedCount.value}</p></>)}}render(<todo-list/>,document.body)

TodoApp with Signal Class

Object oriented programming

In object-oriented programming, the focus is on the objects, which contain both data and methods to operate on the data. This programming paradigm emphasizes the interaction and cooperation between objects, and how to organize and manage code through object encapsulation, inheritance, and polymorphism. The TodoApp with reactivity functions can also be implemented in an object-oriented way, for example, by creating a TodoList class that contains the data of the to-do list and methods to operate on this data, as well as aupdate method to update the UI.

import{render,Signal,tag,Component,h,computed}from'omi'typeTodo={text:string,completed:boolean}classTodoAppextendsSignal<{todos:Todo[],filter:string,newItem:string}>{completedCount:ReturnType<typeofcomputed>constructor(todos:Todo[]=[]){super({ todos,filter:'all',newItem:''})this.completedCount=computed(()=>this.value.todos.filter(todo=>todo.completed).length)}addTodo=()=>{// api athis.value.todos.push({text:this.value.newItem,completed:false})this.value.newItem=''this.update()// api b, same as api a// this.update((value) => {//   value.todos.push({ text: value.newItem, completed: false })//   value.newItem = ''// })}toggleTodo=(index:number)=>{consttodo=this.value.todos[index]todo.completed=!todo.completedthis.update()}removeTodo=(index:number)=>{this.value.todos.splice(index,1)this.update()}}consttodoApp=newTodoApp([{text:'Learn OMI',completed:true},{text:'Learn Web Components',completed:false},{text:'Learn JSX',completed:false},{text:'Learn Signal',completed:false}])@tag('todo-list')classTodoListextendsComponent{onInput=(event:Event)=>{consttarget=event.targetasHTMLInputElementtodoApp.value.newItem=target.value}render(){const{ todos}=todoApp.valueconst{ completedCount, toggleTodo, addTodo, removeTodo}=todoAppreturn(<><inputtype="text"value={todoApp.value.newItem}onInput={this.onInput}/><buttononClick={addTodo}>Add</button><ul>{todos.map((todo,index)=>{return(<li><label><inputtype="checkbox"checked={todo.completed}onInput={()=>toggleTodo(index)}/>{todo.completed ?<s>{todo.text}</s> :todo.text}</label>{' '}<buttononClick={()=>removeTodo(index)}></button></li>)})}</ul><p>Completed count:{completedCount.value}</p></>)}}render(<todo-list/>,document.body)

We won't discuss which method is good or bad here. You can choose either method using omi.

Auto Import h

vite.config.js:

import{defineConfig}from'vite'exportdefaultdefineConfig({esbuild:{jsxInject:"import { h } from 'omi'",jsxFactory:"h",jsxFragment:"h.f"}})

You can inject code during construction, so you don't have to manually exporth.

Define Cross Framework Component

The case of using Omi component in Vue is as follows:

my-counter.tsx:

import{tag,Component,h,bind}from'omi'@tag('my-counter')classMyCounterextendsComponent{staticprops={count:{type:Number,default:0,changed(newValue,oldValue){this.state.count=newValuethis.update()}}}state={count:null}install(){this.state.count=this.props.count}  @bindsub(){this.state.count--this.update()this.fire('change',this.state.count)}  @bindadd(){this.state.count++this.update()this.fire('change',this.state.count)}render(){return(<><buttononClick={this.sub}>-</button><span>{this.state.count}</span><buttononClick={this.add}>+</button></>)}}

Using in Vue3

<script setup>import {ref }from'vue'// import omi componentimport'./my-counter'defineProps({  msg:String,})constcount=ref(0)constchange= (e)=> {count.value=e.detail}</script><template>  <h1>{{ msg }}</h1>  <my-counter@change="change":count="count" />  <p>    【Omi】   </p>  <divclass="card">    <buttontype="button"@click="count++">count is {{ count }}</button>    <p>     【Vue】     </p>  </div></template>

If youfire thecount-change in an Omi component:

this.fire('count-change',this.state.count)

To use the component and listen for events in Vue:

<my-counter@count-change="change":count="count"/>

Using in React

import{useState,useRef,useEffect}from'react'importuseEventListenerfrom'@use-it/event-listener'import'./my-counter'functionApp(){const[count,setCount]=useState(100)constmyCounterRef=useRef(null)useEffect(()=>{constcounter=myCounterRef.currentif(counter){consthandleChange=(evt)=>{setCount(evt.detail)}counter.addEventListener('change',handleChange)return()=>{counter.removeEventListener('change',handleChange)}}},[])return(<><h1>Omi + React</h1><my-countercount={count}ref={myCounterRef}></my-counter><divclassName="card"><buttononClick={()=>setCount((count)=>count+1)}>          count is{count}</button></div></>)}exportdefaultApp

Contributors

License

MIT © Tencent

About

Web Components Framework - Web组件框架

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript81.2%
  • CSS14.0%
  • JavaScript4.0%
  • Other0.8%

[8]ページ先頭

©2009-2025 Movatter.jp