craftJS

2021/05/14 tools

craft.js的一个记录,体验拖拽式生成网站,写一个简单的demo

1、craft简介

Craft.js通过模块化页面编辑器的构建模块来解决此问题。它提供了拖放系统,并处理了应呈现,更新和移动用户组件的方式。

官网:https://craft.js.org/

2、demo简介

由于craft.js目前才0.1.0-beta.17版本,国内没啥资料,记录一下简单demo的实现,可以快速入门

3、创建项目

项目是使用react,UI框架官方推荐的是material-ui,但是我这里用的是ant design

npx create-react-app mydemo

直接放项目依赖,可能后续版本不一致

"dependencies": {
  "@craftjs/core": "^0.1.0-beta.17",
  "@material-ui/core": "^4.11.4",
  "@testing-library/jest-dom": "^5.11.4",
  "@testing-library/react": "^11.1.0",
  "@testing-library/user-event": "^12.1.10",
  "antd": "^4.15.5",
  "material-ui-color-picker": "^3.5.1",
  "react": "^17.0.2",
  "react-contenteditable": "^3.3.5",
  "react-dom": "^17.0.2",
  "react-scripts": "4.0.3",
  "web-vitals": "^1.0.1"
}

把依赖性放到配置文件里面,安装就好了。

npm install

或者使用yarn,都一样

然后把src/app.js里面的都删掉

import './App.css';

function App() {
  return (
    <div className="App">
    </div>
  );
}

export default App;

然后引入需要的依赖

import React from 'react';
import { Row, Col } from 'antd';
import './App.css';
import { Editor, Frame, Element } from "@craftjs/core";

function App() {
  return (
    <div className="App">
      <Row>
        <Col span={16} className="leftBox">
        </Col>
        <Col span={8} className="toolBox">
          <div>这里放工具栏</div>
        </Col>
      </Row>
    </div>
  );
}

export default App;

修改index.css,把App.css里面的都删了,不删也行,只不过我想删。

@import '~antd/dist/antd.css';
.leftBox {
    border: 1px solid #ccc;
}

.header {
    border-bottom: 1px solid #ccc;
}

.container {
    background: #ccc;
    border: 1px solid rgb(32, 32, 32);
    margin: 10px 0;
    min-height: 40px;
    padding: 10px;
}

.toolBox {
    padding-left: 20px;
}

4、创建Button模块

因为是基于模块开发的,所以要把各个组件都抽离成模块, 项目中一共没用到几个模块,先写一个Button

创建src/conponents/Button.jsx

import React from "react";
import { useNode } from "@craftjs/core";
import { Button } from 'antd';


export const MyButton = (props) => {
  const { connectors: { connect, drag } } = useNode();
  const { text } = props;
  return (
    // 说这个组件是可以拖动的
    <Button ref={ref => connect(drag(ref))} >
      {text}
    </Button>
  )
}

// 给按钮的默认配置,如果不传就走的这个参数,默认文字为`按钮`
export const ButtonDefaultProps = {
  text: '按钮',
};

MyButton.craft = {
  props: ButtonDefaultProps
}

然后在入口app.js引入

import React from 'react';
import { Row, Col } from 'antd';
import './App.css';
import { Editor, Frame, Element } from "@craftjs/core";
import {MyButton} from './conponents/Button'
function App() {
  return (
    <div className="App">
      {/* 这是编辑器的区域,resolve人里面是会用到的组件,需要在这里申明一下 */}
      <Editor resolver=>
        <Row>
          <Col span={16} className="leftBox">
            {/* 编辑区域需要包裹在这个元素里面 */}
            <Frame>
              {/* 生成一个div元素,是一个canvas节点,可以编辑*/}
              <Element is='div' canvas style=>
                <MyButton text="默认的"></MyButton>
                <MyButton text="默认的2"></MyButton>
              </Element>
            </Frame>
          </Col>
          <Col span={8} className="toolBox">
            <div>这里放工具栏</div>
          </Col>
        </Row>
      </Editor>
      
    </div>
  );
}

export default App;

这个时候运行就会发现界面上多了俩按钮,然后就可以拖动这俩按钮交换位置了。

5、创建Container组件

这个组件具体用法可以参考官网https://craft.js.org/r/docs/concepts/user-components#connectors

就是定义一个区域,可以进行编辑

创建src/conponents/Container.jsx

import React from "react";
import { Element, useNode } from "@craftjs/core";
import {Text} from './Text'

export const Container = ({ children }) => {
  const { connectors: { connect, drag } } = useNode();
  return (
    <div ref={ref => connect(drag(ref))} className='container'>
      {children}
    </div>
  )
}

这个我为了看的到效果,在前面有提前定义好样式,然后在app.js里面引入

// 这加了新添加的东西
import { Container } from './conponents/Container';

function App() {
  return (
    <div className="App">
      <Editor resolver=>
        <Row>
          <Col span={16} className="leftBox">
            <Frame>
              {/* 多大的 */}
              <Element is='div' canvas style=>

                {/*...之前的东西*/}
                <Container>
                  <MyButton text="Container里面的按钮"></MyButton>
                </Container>

              </Element>
            </Frame>
          </Col>
        </Row>
      </Editor>
      
    </div>
  );
}

这样就可以看到有一个灰色的区域了,不过这个组件一般都是用来拖拽生成一个区域,然后里面进行编辑的,我们写拖拽工具插件

6、创建Toolbox模块

创建src/conponents/Toolbox.jsx


import React from "react";
import { Element, useEditor } from "@craftjs/core";
import { Container } from "./Container";
import { Row, Col, Button } from 'antd';
import { MyButton } from './Button'


export const Toolbox = () => {
  const { connectors, query } = useEditor();

  return (
    <Row container>
      <Col span={24} container direction="column" >
        <Button ref={ref => connectors.create(ref, <MyButton text="拖拽生成的按钮"/>)}>Button</Button>
      </Col>
      <Col span={24} container direction="column" >
        {/* 注意Container这里:是创建一个element标签,然后表示为Container元素,然后是个canvas节点   这样的才可以进行编辑*/}
        <Button ref={ref => connectors.create(ref, <Element is={Container} padding={20} canvas />)} >Container</Button>
      </Col>
    </Row>
  )
};

然后app.js引入


import { Toolbox } from './conponents/Toolbox'


<Editor resolver=>


  <Col span={8} className="toolBox">
    <div>这里放工具栏</div>
    <Toolbox></Toolbox>
  </Col>
</Editor>

然后就可以拖拽使用了

7、总结

没有写一些文档类型的东西,没有写一些定义之类的东西,因为文档全英文,自己翻译不准,然后具体也没有很明白,只是简单记录一下使用方法,给入个门,最起码可以跑通,然后操作起来,具体扩展就靠自行探索了,最基本的东西就这些,其他更深层次的功能,比如layer待我弄明白再写一篇。

Search

    Table of Contents