主要内容
- 完成第一个业务组件LText的书写
- 画布逻辑:完成业务组件属性和表单组件的显示和实时更新
- 代码升级:支持vNode的在vue template中的显示
2-1.将编辑器数据结构添加至vuex store
1.新建两个interface
1.EditorProps{
components: 中间编辑器渲染的数组
currentElement: 当前编辑的是哪个元素,uuid
//...其他的后面补充
}
2.ComponentData{
props: {}
id: uuid生成
name: 业务组件库名称
}
2.安装uuid和@types/uuid。
3.editor文件中引入uuid V4。
4.创建几条测试数据,是某种interface。
5.创建editor的数据。
editor = {
components: 刚创建的测试数据
currentElement: ''
}
6.在store中导入editor模块和类型。加入store的modules中。
7.在editor中引入store,获取store中的components,并展示出来。
2-2.LText组件初步实现
业务组件的属性分为样式属性和其他属性。
比如我有text和fontSize两个属性。
创建LText的组件。
template
中的标签是不固定的 -> 采用component is的写法 传入style class
中间传入text
template
props:{
text: {
type:
},
fontSize: {
type:
}
// p标签或者div
tag: {
type:
default:
}
}
setup(props){
// 从所有的属性中找到样式属性 -> lodash的pick方法 -> computed
}
安装lodash-es(采用ES modules写的)和@types/lodash-es(定义文件)。
在Editor中循环的展示LText。也是用component的is。v-bind绑定props属性。
2-3.LText添加通用属性
有1个问题:
整合LText的props,让业务组件可以快速的添加各种属性。
查看需求文档:
文本组件有通用属性和特有属性。
在src创建defaultProps文件。
创建通用属性的数据结构CommonDefaultProps,并且有默认值。
创建文本的特有属性TextDefaultProps。
TextDefaultProps混入通用属性。
在LText组件中需要转换数据结构。
{
text: {
type:
default:
}
}
用loadash的mapValues方法。
在LText组件中导入转换后的数据结构。
tag不属于通用属性和特有属性。
接着选中所有的样式属性,也就是剔除非样式的属性。用lodash的without的方法。接着修改LText的style。
value.constructor写成了typeof value 一直报错。
做完出现有些属性找不到的问题。
2-4. LText使用hooks重用逻辑
转换数据结构的方法中得从输入推断输出的数据的类型。ts的范型的类型约束。
使用hooks抽取可重用逻辑。
1.获取style的所有相关属性。
2.点击能跳转文本,handleClick的处理。
如果actionType是ulr,还有url时,点击文本能跳转。在hooks中需要判断,并且给他添加handleClick,点击后跳转的逻辑。
LText使用hooks。
2-5.点击模板列表添加到到画布
创建一个componetsList组件。
用v-for循环展示LText组件。用v-bind把属性传过去。
每一个LText外面需要一个div包裹起来,用来隔离。并在div上绑定点击事件(用emit)。
监听componetsList组件的点击事件,然后去store中处理,创建一个newComponent,id、name和props。然后push进components。
2-6.为业务组件属性添加类型的利弊
问题:我们是否特定的interface描述整个业务组件一系列的属性? 添加CommonComponentProps和TextComponentProps两个interface。
hooks中传入的参数 Readonly、Partial。
使用ts,确实害怕定义类型的麻烦。
3-1.获取正在编辑的元素的属性
更新组件的流程:
- 点击某一个组件,选中
- 将它的属性以不同类型的表单呈现在右侧
- 编辑表单中的值,在值更新的同时将数据更新至页面
创建一个EditWrapper组件。
首先给组件传入id,id是必传的。
发射一个事件(用emits)
在setup中,创建一个onItemClick方法,用来发射事件(id)。
在div上绑定这个事件。div中用slot。
在Editor的展示区替换掉EditWrapper组件。
将setActive方法绑定到EditWrapper组件上。
store的mutations中增加一个方法setAction。
setAction(){
更新current.Element
}
interface ComponentData{
props: ___
id:___
name:___
}
给store添加getters,通过id找到当前的element。
去Editor中添加currentElement。给它添加范型(联合类型)。
右侧sidebar中用pre标签展示currentElement。
测试: 点击画布区域的某一个元素,右侧sidebar展示出来它的属性们。
逻辑写完了,现在加一些css。
被选中的组件有一个边框高亮。
给EditWrapper组件添加一个属性active。用active来控制样式。active为true时加一个蓝色的边框。active从父组件中传递,通过判断该id和currentElement的id是否一样。
3-2. 添加属性和表单的基础对应关系并展示
界面到数据的抽象。
const textComponentProps = {
text: 'hello',
color: '#fff'
}
创建一个interface{
有component
还有一个可选的value
}
const propsMap = {
text: {
component: 'input'
},
color: {
componnet: 'color-picker'
}
}
// 循环所有的属性,在每个属性中去渲染出处理这个属性的组件
用ts的属性循环 => {
component: '',
value: ''
}
创建src/propsMap.ts文件。
传入的数据转换成界面。
创建一个PropsTable的组件。
传入的数据,判断是否在propsMap中,如果有才能转换成{component: '', value: ''}这样格式的。所以之前的lodash的mapToVaules方法不能用了。采用reduce。还用到了类型断言。
处理完的数据v-for循环展示。
最后实现的功能就是点击画布编辑的某一个元素,右侧显示出currentElement的所有属性,例如text=>去展示一个input。
3-3.添加更多的简单对应关系并展示
text---文本————a-input/a-textarea
lineHeight---数字————a-slider
fontSize---数字————a-input-number
首先先去propsMap中添加对应的关系。
要给表单组件添加一系列属性,比如a-slider想设置min、max和step。
给interface PropToForm的a-slider增加一个extraProps。[key: string]
组件需要v-bind传递extraProps。
再去添加一个rows是3的textarea。
给每一个属性组件添加一个属性标签。
断言里加一个Required。可选变成必选。
3-4.添加更多复杂对应关系并展示
fontFamily---几个文本之一————a-select textAlign---几个文本之一————a-radio-group
扩展PropToForm的interface。比如说选项按钮,需要子组件,增加subComponent属性。options数组。
v-for循环展示,用template包裹。
传入的属性有的需要转换格式。
PropToForm增加一个函数initialTransform,用来给属性转换格式。(这里代码写的不太对)
再去PropsTable中把value进行转换。
fontSize也要"20px" => 20
3-5.分析展示和编辑属性的"金科玉律"
还有一些组件是ant-design没有的,自己需要开发。 颜色选择组件。 特殊的checkbox。
<edit-component :value="#111111/123/[1,2,3]" />
<edit-component :valueProp="#111111/123/[1,2,3]" />
PropToForm还需要加一个valueProp的动态属性。会给component传入:[value.valueProp]的值。
不知道这在干嘛?
必须提供一个属性传入需要编辑的值,默认为value
必须提供一个事件发射出编辑后的新的值,默认为change
3-6.添加编辑表单并更新界面
给PropsTables添加emits。
PropsToForm添加属性eventName和events。
给component绑定事件。v-on。
两个有区别的数据结构。PropToForm精简一些,只是为了渲染表单。然后去PropsTable定义一个更复杂的结构FormProps, 加上events, 它的类型是一个object,里面是key对应方法。
优化reduce方法,定义一个新的变量FormProps类型。在event定义中发射事件change,传参key和value。类型断言也要改。
PropsTable发射事件,在Editor上接收事件。
测试: 修改右边组件Form的值,可以接收发射的事件。
3-7.添加编辑表单并更新界面
PropsToForm中不仅要定义正向的转换initialTransform,还要定义反向的转换afterTransform。
其中text、textAlign需要获取到e.target.value。
fontSize需要加px,和删px。
lineHeight: string = number。
在发送事件时去调用transform。
Editor中handleChange中commit方法updateComponent。store的mutations增加一个updateComponent。寻找currentElement元素,然后修改属性。
3-8.提出优化需求,以及组件返回的真相
1.字体选择的时候,下拉菜单没有字体的例子显示。
将文本转换为vNode。
<div>{{ text }}</div>
把这里的text转换成vnode。
ts=>Vue.h方法。
tsx=>直接写标签,最后断言成VNode。
2.在编辑器组件的右侧添加一个删除图标,点击后可以将该元素删除。
3.添加更多属性和组件的对应关系。比如Opacity。