0.2.0 • Published 21 days ago

transform-component v0.2.0

Weekly downloads
-
License
MIT
Repository
-
Last release
21 days ago

transform-component - 转换不同类型的渲染组件

前言

背景

在一些时候,当前项目技术栈可能是React,但是要引入一个vue3的组件,或者不同运行时的react组件

所以,一个跨技术栈、跨运行时,且支持插槽的组件转换器就来了

说明

支持转换的组件类型: vue@2, vue@3, react, none(无框架,类微前端) 支持在支持类型间任意转换

  • shimer - 组件垫片方法;用于创建一个宿主组件来接收节点、参数
  • renderer - 组件渲染方法;用于通过接收的参数在指定节点下渲染组件
  • transformer - 组件转换方法; 类似 shimer(wrapEl => renderer(Component, wrapEl))

用法

import transformComponent from 'transform-component'

/**
 * @desc 转换渲染组件
 * @param {string} sourceType - 来源组件类型 - ['vue2', 'vue3', 'react', 'none']
 * @param {string} targetType - 目标组件类型 - ['vue2', 'vue3', 'react', 'none']
 * @param {object|function} Component - 要转换的组件
 * @param {object} sourceOptions - 来源组件的渲染参数
 * @param {object} targetOptions - 目标组件渲染参数
 * @return {object|function}
 */
const TargetCOmponent = transformComponent(sourceType, targetType, SourceComponent, sourceOptions, targetOptions)
console.log(TargetCOmponent)

查看所有的支持类型

import { transformers, shimers, renderers } from 'transform-component'

// 默认支持的组件类型转换器对象 - transformComponent的快捷形式
console.log(transformers)
// [
//   "react2react",
//   "react2vue3",
//   "react2vue2",
//   "react2none",
//   "vue32react",
//   "vue32vue3",
//   "vue32vue2",
//   "vue32none",
//   "vue22react",
//   "vue22vue3",
//   "vue22vue2",
//   "vue22none",
//   "none2react",
//   "none2vue3",
//   "none2vue2",
//   "none2none"
// ]

// 默认支持的垫片组件类型对象
console.log(shimers)
// [
//   "react",
//   "vue@3",
//   "vue@2",
//   "none"
// ]

// 默认支持的渲染组件类型对象
console.log(renderers)
// [
//   "react",
//   "vue@3",
//   "vue@2",
//   "none"
// ]

示例

react -> vue3

import React from 'react'
import ReactDOM from 'react-dom'
import Vue from 'vue'
import ReactComponent from 'some-react-component'

// 方案一
import transformComponent from 'transform-component'
const Vue3Component = transformComponent('react', 'vue@3', ReactComponent, { React, ReactDOM }, { Vue })

// 方案二
import { transformers } from 'transform-component'
const Vue3Component = transformers.react2vue3(ReactComponent, { React, ReactDOM }, { Vue })

transformers.react2vue3 是 transformComponent.bind(null, 'react', 'vue@3') 的快捷形式

react -> none - 直接渲染组件到dom

import React from 'react'
import ReactDOM from 'react-dom'
import ReactComponent from 'some-react-component'

// 方案一 import transformComponent from 'transform-component' const renderTo = transformComponent('react', 'none', ReactComponent, { React, ReactDOM })

// 方案二 import { transformers } from 'transform-component' const renderTo = transformers.react2none(ReactComponent, { React, ReactDOM })

// 渲染方法 const { dispose, setProps} = renderTo(document.querySelector('#app'))

> transformers.react2none 约等于 renderer.react
> 即直接渲染该组件

### vue3 -> react
```js
import React from 'react'
import ReactDOM from 'react-dom'
import Vue from 'vue'
import Vue3Component from 'some-vue3-component'

// 方案一
import transformComponent from 'transform-component'
const ReactComponent = transformComponent('vue@3', 'react', Vue3Component, { Vue }, { React, ReactDOM })

// 方案二
import { transformers } from 'transform-component'
const ReactComponent = transformers.vue32react(Vue3Component, { Vue }, { React, ReactDOM })

vue3 -> vue2

import Vue2 from 'vue@2'
import Vue3 from 'vue@3'
import Vue3Component from 'some-vue3-component'

// 方案一
import transformComponent from 'transform-component'
const Vue2Component = transformComponent('vue@3', 'vue@2', Vue3Component, { Vue: Vue3 }, { Vue: Vue2 })

// 方案二
import { transformers } from 'transform-component'
const Vue2Component = transformers.vue32vue2(Vue3Component, { Vue: Vue3 }, { Vue: Vue2 })

其余未列出的类型转换,与上面示例同理

扩展

扩展渲染方法 - renderer

import { renderers } from 'transform-component'

// 声明渲染器
const renderSomeTypeComponent = (SomeTypeComponent: Function | Object, wrapEl: HTMLElement, rendererOptions: Object) => {
  const {
    // 组件依赖包
    SomeTypeRender,
    // 默认的props; 变更时通过 setProps 接收
    props,
    // 默认的插槽; 变更时通过 setSlots 接收
    slots,
  } = rendererOptions

  // 在指定节点下渲染该组件 - 伪代码
  SomeTypeRender.renderComponent(SomeTypeComponent, wrapEl)

  // 实现下列方法
  // 释放组件时调用方法
  const dispose = () => void
  // 组件props变更时调用方法
  const setProps = (newProps: Object) => void
  // 抽象的插槽变更时调用方法
  const setSlots = (newSlots: SlotsObject) => void

  interface SlotsObject {
    [slotKey: string]: (slotArgs: Array<any>, slotWrapEl: HTMLElement) => void;
  }

  // 返回渲染控制方法
  return {
    dispose,
    setProps,
    setSlots,
  }
}

// 声明渲染器的依赖
renderSomeTypeComponent.deps = {
  // 默认的变量名: 默认的包名
  SomeTypeRender: 'some-type-render',
}

// 接入渲染器
renderers.someType = renderSomeTypeComponent

扩展垫片方法 - shimer

import { shimers } from 'transform-component'

// 声明渲染器
const createSomeTypeComponent = (renderToElement: Function, shimerOptions: Object) => {
  const {
    // 组件依赖包
    SomeTypeRender,
  } = shimerOptions

  // 声明一个新组件 - 伪代码
  const SomeTypeComponent = (props) => {

    // 组件挂载时触发 dispose
    let rendererHandle
    onMount(() => {
      const shimEl = shimRef.current
      rendererHandle = renderToElement(shimEl, {
        props,
      })
    })

    // 组件卸载时触发 dispose
    onUnMount(() => {
      rendererHandle.dispose()
    })

    // 组件props变更时触发 setProps
    onPropsChange(() => {
      rendererHandle.setProps(props)
    })

    // 组件slots变更时触发 setSlots
    const slotsParams = {}
    onSlotsChange(() => {
      const slots = {}
      someTypeSlotKeys.forEach(key => {
        slots[key] = (slotArgs, slotWrapEl) => {
          slotsParams[key] = [slotArgs, slotWrapEl]
        }
      })
      rendererHandle.setSlots(slots)
    })

    // 接收到slots参数回调时 生成构造插槽节点
    const fakeSlotsNodes = {}
    someTypeSlotKeys.forEach((key, i) => {
      const slotParams = slotsParams[key]
      if (slotParams && slotParams[1]) {
        const [slotArgs, slotWrapEl] = slotParams
        // const vnodes = someTypeSlotValues[i](...slotArgs)
        fakeSlotsNodes[key] = <Teleport to={slotWrapEl}>{vnodes}</Teleport>
      }
    })

    // 创建shim节点及构造的插槽节点
    return <div component-shim ref={shimRef}>{fakeSlotsNodes}</div>
  }

  // 返回生成的组件
  return SomeTypeComponent
}

// 声明渲染器的依赖
createSomeTypeComponent.deps = {
  // 默认的变量名: 默认的包名
  SomeTypeRender: 'some-type-render',
}

// 接入渲染器
shimers.someType = createSomeTypeComponent
0.2.0

21 days ago

0.1.9

3 months ago

0.1.8

8 months ago

0.1.7

8 months ago

0.1.6

8 months ago

0.1.5

9 months ago

0.1.4

11 months ago

0.1.3

11 months ago

0.1.2

11 months ago

0.1.1

11 months ago

0.1.0

11 months ago