目录
- 低代码之构建框架1
-
- 1:项目初始化
- 2:src / data.json 数据 ( 容器大小与渲染的表单数据 )
- 3:App.vue ( 导入editor组件传递data.json之中的数据与 向下提供组件配置数据config )
- 4:src / packages / editor.jsx 框架区域样式与组件引入
- 5:editor.scss
- 6:src / packages / editor-block.jsx 子组件
- 7:src / utils / editor.config.jsx 编辑区域的配置文件
- 8:main.js
- 效果
低代码之构建框架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){
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.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;
}
&::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;
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')
return ()=> {
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 编辑区域的配置文件
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'
})
8:main.js
import { createApp } from 'vue'
import App from './App.vue'
import 'element-plus/dist/index.css'
createApp(App).mount('#app')
效果