低代码01之构建项目框架

低代码之构建框架1

1:项目初始化

  • vue create vue-lesson 初始化项目文件
  • npm i 初始化 package.json
  • package.json 配置运行脚本
    {
      "name": "vue-lesson",
      "version": "0.1.0",
      "private": true,
      "scripts": {
        "serve": "vue-cli-service serve",
        "build": "vue-cli-service build"
      },
      "dependencies": {
        "core-js": "^3.8.3",
        "element-plus": "^2.3.6",
        "vue": "^3.2.13"
      },
      "devDependencies": {
        "@vue/cli-plugin-babel": "~5.0.0",
        "@vue/cli-service": "~5.0.0",
        "sass": "^1.32.7",
        "sass-loader": "^12.0.0"
      }
    }
    
  • 安装依赖
    npm i element-plus
    

2:src / data.json 数据 ( 容器大小与渲染的表单数据 )

{
  "container":{
    "width":550,
    "height":550
  },
  "blocks":[
    {"top":100,"left":100,"zIndex":1,"key":"text"},
    {"top":200,"left":200,"zIndex":1,"key":"button"},
    {"top":300,"left":300,"zIndex":1,"key":"input"}
  ]
}

3:App.vue ( 导入editor组件传递data.json之中的数据与 向下提供组件配置数据config )

<template>
  <div class="app">
    <Editor v-model="state"></Editor>
  </div>
</template>

<script>
import { provide, ref } from "vue";
import data from "./data.json";
import Editor from "./packages/editor"
import { registerConfig as config } from "./utils/editor.config";
export default {
  components:{
    Editor
  },
  setup() {
    const state = ref(data);
    provide('config',config) // 把组件配置传入
    return {
      state,
    };
  },
};
</script>
<style lang="scss">
html,body,#app{
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}
.app {
  background: #fff;
  width: 100%;
  height: 100%;
}
</style>

4:src / packages / editor.jsx 框架区域样式与组件引入

import { computed, defineComponent ,inject} from "vue";
import "./editor.scss"
import EditorBlock from "./editor-block";
export default defineComponent({
  props:{
    modelValue:{
      type:Object
    },

  },
  setup(props){
    // console.log('props',props.modelValue);
    const data = computed({
      get () {
        return props.modelValue
      }
    })
    const contentStyle = computed(()=>({
      width: data.value.container.width + 'px',
      height: data.value.container.height + 'px'
    }))
    const config = inject('config')
    return () => <div class='editor'>
        <div class='editor-left'>
          {/** 根据config的注册列表 渲染出左侧的物料区域 */}
            { 
              config.componetsList.map(component=>(
                <div class="editor-left-item">
                  <span class="editor-left-item-label">{ component.label }</span>
                  <div>{ component.preview() }</div>
                </div>
              ))
            }
        </div>
        <div className="editor-center">
          <div class="editor-top">top</div>
          <div class="editor-content">
            {/* 负责尝试滚动条 */}
            <div class="editor-content-canvas">
              {/* 产生内容区域 */}
              <div class="editor-content-canvas_content" style={contentStyle.value}>
                {
                  (data.value.blocks.map(block=>
                    (<EditorBlock block={block}>
                    </EditorBlock>)
                  ))
                }
              </div>
            </div>
          </div>
        </div>

        <div class="editor-right">right</div>
    </div>
  }
})

5:editor.scss

.editor {
  width: 100%;
  height: 100%;
  overflow: hidden;
  display: flex;
  .editor-left ,.editor-right{
    width: 270px;
    background: yellow;
    height: 100%;
  }
  .editor-left {
    .editor-left-item {
      position: relative;
      width: 250px;
      margin: 20px auto;
      display: flex;
      justify-content: center;
      align-items: center;
      background: #ccc;
      padding: 20px;
      box-sizing: border-box;
      cursor: move;
      user-select: none; // 无法操作
      min-height: 100px;
      .editor-left-item-label {
        position: absolute;
        left: 0;
        top: 0;
        background: rgb(96, 205, 224);
        color: #fff;
        padding: 4px;
      }
      // 设置 item 项目不可点击等
      &::after {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: #ccc;
        opacity: 0.2;
      }
    }
  }
  .editor-center {
    width: calc(100% - 270px - 270px - 20px);
    padding: 0 10px;
    background: orange;
    height: 100%;
  }
  .editor-top {
    height: 80px;
    background: pink;
  }
  .editor-content {
    height: calc(100% - 80px);
    background: orange;
    .editor-content-canvas {
      overflow: scroll;
      height: 100%;
    }
    .editor-content-canvas_content {
      position: relative;
      margin: 20px auto;
      // height: calc(100% - 40px);
      // width: 550px;
      // height: 550px;
      background: #ccc;
    }
  }
}
.editor-block {
  position: absolute;
}

6:src / packages / editor-block.jsx 子组件

import { computed, defineComponent,inject } from "vue";

export default defineComponent({
  props:{
    block:{type:Object}
  },
  setup(props){
    const blockStyle = computed(()=>({
      top:`${props.block.top}px`,
      left: `${props.block.left}px`,
      zIndex:`${props.block.zIndex}`

    }))
    const config = inject('config') // 获取从app.vue 提供的组件配置
    return ()=> {
      // 通过block之中的key 获取config之中对应的组件
      const component = config.componetsMap[props.block.key];
      console.log('component',component);
      // 获取组件的渲染函数
      const componentRender = component.render();
      return <div class="editor-block" style={blockStyle.value}>
        {componentRender}
      </div>
    }

  }
})

7:src / utils / editor.config.jsx 编辑区域的配置文件

// 列表区可以显示所有的物料
// key对应的组件隐射关系

import { ElButton,ElInput } from "element-plus"
function createEditorConfig(){
  const componetsList = []
  const componetsMap = {}

  return {
    componetsList,
    componetsMap,
    register:(component)=>{
      componetsList.push(component)
      componetsMap[component.key] = component
    }
  }
}

export let registerConfig = createEditorConfig()
console.log('registerConfig',registerConfig);
// 文本
registerConfig.register({
  label:'文本',
  preview:()=> '预览文本',
  render:()=> '渲染文本',
  key:'text'
})
registerConfig.register({
  label:'按钮',
  preview:()=> <ElButton>预览按钮</ElButton>,
  render:()=> <ElButton>渲染按钮</ElButton>,
  key:'button'
})
registerConfig.register({
  label:'输入框',
  preview:()=> <ElInput placeholder='预览输入框'></ElInput>,
  render:()=> <ElInput placeholder='渲染输入框'></ElInput>,
  key:'input'
})

// echarts等

8:main.js

import { createApp } from 'vue'
import App from './App.vue'
import 'element-plus/dist/index.css'

createApp(App).mount('#app')

效果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值