Appearance
数据视图
描述
视图主要是用来控制页面中绘制的组件,以及组件的各个属性、方法、事件等,通过编辑视图,可以修改页面的呈现与交互。
由于使用页面设计器可以直接设计页面,配置组件,操作视图更简单,也更为方便直观。
因此不建议在此页面管理视图,最好只做查询功能。
如果想要直接修改视图的源代码,那么可以按照下面的说明来操作。
操作
1. 查看
可以查看视图的详细信息。
2. 编辑
可以编辑基础信息。
也可以对视图内容进行友好的可视化代码编辑。
3. 复制
可以对该视图进行复制,以达到快速新建并复用的目的。
4. 删除
删除该视图,并有删除前的信息确认。
5. 寄连
可以查看绑定的寄连,绑定之后,在寄连执行的时候可以直接过去到当前视图内容对象。
6. 页面
可以查看所有使用该视图的页面,方便修改视图的的时候知道会受到影响的页面。
查询
可以通过视图编码、用途描述、数据内容以及ID进行查询,支持模糊查询。
点击空格即可唤出查询窗口,输入条件后按回车键执行查询。
可以多个条件同时输入,支持清空条件。
规范
1. 设计原则
我们将页面中的各个区域进行划分,以行为单位,也就是一个页面由多个行组成,所有的页面元素全部都归属于一个对应的行里面。
每个行可以分成多列,每个列中可以继续包含多行和多列,我们将页面中的元素全部都放到对应的列里面,每个元素都对应着我们预置的某个组件,这样就形成了整个页面。
2. 设计理念
通过json的形式对这些行、列、元素进行描述,可以指定属性、事件、方法、权限等等。页面加载时通过一个或多个这样的json就能够知道该页面的结构,从而进行页面的渲染,以及其他行为的处理。
我们将由此设计出来的json称之为数据视图,因为它通过数据的描述,能够决定页面视图的呈现。
行列
存在最外层的数组中对象的个数,即表示该数据视图包含的行数,如:[{}]
表示一行,[{},{}]
表示两行.
每一行可以包含列,列用col表示,对应数组中包含的对象个数,即表示列数,如:
js
[{
col: [{
}]
}]
[{
col: [{
}]
}]
上面代码表示有一行一列。
每一行是一个对象,对象中可以包含任意属性,通过col来标识包含的列。
每一列也是一个对象,列或者任意组件都具有插槽,通过以#
开头,来表示这个一个插槽,比如:#default
、#header
等等。
其中default插槽可以省略#
标识,相当于关键字。
js
[{
col: [{
_span: 12, //所占列数
default: [] //表示行内的元素,也可理解为 default 插槽
},{
_span: 12,
default: [{
col: [{}]
}]
}]
}]
[{
col: [{
_span: 12, //所占列数
default: [] //表示行内的元素,也可理解为 default 插槽
},{
_span: 12,
default: [{
col: [{}]
}]
}]
}]
表示有一行两列,第二列中又包含了一行一列。
可以给行列添加任意的属性、事件等,其中key的第一个字符为_
的属性,将会自动绑定到该元素上面。
key中带有前缀on_
的属性将被作为事件来进行处理。
js
[{
_class: 'c-red b', //所使用的样式
'_data-role': 'first-row', //绑定的 dataRole 属性值
col: [{
_class: 'p-c',
_span: 12,
//绑定 click 事件
on_click: function() {
console.log('点击了该列')
},
default: []
}]
}]
[{
_class: 'c-red b', //所使用的样式
'_data-role': 'first-row', //绑定的 dataRole 属性值
col: [{
_class: 'p-c',
_span: 12,
//绑定 click 事件
on_click: function() {
console.log('点击了该列')
},
default: []
}]
}]
其中以下划线开头的属性都会被绑定为组件的属性,以on加下划线开头的属性自动绑定为组件的事件
示例 如下放入一个文字组件在列中,并居中显示。is
属性表示该组件是什么组件。
js
[{
//行样式,其中有字体和字体大小等样式,详细解释后面再说。
_class: 'mt-50 ff-zhongSong fw-700 c-red fs-33 mb-10',
col: [{
_span:24,
_class: 'ta-c', //居中样式
default: [{
is: 'lc-text', //渲染一个 text 文本
default: '生知安行、学知利行、困知勉行'
}]
}]
}]
[{
//行样式,其中有字体和字体大小等样式,详细解释后面再说。
_class: 'mt-50 ff-zhongSong fw-700 c-red fs-33 mb-10',
col: [{
_span:24,
_class: 'ta-c', //居中样式
default: [{
is: 'lc-text', //渲染一个 text 文本
default: '生知安行、学知利行、困知勉行'
}]
}]
}]
is属性代表需要渲染的组件,以lc-开头,加上元素名, 比如要渲染一个element-plus的按钮组件可以这样写:is:'lc-button'
注意: 这部分内容仅做理解页面结构使用,不推荐采用编辑JSON配置去开发页面,正常开发页面仅在页面设计器中拖拽组合即可完成页面搭建。
如想要知道某个页面用到的所有数据视图,可点击数据视图管理页面右上角的 输入 pageId 进行查找。
项目代码中预置好了各种可能用到的组件,我们只需要指定组件名称即可将该组件渲染到页面中。
组件
我们的所有组件全部都是放在列中的,某些特殊组件可能还包含一些其他组件。
所有组件的默认内容都是用default字段来指定,如需绑定数据则用_data来绑定。
下面我们来看一个简单的例子:
首先,我们新建一行一列,并填入一些文字。
js
[{
col: [{
default: [{
is: 'lc-text',
default: '中国铁路北京局集团有限公司'
}]
}]
}]
[{
col: [{
default: [{
is: 'lc-text',
default: '中国铁路北京局集团有限公司'
}]
}]
}]
其中is字段是用来指定要渲染的组件,所有需要引用的组件,需要在组件名前面加上lc-前缀,如text组件的引用就是lc-text。
我们来看下页面中的渲染效果。
然后我们添加一些样式,来改变页面呈现。
js
[{
_class: 'mt-50 ff-zhongSong fw-700 c-red fs-33 mb-10',
col: [{
_class: 'ta-c',
default: [{
is: 'lc-text',
default: '中国铁路北京局集团有限公司'
}]
}]
}]
[{
_class: 'mt-50 ff-zhongSong fw-700 c-red fs-33 mb-10',
col: [{
_class: 'ta-c',
default: [{
is: 'lc-text',
default: '中国铁路北京局集团有限公司'
}]
}]
}]
再看下效果。
让我们再追加一列,并在第二列中添加两个元素,一个下拉框和一段文字。
js
[{
_class: 'mt-50 ff-zhongSong fw-700 c-red fs-33 mb-10',
col: [{
_span: 15,
_class: 'ta-c',
default: [{
is: 'lc-text',
default: '中国铁路北京局集团有限公司'
}]
}, {
_span: 9,
default: [{
is: 'lc-select',
model: 'wen_zhong'
}, {
is: 'lc-text',
default: '发文稿纸'
}]
}]
}]
[{
_class: 'mt-50 ff-zhongSong fw-700 c-red fs-33 mb-10',
col: [{
_span: 15,
_class: 'ta-c',
default: [{
is: 'lc-text',
default: '中国铁路北京局集团有限公司'
}]
}, {
_span: 9,
default: [{
is: 'lc-select',
model: 'wen_zhong'
}, {
is: 'lc-text',
default: '发文稿纸'
}]
}]
}]
看看现在的效果。
可以看到通过我们构造的json,页面已经能够成功解析并渲染出来,其中model字段表示如果要提交到后端的话,这个下拉框对应的key。
现在的下拉框暂时是还没有数据的,因为我们没有配置它。通过指定default我们可以对下拉框构造数据。
让我们重新设定一个json,并对下拉框添加数据。
js
[{
col: [{
default: [{
is: 'lc-select',
default: [{
label: '第一项',
value: '1'
},{
label: '第二项',
value: '2'
},{
label: '第三项',
value: '3'
}],
model: 'wen_zhong'
}]
}]
}]
[{
col: [{
default: [{
is: 'lc-select',
default: [{
label: '第一项',
value: '1'
},{
label: '第二项',
value: '2'
},{
label: '第三项',
value: '3'
}],
model: 'wen_zhong'
}]
}]
}]
看下页面效果
让我们再简单的添加一个事件,在选项发生改变的时候执行操作。
js
[{
col: [{
default: [{
is: 'lc-select',
default: [{
label: '第一项',
value: '1'
},{
label: '第二项',
value: '2'
},{
label: '第三项',
value: '3'
}],
on_change: function(e) {
console.log(e)
console.log('选项值发生改变')
},
model: 'wen_zhong'
}]
}]
}]
[{
col: [{
default: [{
is: 'lc-select',
default: [{
label: '第一项',
value: '1'
},{
label: '第二项',
value: '2'
},{
label: '第三项',
value: '3'
}],
on_change: function(e) {
console.log(e)
console.log('选项值发生改变')
},
model: 'wen_zhong'
}]
}]
}]
看下效果
权限
我们通过多种方式来控制用户的权限,可以精准的针对不同的用户来达到效果。
首先从权限维度来说,主要分为两方面:1. 用户拥有的角色,2. 动态配置的code
再从控制的手段来说,也主要分为两方面:1. 操作视图,2. 操作dom元素
由于有交叉部分,并且还有很多细化的地方,因此我们按照实现方式来对此进行说明。
对于权限的控制,我们可以在元素的json对象上添加control来实现。如:
js
[{
col: [{
default: [{
is:'lc-select',
model: 'wen_zhong',
control: {
code: 'wenzhong',
permission: ['roleA', 'roleC'],
noPermission: ['roleM'],
if: function() {
return true
},
call: function() {
console.log('组件渲染完毕,可以执行操作')
},
dom: 'select_wz',
view: 'select_wz'
},
}]
}]
}]
[{
col: [{
default: [{
is:'lc-select',
model: 'wen_zhong',
control: {
code: 'wenzhong',
permission: ['roleA', 'roleC'],
noPermission: ['roleM'],
if: function() {
return true
},
call: function() {
console.log('组件渲染完毕,可以执行操作')
},
dom: 'select_wz',
view: 'select_wz'
},
}]
}]
}]
code
我们在访问不同的页面的时候,可能会根据配置的不同,以及接口返回的数据不同,把得到的一个或多个 code
值存储起来,每个页面都可能是不一样的 code[]
组,当解析该数据视图的时候,会根据当前设定的 code
去对应的 code[]
组里面去查找,如果找到则进行渲染,如果找不到,则直接跳过该数据视图。
permission
用户在登录成功之后,会获取到配置的对应角色组 roles[]
,我们可以为permission字段设定具有一个或多个值的权限组 permission[]
,
如果 permission
中的至少一个字段能够在 roles
中找到,那么就会进行渲染,否则直接跳过该数据视图。
noPermission
我们可以为noPermission字段设定具有一个或多个值的无权限组 noPermission[]
,如果 noPermission[]
中的至少一个字段能够在角色组 roles
中找到,那么就表示该角色无权渲染该数据视图,将会直接跳过,否则一个都未找到的话,那么才会进行渲染。
if
如果需要手动的去做判断,那么可以使用 controlData
字段,它的值可以是字符串或者函数。
作为字符串:将会对字符串进行求值,如 '1==2'
将作为 false
。
作为函数:可以在函数内部执行某些逻辑,函数体内可以通过this获取到当前的视图以及 controlData
和 requestData
。然后手动指定返回值为 true
或者 false
如果 if
返回为 false
,将会跳过该数据视图的渲染,如果返回为true,那么表示有权限,则会进行渲染。
call
当数据视图渲染完成之后,将会调用 call
对应的函数。同样在 call
的函数体内可以通过 this
获取到当前的视图以及 controlData
和 requestData
,并可额外通过$el获取到渲染完成的页面中对应的元素,可以进行一些处理操作,不需要返回值。
dom
根据设定的 dom
字段的值,当元素渲染完成后,可以通过 controlData
对象来访问对应的元素,如上面设定为 select_wz
,那么访问形式就可以这样写:controlData.select_wzDom
,就得到了对页面元素的引用。
view
根据设定的 view
字段的值,当元素渲染完成后,可以通过 controlData
对象来访问对应的视图,如上面设定为 select_wz
,那么访问形式就可以这样写:controlData.select_wzView
,就得到了对该视图的引用。
说明
code
、permission
、noPermission
、if
可以同时存在,但是他们之间有一个优先级的关系,因此设置的时候尽量不要冲突,如 permission
设定为 [roleA]
,noPermission
也设定为 [roleA]
,那么 noPermission
将不会生效,他们之间的优先级关系为:
code > permission > noPermission > if
,当设定产生冲突时,将会按照这个优先级进行处理。
注意 permission
、noPermission
必须要设定为数组的形式,不支持字符串的设定。
当调用 call
函数时,无法从 controlData
中获取dom和view的引用,因为此时可以通过this来进行访问。
dom
和 view
字段都是字符串,他们不做任何逻辑处理,只是保留了元素和视图的引用,以备在其他地方引用。
数据
我们提供了多个数据源来获取需要的数据,由于数据类型的不同,我们使用对象来对他们进行分类管理。
从功能性上主要分为下面几类:
属性值、预置函数、寄连、视图、元素、工具类。
由于细分下来属性特别多。因此我们通过不同的对象来对这些值进行访问。
initData
该对象主要存储一些初始化数据,一般情况下它的属性值不会发生变化,可以通过寄连、请求的方式进行设定,我们也可以手动指定初始化的数据,供之后访问、比较等操作。
collectionData
所有在视图中带有model字段的属性都会被收集到这个对象中,如果某些字段需要发送给后端,那么属性的key应该写成下划线形式,如a_b。所有不带下划线的属性都不会被发送到后端,除非手动强制指定。我们也可以给该对象赋值一些临时的其他属性,这样方便在别的地方都可以访问到。
requestData
所有通过请求返回的数据都会被存储到该对象中,它还包含了两个特殊的属性:
connections
:所有请求中如果设定了code,那么就会被保存在该对象中,以备之后手动触发请求。
codeControl
:带有权限控制的code可以通过这个对象访问到,我们也可以手动指定code属性。
controlData
页面中的所有数据视图都会以code为标识存储在该对象中,我们手动设定的dom和view也会通过它进行访问。
方法
TriggerRequest
可以传入对应请求的code即可发起请求,主要是用来处理手动触发的请求。
PreTriggerRequest
这是一个请求预处理,传入一个请求的code,即可对参数进行求值计算,将返回一个promise,传递回来的参数中包含两个属性:request
和 run
。request
代表当前的请求,可以通过它修改参数或执行其他操作,run
是一个函数,执行之后将会发起真正的请求。
RunIt
通过它来手动执行寄连,第一个参数表示要执行的寄连code,从第二个参数开始,都是要传入寄连函数的参数。
Dater
是对dayjs工具函数的引用,可以处理各种时间相关的问题,详细使用文档可以官网查看dayjs官网
Loading
element-plus中loading服务的引用。
Message
element-plus中message服务的引用。
Tools
包含了预置的各种工具函数。
- 判断是否为字符串或布尔类型等的数据。
- 获取数据的类型对应的字符串。
- 判断是否为空数组或空对象
- 筛选对象属性。
- 下划线、连字符与驼峰形式的属性间相互转换。
- 获取地址栏参数对象或对应变量值。
- 获取后缀名。
- 抛出错误。
- 交换数组中两个元素的位置。
- 查找数组中元素的索引。
- 删除数组中的某个值。
- 手动加载js文件。
- 置空对象。
- 操作cookie。
- 国密4加解密。
- 验证是否为本地或外部地址。
- 验证是否为有效的URL和Email地址
- 等等
C_
主要包含一些快捷函数,比如获取code数据,或者切换元素的显隐
page
pinia中页面的属性和方法。
user
pinia中用户的属性和方法。
menu
pinia中菜单的属性和方法。
route
路由的信息。
TurnToPage
跳转页面,第一个参数为对象,formId、detail、path三个属性必传其一,也可以添加其他属性,作为页面的属性添加到store中,第二个参数可以为路由指定查询参数。
Company
可以获取当前公司配置的所有信息。
说明
所有在数据视图中指定的组件默认都是由element-plus组件来渲染的,如果需要naive组件渲染,可以通过category属性来指定。
所有组件可以绑定的属性和事件都由渲染组件来决定,只要渲染组件支持,那么就可以任意绑定,除此之外,只要是vue支持的属性、方法或事件也可以通过下划线的方式进行设定。
我们还可以额外指定一些不带下划线的附加属性,之后我们可以通过对视图的引用来对这些属性进行访问。
但是有几个特殊的点需要说明一下:
lc-image 组件
指定的图片地址可以为本地或者服务器,如果指定为本地,那么它将以项目的common/images/目录去寻找。
_class 属性
项目中预置了大多数常见的单属性,我们可以通过简写的形式去使用,要想类名生效一定要遵守约定。
举几个例子来说明一下:
- 设置display: none;可以通过d-n。
- 设置color: red;可以通过c-red。
- 设置position: relative;可以通过p-r。
- 设置padding-top: 5px;可以通过pt-5。
- 设置margin-top: -10px;可以通过mt--10;
- 设置background-color: #ffffff;可以通过bc-ffffff;
- 设置width: 50%;可以通过w_50。
类名的设定只要遵循以下几个原则:
- key中没有短横线,则直接取首字母,key中有短横线,则取短横线分割之后的每个首字母。
- value中没有短横线,直接取首字母,value中有短横线,则取短横线分割之后的每个首字母。
- 将上面取到的两部分用短横线拼接起来,这样就构成了简写类名。
- 如果属性是颜色,那么短横线后面就直接拼接去掉#的颜色值,或者完整英文。
- 如果属性是宽高等数值类型,那么默单位为px,短横线后面直接拼接数值即可,如果是负值那么就用两个短横线连接,如果是百分比值那么就用下划线连接。如果是其他单位,那么需要在最后面明确指定。
- 对于有冲突的属性,比如min-width和max-width简写都是mw,那么就需要前缀全拼,即minw-50或maxw-50。
_data 属性
一般我们在为组件做数据绑定的时候使用_data,如el-table就是默认为这个,因此我们的一些自定义组件或者其他的数据绑定都统一定为_data。
default 属性
这个属性规定了组件的默认渲染内容,我们可以理解为是一个默认插槽,当它单独存在的时候那么可以直接写default来指定属性,但是如果存在其他的插槽,则需要写成完整的形式,如:'#default'
、'#header'
等。
理论上来说,任意的组件都有default插槽,default中又可以包含任意的组件,但是实际开发中,我们不会把一个表格作为按钮的默认插槽,在程序方面没有做限制,需要开发人员自己去遵守。
所有的插槽必须为数组的形式来包含其他组件,除了纯文本组件,它的default可以是一个纯字符串。