vue3 低代码实现分享
前端开发


LText.vue
<template>
<component
:is="tag"
:style="styleProps"
@click="handleClick"
class="l-text-component"
>{{ text }}</component
>
</template>
<script>
import { defineComponent } from "vue";
import {
transformToComponentProps,
textDefaultProps,
textStylePropNames,
} from "../defaultProps";
import useComponentCommomn from "../hooks/useComponentCommomn";
const defaultProps = transformToComponentProps(textDefaultProps);
export default defineComponent({
name: "l-text",
props: {
tag: {
type: String,
default: "div",
},
...defaultProps,
},
setup(props) {
const { styleProps, handleClick } = useComponentCommomn(
props,
textStylePropNames
);
return {
styleProps,
handleClick,
};
},
});
</script>
<style scoped>
h2.l-text-component,
p.l-text-component {
margin-bottom: 0;
}
button.l-text-component {
padding: 5px 10px;
cursor: pointer;
}
.l-text-component {
box-sizing: border-box;
white-space: pre-wrap;
position: relative !important;
}
</style>
propsMap.js
import { h } from "vue";
const fontFamilyArr = [
{ text: "宋体------", value: '"SimSun","STSong"' },
{ text: "微软雅黑--", value: '"Microsoft YaHei","微软雅黑"' },
{
text: "苹方/黑体-简",
value: '"PingFang SC","Hiragino Sans GB","Microsoft YaHei"',
},
{
text: "系统默认--",
value: 'system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI"',
},
{ text: "楷体-----", value: '"KaiTi","STKaiti"' },
{ text: "仿宋-----", value: '"FangSong","STFangsong"' },
{ text: "新宋体----", value: '"NSimSun"' },
{ text: "华文细黑----", value: '"STXihei","华文细黑"' },
{ text: "幼圆-----", value: '"YouYuan","幼圆"' },
];
const fontFamilyOptions = fontFamilyArr.map((font) => {
return {
value: font.value,
text: h("span", { style: { fontFamily: font.value } }, font.text),
};
});
export const mapPropsToForms = {
text: {
text: "文本",
component: "a-textarea",
extraProps: { rows: 3 },
afterTransform: (e) => e.target.value,
},
fontSize: {
text: "字号",
component: "a-input-number",
initalTransForm: (v) => parseFloat(v),
afterTransform: (e) => (e ? e + "px" : ""),
},
lineHeight: {
text: "行高",
component: "a-slider",
extraProps: { min: 0, max: 3, step: 0.1 }, // a-slider组件里的属性
initalTransForm: (v) => parseFloat(v),
afterTransform: (e) => e.toString(),
},
textAlign: {
component: "a-radio-group",
subComponent: "a-radio-button",
text: "对齐",
options: [
{ value: "left", text: "左" },
{ value: "center", text: "中" },
{ value: "right", text: "右" },
],
afterTransform: (e) => e.target.value,
},
fontFamily: {
component: "a-select",
subComponent: "a-select-option",
text: "字体",
options: [{ text: "无--------", value: "" }, ...fontFamilyOptions],
},
color:{
component:'color-picker',
text: "字体颜色",
}
};
EditorView.vue
<script>
import { computed, defineComponent } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useStore } from "vuex";
import LText from "./components/LText.vue";
import LImage from "./components/LImage.vue";
import ComponentList from "./components/ComponentList.vue";
import defaultTextTemplates from "./defaultTextTemplates";
import EditWrapper from "./components/EditWrapper.vue";
import PropsTable from "./components/PropsTable.vue";
import Uploader from "./components/Uploader.vue";
export default defineComponent({
components: { LText, ComponentList, EditWrapper, PropsTable, Uploader ,LImage},
setup() {
const store = useStore();
const editorComponents = computed(() => store.state.editor.components);
const currentElement = computed(() => store.getters.getCurrentElement);
const addItem = (props) => {
console.log(props);
store.commit("addComponent", props);
};
const setActive = (id) => {
store.commit("setActive", id);
};
const handleChange = (it) => {
console.log(it);
store.commit("updateComponent", it);
};
return {
editorComponents,
defaultTextTemplates,
addItem,
setActive,
currentElement,
handleChange,
};
},
});
</script>
<template>
<!-- <h2>AboutView</h2>
<label>
Search: <input v-model.trim="search" maxlength="20">
</label> -->
<a-row :gutter="16" type="flex" style="width: 100vw">
<a-col class="gutter-row" :span="8" style="width: 100%">
<div class="gutter-box">
<div>组件列表</div>
<div>
<component-list :list="defaultTextTemplates" @onItemClick="addItem" />
</div>
<div>
<uploader @onItemClick="addItem" />
</div>
</div>
</a-col>
<a-col class="gutter-row" :span="8" style="width: 100%">
<div class="gutter-box">
<div>画布区域</div>
<div class="huabu">
<edit-wrapper
v-for="c in editorComponents"
:key="c.id"
:id="c.id"
:active="c.id === (currentElement && currentElement.id)"
@setActive="setActive"
>
<component v-bind="c.props" :is="c.name" />
</edit-wrapper>
</div>
</div>
</a-col>
<a-col class="gutter-row" :span="8" style="width: 100%">
<div class="gutter-box">
<div>组件属性</div>
<div>
<PropsTable
v-if="currentElement && currentElement.props"
:props="currentElement.props"
@change="handleChange"
/>
</div>
<pre> {{ currentElement && currentElement.props }}</pre>
</div>
</a-col>
</a-row>
</template>
<style scoped>
.huabu {
background: #c4c1c1;
height: 500px;
}
</style>
等等等
![[衡天云]爆款云服务器 低至12元/月](/hty.png)