如果你想看更多的资讯与学习教程,请到b站关注 傻梦兽 UP主,我在b站等你喔!
【傻梦兽的个人空间-哔哩哔哩】 b23.tv/2B9INMH
与标题一样,最近一个月我收到一个需求。需要做一个跨段的组件库,而且这个ui库是支持sdk的修改功能并且是跨平台的。
在面对这个需求之前,我和你们的大多数的人的思路是一样的,那就是想基于Web Component去完成这个需求,但后面了解下后Web Component并没有Asp,PHP,React这类HTML切入脚本语言这么强大。
我最终还是选择了基于React进行一波改造,当然并不会选择React因为它比较大,我最终把框架指向了Preact或fre。在强大的社区面前我最终选择了基于Preact。
使用这个ui sdk之后,我们可以做什么事情?因为这是一个基于面向对象管理。所以在低代码会有更好的管理与修改,我们先看看代码编写风格。如果你是做个java项目或者做个ng这一类面向对象开发的经验的话会很容易看出我在做什么。
// 创建一个渲染挂载的对象
const app = document.getElementById("app") as HTMLElement;
const reui = new ReUI(app);
// 初始化数据
reui.start();
reui.SetMode(UIMode.Editor);
// 创建page对象
const page = reui.AddPage()
// 目前业务我只实现了浮动ui的一个业务组件
const f = page.CreateFloatUI();
// 在这个浮动UI创建一个Button
f.CreateButton()
// 设置他的属性
f.SetDx(100)
f.SetDy(100)
f.SetRounded(16);
f.CreateMaterialSelect();
f.SetPosition(Position.TopLEft);
const t = f.CreateText() as TextComponentStore;
t.SetStyleToH2();
可以看出我是把我们平时操作低代码的JSON对象全部以对象的形式进行操作。 最后我们只需要这些类的依赖关系进行序列化与反序列化即可。
console.log(JSON.stringify(reui.GetData(), null, 3));
/**
* 将 sotre 反序列化
*/
public GetData() {
const pages = StoreUntis.GetPageUIList(this.store);
const components = pages.map(p => {
return {
tag: p.tag,
uuid: p.GetUUID(),
children: p.components.value.map(v => v.Serialization())
}
})
const options = {};
return {
components,
options
}
}
那如何进行initData呢?主要的思路
initData(data: UIData) {
if (data && data.hasOwnProperty("components")) {
this.views.value = this.createComponentStores(data.components);
}
}
createComponentStores(componentsData: ComponentData[]) {
const componentStores: ComponentStore[] = [];
componentsData.forEach(componentData => {
if (!componentData.tag) {
return;
}
const ComponentStoreBuilder = ComponentStoreMap.get(componentData.tag);
if (!ComponentStoreBuilder) {
return;
}
const component = new ComponentStoreBuilder(componentData);
if (componentData.hasOwnProperty("children")) {
component.setCompoents(this.createComponentStores(componentData.children));
}
componentStores.push(component);
});
return componentStores;
}
App.tsx
export const Application = () => {
const views = ReUI.instance.store.views;
return <div>{VnodeDOM.RenderComponents(views.value)}</div>;
};
是的我们实现了一个signals功能,然后通过subscribe的方式进行去触发preact的渲染render方法。然后每一个组件都是监听一个props.
import './styles/index.css';
import classnames from "classnames";
import { h } from "preact";
import { ImageComponentStore } from ".";
import { RenderComponentProps } from "../../../core/props";
interface ImageProps extends RenderComponentProps {
component: ImageComponentStore
}
export const Image = (props: ImageProps) => {
const { component } = props;
const { uri, href, isEditorMode } = component;
const handleClick = () => {
if (isEditorMode) {
} else {
handlerPreviewMode();
}
}
const handlerPreviewMode = () => {
if (href) {
window.open(href);
}
}
return (
<img className={classnames(
'w-full', 'rounded-lg', 'realibox-image', 'flex', 'justify-center', 'items-center',
'bg-contain', 'bg-no-repeat', 'bg-center'
)}
onClick={handleClick}
src={uri}
draggable={false}
/>
)
};
为了让组件可以添加扩展必须继承一个ComponentStore
export class ImageComponentStore extends ComponentStore {
tag = ComponentType.Image;
// uri
private _uri = signal("");
// ... codeing
constructor(componentsData: ImageComponentData) {
super(componentsData);
this.update({
uri: componentsData.uri,
href: componentsData.href,
});
}
public SetUrl(value: string) {
this.uri = value;
}
public Serialization() {
return {
tag: this.tag,
uuid: this.GetUUID(),
uri: this.uri,
href: this.href
}
}
}
最后我们看看成果。
我们可以像低代码一样操作它。
甚至可以在Vue的团队里面通过我给出的的GetData序列化,在Vue项目里面通过initData方法进行反序列化渲染出来,并且带有跟随热点的功能。