Files
dooring/packages/dooringx-dumi-doc/docs/Guide/index.md
2022-09-02 18:06:26 +08:00

7.1 KiB
Raw Blame History

title, toc, order, nav
title toc order nav
介绍 menu 1
title order
指南 1

dooringx-lib 是什么?

dooringx-lib 是 dooringx 的基座,是移除了 dooringx 插件的可视化拖拽框架。

dooringx-lib 提供自己的一套数据流事件机制以及弹窗等解决方案,可以让你更快地自己定制开发可视化拖拽平台。

区别于别的搭建平台,其较为适合制作移动端,主要是绝对定位搭建而非静态定位搭建,绝对定位的拖拽较为方便运营人员理解。

dooringx-lib 如何工作?

dooringx-lib 在运行时维护一套数据流主要分为json数据部分左侧组件部分右侧配置项部分快捷键部分弹窗部分事件与函数部分数据源部分。

其除了提供基础的拖拽、移动、缩放、全选、旋转等功能外,还可以使用暴露的组件。如果觉得组件不够定制化,可以调整样式或者自己重新写。

数据流转是怎样的?

1、页面上渲染主要围绕store中json制作你可以在任何地方通过config.getStore().getData()拿到store数据修改后使用config.setData()设置数据。

2、右侧配置项的开发本质也是通过修改json完成。

3、事件流设计每个组件可以抛出任意个函数组件中可以设置时机比如设置点击组件a按钮或b按钮为触发时机触发后调用事件链。事件链可以设置由多个组件抛出的函数链接而成。

快速上手

首先创建个文件夹例如dooringx-example。

我们推荐使用Umi脚手架快速搭建我们的项目。

在文件夹内使用命令yarn create @umijs/umi-app npx @umijs/create-umi-app

安装dooringx-lib:

yarn add dooringx-lib

lib中部分组件来源于antd和其icon。需要安装antd和icon。动画部分主要使用了animate.css也需要安装下。

yarn add antd @ant-design/icons animate.css

首先新增路由,用于预览显示。编辑根目录下的.umirc.ts:

  routes: [
    {
      exact: false,
      path: '/',
      component: '@/layouts/index',
      routes: [
        { path: '/', component: '@/pages/index' },
        { path: '/preview', component: '@/pages/preview' },
        { path: '/iframe', component: '@/pages/iframe' },
      ],
    },
  ],

src下新增layouts用于嵌套子页面

import { UserConfig } from 'dooringx-lib';
import 'dooringx-lib/dist/dooringx-lib.esm.css';
import { createContext, useState } from 'react';
import { IRouteComponentProps } from 'umi';
import plugin from '../plugin';
import 'antd/dist/antd.css';
import 'animate.css';

export const config = new UserConfig(plugin);
export const configContext = createContext<UserConfig>(config);
config.i18n = false;
export default function Layout({ children }: IRouteComponentProps) {
  return (
    <configContext.Provider value={config}>{children}</configContext.Provider>
  );
}

layout依赖个人定制的plugin我们简单做个测试组件。

src下新增plugin文件夹index.tsx:

import { InitConfig } from 'dooringx-lib';
import { LeftRegistComponentMapItem } from 'dooringx-lib/dist/core/crossDrag';
import { PlayCircleOutlined } from '@ant-design/icons';

const LeftRegistMap: LeftRegistComponentMapItem[] = [
  {
    type: 'basic',
    component: 'button',
    img: 'icon-anniu',
    imgCustom: <PlayCircleOutlined />,
    displayName: '按钮',
    urlFn: () => import('./button'),
  },
];

export const defaultConfig: Partial<InitConfig> = {
  leftAllRegistMap: LeftRegistMap,
  leftRenderListCategory: [
      {
      type: 'basic',
      icon: <HighlightOutlined />,
      displayName: '基础',
    },
  ],
  initComponentCache: {},
  rightRenderListCategory: [],
  initFunctionMap: {},
  initCommandModule: [],
  initFormComponents: {},
};

export default defaultConfig;

src/plugin/button/index.tsx

import { ComponentItemFactory } from 'dooringx-lib';
import { Button } from 'antd';

const Dbutton = new ComponentItemFactory(
  'button',
  '按钮',
  {},
  {
    width: 200,
    height: 55,
  },
  () => {
    return <Button>测试</Button>;
  },
  true,
);
export default Dbutton;


在src/pages/index.tsx处新增编辑器代码

import {
  RightConfig,
  Container,
  useStoreState,
  innerContainerDragUp,
  LeftConfig,
  ContainerWrapper,
  Control,
} from 'dooringx-lib';
import { useContext } from 'react';
import { configContext } from '@/layouts';
import { useCallback } from 'react';
export const HeaderHeight = '40px';
export default function IndexPage() {
  const config = useContext(configContext);
  const subscribeFn = useCallback(() => {
    localStorage.setItem(
      'PREVIEWSTATE',
      JSON.stringify(config.getStore().getData()),
    );
  }, [config]);
  const [state] = useStoreState(config, subscribeFn)
  return (
    <div {...innerContainerDragUp(config)}>
      <div style={{ height: HeaderHeight }}>
        head
        <button
          onClick={() => {
            window.open('/iframe');
          }}
        >
          go preview
        </button>
      </div>
      <div
        style={{
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
          height: `calc(100vh - ${HeaderHeight})`,
          width: '100vw',
        }}
      >
        <div style={{ height: '100%' }}>
          <LeftConfig config={config}></LeftConfig>
        </div>

        <ContainerWrapper config={config}>
          <>
            <Control
              config={config}
              style={{
                position: 'fixed',
                bottom: '60px',
                right: '450px',
                zIndex: 100,
              }}
            ></Control>
            <Container state={state} config={config} context="edit"></Container>
          </>
        </ContainerWrapper>
        <div className="rightrender" style={{ height: '100%' }}>
          <RightConfig state={state} config={config}></RightConfig>
        </div>
      </div>
    </div>
  );
}

此时启动项目,可以看见编辑器已经显示出来了。拖动组件时,也能正确置入画布。

src的pages下新增对应的页面

src/pages/preview/index.tsx

import { configContext } from '@/layouts';
import { Preview } from 'dooringx-lib';
import { useContext } from 'react';

function PreviewPage() {
  const data = localStorage.getItem('PREVIEWSTATE');
  const config = useContext(configContext);
  if (data) {
    try {
      const json = JSON.parse(data);
      config.resetData([json]);
    } catch {
      console.log('err');
    }
  }
  return (
    <div
      style={{
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
      }}
    >
      <Preview config={config}></Preview>
    </div>
  );
}

export default PreviewPage;

src/pages/iframe/index.tsx

function IframePage() {
  return (
    <div
      style={{
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
      }}
    >
      <iframe
        style={{ width: '375px', height: '667px' }}
        src="/preview"
      ></iframe>
    </div>
  );
}
export default IframePage;

此时拖拽组件进入画布后,点击按钮进入预览则可看见预览状态也被渲染出来了。