整体来看,Edge 主题在 React 的支持情况要比 Vue 逊色一些,主要原因在于 React 自己构造一整套的事件处理机制,导致 LuLu UI 中部分 UI 组件的自定义事情没法直接套用 React 语法,需要借助 ref 手动添加事件,还有部分原因在于 React 有不少自己定义的规则。
- 非 Web Components 元素使用
className
而不是class
; - 部分表单元素
value
不能直接赋值,需要使用defaultValue
属性; - 布尔属性一定要加 true,类似下面的代码就没有效果:
<i is-tips title="内容">提示</i>
必须明确指定
is-tips
属性值为true
:<i is-tips="true" title="内容">提示</i>
我实在是不清楚为何 React 不按照 DOM 标准来设计,可能是跨端的野心,也可能是面向的开发群体是偏后,相比之下 Preact 则友好很多,同时采用原生的 DOM 事件系统,和 LuLu UI 完全一致,HTML 属性也是浏览器原生会泽,同时使用标签模板字面量开发了 htm,可以取代 JSX 的能力,可以在浏览器中直接使用。
所以,这里先示意如何在 Preact Web 免安装环境中使用 LuLu UI。
Preact与LuLu UI
先示意比较简单的日期范围选择组件,相关代码如下:
<div id="dateApp"></div>
<script type="module"> import { html, render } from 'https://unpkg.com/htm/preact/index.mjs?module' function App (props) { return html`<input type="date" value="${props.value}" is="ui-datetime"/>` } render(html`<i is-tips title="支持标准HTML">日期:</i> <${App} value="2021-08-17" />`, dateApp) </script>
实时效果如下所示,可以看到日期可以正常选择:
事件
由于 Preact 是基于原生的 DOM 事件体系构建的,因此可以和 LuLu UI 无缝对接使用。
<div id="dateApp2"></div>
function OnChange (event) { dateApp2.querySelector('p').innerHTML = `选择的日期是:${event.target.value}` } function OnConnected (event) { event.target.after(` 今天是:${event.target.value}`) } render(html`<input onchange="${OnChange}" onconnected="${OnConnected}" is="ui-datetime" /><p></p>`, dateApp2)
实时效果如下所示,可以看到 LuLu UI 组件中自定义的 connected 事件触发了,当我们改变日期,原生的 change 事件也触发了。
传参
既然 Preact 和 LuLu UI 的事件体系完全一致,参数的传递处理就变得异常简单,和 Vue 中使用 LuLu UI 类似。
还是举数据列表的例子,代码如下所示。
<div id="listApp"></div>
// 传参设置
function setListData (event) {
event.target.params.data = [{
value: '蔡伦',
userid: 1
}, ... , {
value: '彭玉乐',
userid: 7
}]
};
render(html`<input class="ui-input" is="ui-datalist" onconnected="${setListData}"/>`, listApp);
实时效果如下所示,点击输入框,可以看到选择列表出现了,功能都是正常的。
React与LuLu UI
虽然 LuLu UI 的气质和 React 不太相符,但是,绝大多数组件依然是可以无障碍使用的,并且相比 Vue 还有优势,那就是自定义元素组件天然支持。例如下面的 <ui-drop>
自定义元素组件在 React 中可以正常渲染,但是在 Vue 中会被警告处理:
<ui-drop target="t2" eventtype="hover">hover我</ui-drop>
下面通过几个典型例子,展示下如何在 React 框架开发环境中使用 LuLu UI,大家可以重点关注下自定义事件的处理。
假设你已经安装了 LuLu UI。
npm install lu2
表单控件
以最为基础的 <select>
控件举例。
相关代码如下所示:
<div id="root"></div>
import React from 'react'; import ReactDOM from 'react-dom'; import "lu2/theme/edge/css/common/ui/Select.css"; import "lu2/theme/edge/js/common/ui/Select.js"; function showValue (e) { console.log(`选中的值是:${e.target.value}`); } const select = (<select is="ui-select" defaultValue={3} onChange={showValue}> <option value="1" disabled>选项1</option> <option value="2">选项2</option> <option value="3">选项3</option> </select>) ReactDOM.render(select, document.getElementById('root'));
效果截图示意:
由于 LuLu UI 中的 Select 组件基于原生 <select>
元素实现,全部都是 HTML 属性传参,事件也是浏览器原生的 change 事件,因此可以和 React 无障碍混合使用。
弹框
由于弹框大部分的使用场景都是使用 new 语法构造,因此,也是可以在 React 中无障碍使用的,类似组件还有 LightTip 轻提示。
使用示意,点击一个按钮出现 alert 提示框:
<div id="root"></div>
import "lu2/theme/edge/css/common/ui/Button.css"; import "lu2/theme/edge/css/common/ui/Dialog.css"; import Dialog from "lu2/theme/edge/js/common/ui/Dialog.js"; function showDialog () { new Dialog().alert('提示信息'); } const button = <button type="primary" is="ui-button" onClick={showDialog}>弹框</button> ReactDOM.render(button, document.getElementById('root'));
效果截图示意:
数据列表
在 Vue 以及 Preact 中,数据列表的参数可以通过 connected 事件进行设置,但是,React 由于自建事件机制,因此,无法触发 LuLu UI 内置的自定义事件,想要设置参数,就需要使用其他方法,例如 ref,使用示意:
<div id="root"></div>
import "lu2/theme/edge/css/common/ui/Input.css"; import "lu2/theme/edge/css/common/ui/Datalist.css"; import "lu2/theme/edge/js/common/ui/Datalist.js"; const myRef = React.createRef(); const datalist = <input class="ui-input" results="5" is="ui-datalist" ref={myRef}/> // 组件 DOM 渲染 ReactDOM.render(datalist, document.getElementById('root')); // 传参,此时 myRef.current 就是组件元素 const data = [{ value: '蔡伦', userid: 1 }, ..., { value: '彭玉乐', userid: 7 }]; if (myRef.current.isConnectedCallback) { myRef.current.params.data = data; } else { myRef.current.addEventListener('connected', function () { this.params.data = data }); }
效果截图示意:
表单验证
测试自定义属性
以上3个示例囊括了 LuLu UI 所有的 UI 组件类型,可以看出,LuLu UI Edge 主题绝对可以在 React 中使用的,只是较少部分组件的使用方式不那么优雅。
TypeScript与LuLu UI
由于 LuLu UI 并非基于某个框架集成的 UI 组件库,因此,对于对格式要求比较严苛的 TypeScript 环境,还需要一些额外的声明工作。
例如,可以在项目中新建一个名为 lu2.d.ts 的文件。然后——
自定义元素的声明,以下拉和选项卡元素举例:
declare namespace JSX { interface IntrinsicElements { "ui-tab": any; } } declare namespace JSX { interface IntrinsicElements { "ui-drop": any; } }
自定义属性需要声明,例如(不是全部,仅示意):
declare namespace React { interface HTMLAttributes<T> { align?: string, open?: boolean, class?: string, maxlength?: string, name?: string, } }
动态加载的 JS 模块也需要声明:
declare module 'lu2/theme/edge/js/common/ui/Tab.js' {} declare module 'lu2/theme/edge/js/common/comp/Form.js' {} declare module 'lu2/theme/edge/js/common/ui/LightTip.js' {} ...
全局实例对象也需要声明:
declare function LightTip(); declare function Dialog();
以上代码均是示意,并未包含所有组件,大家根据使用情况,自行添加即可。也欢迎提供完整版的 lu2.d.ts 文件。
本页贡献者:
zhangxinxu