UI组件化

333 阅读1分钟

组件强解藕

  • UI组件

    • 脱离业务和计算逻辑
    • 只针对具体UI样式和操作进行封装
    • 个体独立性
  • 功能组件

    • 具体运用时所需要的逻辑和计算
    • 组合拼接
    • 群体综合性
  • UI组件.png

  • 如图,单个的页签可以作为一个UI组件,将UI组件和逻辑操作与计算结合封装成了一个功能组件

方案落地

技术选型

  • Web Component —— 浏览器原生支持(不依赖于框架,前端工程中可无破坏注入)

应用

  • 先贴实例:用来放置label和input的布局组件

item.png

  • UI组件代码

    // html
    <div class="cpt-item">
        <div class="label">
            <slot name="label"></slot>
        </div>
        <div class="operate-area">
            <slot></slot>
        </div>
    </div>
    <style>
        .cpt-item {
            display: grid;
            grid-template-columns: var(--label-width, 200px) auto;
            grid-column-gap: 1em;
        }
    ​
        .label{
            display: flex;
            flex-direction: row-reverse;
        }
    </style>// js
    import html from './item.tmpl.html';
    ​
    export default function InjectItem() {
        customElements.define('cpt-item', class extends HTMLElement {
            connectedCallback() {
                this.shadow = this.attachShadow({ mode: 'closed' });
                this.shadow.innerHTML = html;
            }
        })
    }
    

html.png

  • 组件运用

    <div className="contain-unit">
      <cpt-item class="unit">
        <label slot="label" >用户名:</label>
        <input type="text" name="user" value={name} onChange={e => setName(e.target.value)} />
      </cpt-item>
    </div>
    <div className="contain-unit">
      <cpt-item class="unit">
        <label slot="label">密码:</label>
        <input type="password" name='psd' value={psd} onChange={e => setPsd(e.target.value)} />
      </cpt-item>
    </div>
    

工程化

  • webpack5项目

  • 编写cpt.html文件的loader

    module.exports = function loader(source) {
        return `export default ${JSON.stringify(source)}`
    }
    
  • 配置

    {
      "test": /.tmpl.html$/,
      "loader": path.resolve('./config/tmpl.loader.js')
    }
    

file.png

待解决

  • 如何更好的让css脱离
  • 如何更优雅的进行属性初始化
  • 是【生成组件代码】还是【引入组件】方案辩证