69行代码 实现一个vue、react、san 超好用通用table组件

基于 Web Components 封装一个通用组件库! 打破框架的隔阂

是否需要这么做

  1. 如 antd 有一个很好用的组件。但是无vue、san框架适配版本,那这两个框架就无法使用;当发现 ElementUI 有好用的组件,react 也无法使用。
  2. 当你在接手一个老的不能再老的项目的时候,发现这个项目依赖的的底层框架生态很弱,最可怕的就是没有功能强大组件库。当有新需求进来的时候,就需要手撸一个适配的组件。
  3. 熟悉react或者vue、angular,期望使用我熟悉的框架开发前端;而无需考虑历史兼容问题。

如果当前开发中,你确实有以上的问题,或者需求,这个思路或许可以帮到你。

万变不离之中

作为前端同学,无论你使用任何框架、或者再牛逼的技术。想要让浏览器能够展示你的编码的效果,最终你都需要将相应的资源打包成html、js、css。

那思路就很明确了;当我发现antd有好用的组件时;是否可以将 react + antd 打包成为一个js包,但是对外暴露的是一个自定义标签。也就是利用 Web Components 中的自定义标签相关的技术做个嫁接

大致流程如下:

对 Web Components 不太熟悉可以看下这个专栏;juejin.cn/column/7299...

这里就对基础技术不做过多介绍了。

核心 69 行代码

ts 复制代码
import React from 'react'
import ReactDOM from 'react-dom/client'
import * as antdComponent from 'antd'
import * as styleContent from './table.scss'
const template = document.createElement('template')
const prefix = 'wheat-table'
const styles = `<style> ${styleContent}</style>`
template.innerHTML = `
  ${styles}
  <div class="wheat-table"></div>
`
class WheatTable extends HTMLElement {
  constructor() {
    super()
    this.tableData = [];
    this.columns = [];
    this.tableProps = {};
    this.render()
  }
  setTableProps(props) {
    this.tableProps = props;
    this.renderReactElement();
  }
  setDataSource(data){
    this['table-data'] = data;
    this.renderReactElement();
  }
  setColumns(columns) {
    console.log('columns', columns)
    const columnsData = [];
    columns.forEach(item => {
      const _item = {}
      Object.keys(item).forEach(key => {
        if(key === 'render'){
          _item.render = (text, row) => {
            const {componentName, ...other} = item.render(text, row)
            if(antdComponent && antdComponent[componentName]){
              const Component = antdComponent[componentName]
              return <Component {...other}/>
            }
            return React.createElement(type, {...other}, text)
          };
        } else {
          _item[key] = item[key]
        }
      })
      columnsData.push(_item)
    })
    this.columns = columnsData
    this.renderReactElement()
  }
  renderReactElement() {
    const data = this['table-data'];
    const Table = antdComponent['Table']
    this.root.render(<Table columns={this.columns} dataSource={data} {...this.tableProps} />);
  }
  connectedCallback() {
    this.renderReactElement()
  }
  render() {
    this._shadowRoot = this.attachShadow({ mode: 'open' })
    const mountPoint = template.content.cloneNode(true);
    this._shadowRoot.appendChild(mountPoint);
    this.$table = this._shadowRoot.querySelector('.wheat-table')
    this.root = ReactDOM.createRoot(this.$table);
  }
}
// 判定是否已经被注册
!window.customElements.get(prefix) && window.customElements.define(prefix, WheatTable)

核心代码

其实核心实现大代码在 52~56行。关键的四行代码。调用 render 方法,传入 table 组件。就结束。

ts 复制代码
renderReactElement() { 
    const data = this['table-data']; const Table = antdComponent['Table'] 
    this.root.render(
       <Table 
           columns={this.columns} 
           dataSource={data} 
           {...this.tableProps} 
         />
       ); 
    }

相关文档

我已经将相关的代码都提交至github,并且编写了相关的使用文档: 组件文档:文档地址

github: github.com/glean-wheat...

这是一个思路,后期会继续优化

相关推荐
惜.己15 分钟前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5
什么鬼昵称38 分钟前
Pikachu-csrf-CSRF(get)
前端·csrf
长天一色1 小时前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
feng_xiaoshi1 小时前
【云原生】云原生架构的反模式
云原生·架构
刷帅耍帅1 小时前
设计模式-桥接模式
设计模式·桥接模式
NiNg_1_2341 小时前
npm、yarn、pnpm之间的区别
前端·npm·node.js
秋殇与星河1 小时前
CSS总结
前端·css
BigYe程普2 小时前
我开发了一个出海全栈SaaS工具,还写了一套全栈开发教程
开发语言·前端·chrome·chatgpt·reactjs·个人开发
余生H2 小时前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
程序员-珍2 小时前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发