Skip to content

Repository files navigation

uni-component npmbuild statuscoverage

中文

Unified Component: Write once component, Run in multiple lib/platform.

Depend on @uni-store.

Unified Component core parts:

  • setup, like vue setup, just define the component state. The state can be used to any platforms. This should be contained pure component state logic.
  • render, optional. This should be used when platform support render function, like : web platform or miniapp which supported runtime render.

Usage cases:

Installation

pnpm add @uni-component/core
# or with yarn
yarn add @uni-component/core
# or with npm
npm install @uni-component/core

Usage

More cases, see @uni-component/components.

Define a component

import{h,PropType,uniComponent}from'@uni-component/core'import{computed,ref}from'@uni-store/core'// pure setup stateexportconstUniButton=uniComponent('uni-button',{type: {type: StringasPropType<'button'|'submit'|'reset'>,default: 'button'},text: String,icon: String,primary: Boolean,onClick: FunctionasPropType<(e?: MouseEvent)=>any>},(name,props)=>{constn=ref(0)constrootClass=computed(()=>{return{[`${name}-primary`]: props.primary}})constclickAction=(e?: MouseEvent)=>{n.value+=1// do othersprops.onClick&&props.onClick(e)}return{
n,
rootClass,
clickAction
}})// platform component with pure render functionexportconstCubeButtonxx=uni2Platform(UniButton,(props,state,{ renders })=>{const{ type, text }=props// rootClass always contain Component name, like 'cube-button'const{ rootClass, n, clickAction }=stateconstt=text ? text : (renders.defaultRender&&renders.defaultRender())return(<buttonclass={rootClass}type={type}onClick={clickAction}><span>{ t }{ n }</span></button>)})

With Vue 3

Install:

pnpm add @uni-component/vue
# or with yarn
yarn add @uni-component/vue
# or with npm
npm install @uni-component/vue

Use:

/// <reference types="@uni-component/vue/platform" />import{h,Fragment}from'@uni-component/core'import'@uni-component/vue'import{createApp}from'vue'constApp=()=>{return(<><CubeButton>child</CubeButton><CubeButtonprimary={true}text='text'></CubeButton></>)}createApp(App).mount('#root')

JSX with tsconfig: { "jsxFactory": "h", "jsxFragmentFactory": "Fragment" }

With React

Install:

pnpm add @uni-component/react
# or with yarn
yarn add @uni-component/react
# or with npm
npm install @uni-component/react

Use:

/// <reference types="@uni-component/react/platform" />import{h,Fragment}from'@uni-component/core'import'@uni-component/react'importReactDOMfrom'react-dom'constApp=()=>{return(<><CubeButton>child</CubeButton><CubeButtonprimary={true}text='text'></CubeButton></>)}ReactDOM.render(<App/>,document.getElementById('root'))

JSX with tsconfig: { "jsxFactory": "h", "jsxFragmentFactory": "Fragment" }

Documentation

Define pure state - Headless Component

In my opinion, the pure state is a headless component.

Use uniComponent API.

Object props:

import{uniComponent,classNames,UniNode,PropType}from'@uni-component/core'constUniXxYy=uniComponent('uni-xx-yy',{type: {type: StringasPropType<'button'|'submit'|'reset'>,default: 'button'},text: String,icon: String,primary: Boolean,onClick: FunctionasPropType<(e?: MouseEvent)=>any>,xxRender: FunctionasPropType<(param: {})=>UniNode|undefined>,},(name,props,context)=>{// name is 'UniXxYy'constn=ref(0)constrootClass=computed(()=>{return{[`${name}-primary`]: props.primary}})// other class you should always use classNamesconstotherClass=computed(()=>{returnclassNames({[`${name}-child-xx`]: props.type==='reset'})})constclickAction=(e?: MouseEvent)=>{n.value+=1// do othersprops.onClick&&props.onClick(e)}return{
n,
rootClass,
clickAction
}})

Notice: xxRender prop will be treated as render function(React - render function, vue - scope slot)

Array props:

constUniXxYy=uniComponent('uni-xx-yy',['a','b'],(name,props,context)=>{// name is 'UniXxYy'// props.a and props.b can be any value// ...return{// ...}})

No props:

constUniXxYy=uniComponent('uni-xx-yy',(name,props,context)=>{// name is 'UniXxYy'// ...return{// ...}})

About context param

{// renders contained all `xxRender` in props// renders.defaultRender() is used to replace `props.children` in react and `slots.default` in vue
renders: Record<string,(...args: any[])=>any>// all element attrs, no ref and key
attrs: Record<string,any>// element attrs without `class, style, id`
$attrs: Record<string,any>// original props setted by usage case// without default propsnodeProps?: Record<string,any>|null}

Define platform component

This is optional.

Use uni2Platform(UniComponent, render: (props, state, context) => UniNode | undefined) API.

  • UniComponent headless component, the uniComponent() result
  • render() pure render function.
    • About state param
      {rootClass: string,rootStyle: {[key: string]: 'string value'},rootId: string|undefined// other state with your custom state// n,// xxAction,//...}

Demo:

// platform component with pure render functionconstXxYy=uni2Platform(UniXxYy,(props,state,{ renders })=>{const{ type, text }=props// rootClass always contain Component name, like 'uni-xx-yy'const{ rootClass, rootStyle, rootId, n, clickAction }=stateconstt=text ? text : (renders.defaultRender&&renders.defaultRender())return(<buttonid={rootId}class={rootClass}style={rootStyle}type={type}onClick={clickAction}><span>{t}{n}</span></button>)})

Reference a DOM element or Component

Use useRef API and ref attribute.

import{useRef}from'@uni-component/core'constUniXxYy=uniComponent('uni-xx-yy',(name)=>{// name is 'UniXxYy'constele=ref<HTMLElement>()constsetEleRef=useRef(ele)// buttonComponent will be the state of CubeButton// defined in UniButtonconstbuttonComponent=ref<{n: number,clickAction: (e?: MouseEvent)=>void}>()constsetButtonComponentRef=useRef(buttonComponent)return{
setEleRef,
setButtonComponentRef,}})

render:

constXxYy=uni2Platform(UniXxYy,(props,state)=>{const{ setEleRef, setButtonComponentRef }=statereturn(<divref={setEleRef}><CubeButtonref={setButtonComponentRef}>xx</CubeButton></div>)})

Notice: The ref value will be this component's state result when referenced a component

Lifecycles

Only 3 lifecycles: mounted, updated and unmounted.

import{onMounted,onUpdated,onUnmounted}from'@uni-component/core'constUniXxYy=uniComponent('uni-xx-yy',(name)=>{onMounted(()=>{console.log('mounted')})onUpdated(()=>{console.log('updated')})onUnmounted(()=>{console.log('unmounted')})return{// ...}})

Provide and Inject

Like vue 3 Provide / Inject.

Provide:

// parent componentimport{provide}from'@uni-component/core'constUniXxYy=uniComponent('uni-xx-yy',(name)=>{provide('xx-key',{// xx: xxValue// ...})return{// ...}})

Inject:

// child componentimport{inject}from'@uni-component/core'constUniXxYyChild=uniComponent('uni-xx-yy-child',(name)=>{// const xxProvide = inject('xx-key')// with default valueconstxxYyProvideValue=inject('xx-key',{// xx: defaultValue// ...})return{// ...}})

Other API

  • classNames(), process element class names. Same as classnames.
  • const mergedStyle = mergeStyle(stringStyle, objectStyle, ...(string or object styles)), merge styles. mergedStyle is an object.

License

MIT

About

Unified Component

Resources

Stars

9 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages