优化实战 第 59 期 - 高效利器之跨技术栈组件库

2,646 阅读3分钟

在实际的开发中,经常需要基于不同的技术栈去写重复的功能,不仅影响开发效率还增加后期的维护成本

理想方案:只需编写且维护一套代码,就可以同时运行在各类前端技术栈中

原生组件的组成

  • Custom elements(自定义元素)

    class UserCard extends HTMLElement {
      constructor() {
        super()  // 必须首先调用 super 方法
      }
      // 编写元素的功能代码
    }
    customElements.define('user-card', UserCard)  // 注册自定义元素
    

    自定义元素的名称必须包含连词线(不能是单个单词),用来区别原生的 HTML 元素

    life-cycle.png

  • Shadow DOM(影子DOM)

    shadow-dom.png

    对自定义元素进行组件化,将结构、样式、行为隐藏起来,并与页面上的其他代码相隔离

  • HTML templates(HTML模板)

    <template id="tpl">
      <p slot="content">灵活的模板内容</p>
    </template>
    

    解析器在加载页面时为了确保模板内容的有效性,会对模板内容进行解析,但不进行渲染

    class UserCard extends HTMLElement {
      constructor() {
        super()
        const template = document.getElementById('tpl')
        const templateContent = template.content
        const shadowRoot = this.attachShadow({ mode: 'opem' }).appendChild(templateContent.cloneNode(true))
      }
    }
    

    需要手动添加模板的内容到 shadow DOM

原生组件的缺点

  • 大量 DOM 操作

    DOM 操作,回到了 jQuery 的开发时代,不符合现代开发方式

  • 可维护性差

    缺乏类型约束,代码质量无法保证,容易出错

  • 兼容代码多

    兼容性代码分散在各个组件内部,没办法统一收敛

  • 缺乏 CSS 提示

    style 通过字符串的方式拼接在代码内部,无法提示

基于原生组件的 StencilJS

  • 官方介绍

    Stencil 是一个生成 Web Component 的编译器。它将最流行框架的最佳概念,结合到了一个简单的构建工具中

  • 集成特性

    Virtual DOM - 虚拟DOM

    Async rendering - 异步渲染

    Reactive data-binding - 响应式数据绑定

    JSX语法支持

    TypeScript

  • 创建新项目

    npm init stencil
    

    根据 CLI 选项进行选择创建组件 component后,并输入项目名称

  • 动态创建组件

    npm run generate
    

    根据提示输入组件名称,会自动在 components 目录下生成相关初始化文件

  • 构建发布内容

    npm run build
    

    发布组件库到官方仓库可参阅 第 30 期 - 高效利器之跨技术栈工具库 一文

跨技术栈使用组件库

  • 安装组件库

    npm install gis-ui
    
  • 引入组件库

    import { defineCustomElements } from 'gis-ui/loader'
    defineCustomElements()
    

    说明:在项目的入口文件中进行自定义组件的初始化

  • 在 Vue 项目中使用

    组件的 参数以及事件的配置 均遵循项目基础库中 API 的定义方式进行使用

  • 在 React 项目中使用

    组件的 参数配置 遵循项目基础库中 API 的定义方式进行使用

    组件的 事件配置 通过 addEventListener 监听 事件名称 的方式进行使用

  • 注意事项

    通过组件的 事件配置 获取组件内部的回调数据,均需从事件对象 event 中获取 detail 属性

    一起学习,加群交流看 沸点