Skip to content

数据视图

描述

视图主要是用来控制页面中绘制的组件,以及组件的各个属性、方法、事件等,通过编辑视图,可以修改页面的呈现与交互。

由于使用页面设计器可以直接设计页面,配置组件,操作视图更简单,也更为方便直观。

因此不建议在此页面管理视图,最好只做查询功能。

如果想要直接修改视图的源代码,那么可以按照下面的说明来操作。

操作

1. 查看

可以查看视图的详细信息。

2. 编辑

可以编辑基础信息。

也可以对视图内容进行友好的可视化代码编辑。

数据视图代码.png

3. 复制

可以对该视图进行复制,以达到快速新建并复用的目的。

4. 删除

删除该视图,并有删除前的信息确认。

5. 寄连

可以查看绑定的寄连,绑定之后,在寄连执行的时候可以直接过去到当前视图内容对象。

6. 页面

可以查看所有使用该视图的页面,方便修改视图的的时候知道会受到影响的页面。

查询

数据视图查询.png

可以通过视图编码、用途描述、数据内容以及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。

我们来看下页面中的渲染效果。

视图渲染文字.png

然后我们添加一些样式,来改变页面呈现。

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: '中国铁路北京局集团有限公司'
    }]
  }]
}]

再看下效果。

视图渲染文字样式.png

让我们再追加一列,并在第二列中添加两个元素,一个下拉框和一段文字。

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: '发文稿纸'
    }]
  }]
}]

看看现在的效果。

视图加下拉框.png

可以看到通过我们构造的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'
    }]
  }]
}]

看下页面效果

视图下拉选项.png

让我们再简单的添加一个事件,在选项发生改变的时候执行操作。

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'
    }]
  }]
}]

看下效果

视图下拉选择改变值.png

权限

我们通过多种方式来控制用户的权限,可以精准的针对不同的用户来达到效果。

首先从权限维度来说,主要分为两方面: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获取到当前的视图以及 controlDatarequestData。然后手动指定返回值为 true或者 false

如果 if返回为 false,将会跳过该数据视图的渲染,如果返回为true,那么表示有权限,则会进行渲染。

call

当数据视图渲染完成之后,将会调用 call对应的函数。同样在 call的函数体内可以通过 this获取到当前的视图以及 controlDatarequestData,并可额外通过$el获取到渲染完成的页面中对应的元素,可以进行一些处理操作,不需要返回值。

dom

根据设定的 dom字段的值,当元素渲染完成后,可以通过 controlData对象来访问对应的元素,如上面设定为 select_wz,那么访问形式就可以这样写:controlData.select_wzDom,就得到了对页面元素的引用。

view

根据设定的 view字段的值,当元素渲染完成后,可以通过 controlData对象来访问对应的视图,如上面设定为 select_wz,那么访问形式就可以这样写:controlData.select_wzView,就得到了对该视图的引用。

说明

codepermissionnoPermissionif可以同时存在,但是他们之间有一个优先级的关系,因此设置的时候尽量不要冲突,如 permission设定为 [roleA]noPermission也设定为 [roleA],那么 noPermission将不会生效,他们之间的优先级关系为:

code > permission > noPermission > if,当设定产生冲突时,将会按照这个优先级进行处理。

注意 permissionnoPermission必须要设定为数组的形式,不支持字符串的设定。

当调用 call函数时,无法从 controlData中获取dom和view的引用,因为此时可以通过this来进行访问。

domview字段都是字符串,他们不做任何逻辑处理,只是保留了元素和视图的引用,以备在其他地方引用。

数据

我们提供了多个数据源来获取需要的数据,由于数据类型的不同,我们使用对象来对他们进行分类管理。

从功能性上主要分为下面几类:

属性值、预置函数、寄连、视图、元素、工具类。

由于细分下来属性特别多。因此我们通过不同的对象来对这些值进行访问。

initData

该对象主要存储一些初始化数据,一般情况下它的属性值不会发生变化,可以通过寄连、请求的方式进行设定,我们也可以手动指定初始化的数据,供之后访问、比较等操作。

collectionData

所有在视图中带有model字段的属性都会被收集到这个对象中,如果某些字段需要发送给后端,那么属性的key应该写成下划线形式,如a_b。所有不带下划线的属性都不会被发送到后端,除非手动强制指定。我们也可以给该对象赋值一些临时的其他属性,这样方便在别的地方都可以访问到。

requestData

所有通过请求返回的数据都会被存储到该对象中,它还包含了两个特殊的属性:

connections:所有请求中如果设定了code,那么就会被保存在该对象中,以备之后手动触发请求。

codeControl:带有权限控制的code可以通过这个对象访问到,我们也可以手动指定code属性。

controlData

页面中的所有数据视图都会以code为标识存储在该对象中,我们手动设定的dom和view也会通过它进行访问。

方法

TriggerRequest

可以传入对应请求的code即可发起请求,主要是用来处理手动触发的请求。

PreTriggerRequest

这是一个请求预处理,传入一个请求的code,即可对参数进行求值计算,将返回一个promise,传递回来的参数中包含两个属性:requestrunrequest代表当前的请求,可以通过它修改参数或执行其他操作,run是一个函数,执行之后将会发起真正的请求。

RunIt

通过它来手动执行寄连,第一个参数表示要执行的寄连code,从第二个参数开始,都是要传入寄连函数的参数。

Dater

是对dayjs工具函数的引用,可以处理各种时间相关的问题,详细使用文档可以官网查看dayjs官网

Loading

element-plus中loading服务的引用。

Message

element-plus中message服务的引用。

Tools

包含了预置的各种工具函数。

  1. 判断是否为字符串或布尔类型等的数据。
  2. 获取数据的类型对应的字符串。
  3. 判断是否为空数组或空对象
  4. 筛选对象属性。
  5. 下划线、连字符与驼峰形式的属性间相互转换。
  6. 获取地址栏参数对象或对应变量值。
  7. 获取后缀名。
  8. 抛出错误。
  9. 交换数组中两个元素的位置。
  10. 查找数组中元素的索引。
  11. 删除数组中的某个值。
  12. 手动加载js文件。
  13. 置空对象。
  14. 操作cookie。
  15. 国密4加解密。
  16. 验证是否为本地或外部地址。
  17. 验证是否为有效的URL和Email地址
  18. 等等

C_

主要包含一些快捷函数,比如获取code数据,或者切换元素的显隐

page

pinia中页面的属性和方法。

user

pinia中用户的属性和方法。

pinia中菜单的属性和方法。

route

路由的信息。

TurnToPage

跳转页面,第一个参数为对象,formId、detail、path三个属性必传其一,也可以添加其他属性,作为页面的属性添加到store中,第二个参数可以为路由指定查询参数。

Company

可以获取当前公司配置的所有信息。

说明

所有在数据视图中指定的组件默认都是由element-plus组件来渲染的,如果需要naive组件渲染,可以通过category属性来指定。

所有组件可以绑定的属性和事件都由渲染组件来决定,只要渲染组件支持,那么就可以任意绑定,除此之外,只要是vue支持的属性、方法或事件也可以通过下划线的方式进行设定。

我们还可以额外指定一些不带下划线的附加属性,之后我们可以通过对视图的引用来对这些属性进行访问。

但是有几个特殊的点需要说明一下:

lc-image 组件

指定的图片地址可以为本地或者服务器,如果指定为本地,那么它将以项目的common/images/目录去寻找。

_class 属性

项目中预置了大多数常见的单属性,我们可以通过简写的形式去使用,要想类名生效一定要遵守约定。

举几个例子来说明一下:

  1. 设置display: none;可以通过d-n。
  2. 设置color: red;可以通过c-red。
  3. 设置position: relative;可以通过p-r。
  4. 设置padding-top: 5px;可以通过pt-5。
  5. 设置margin-top: -10px;可以通过mt--10;
  6. 设置background-color: #ffffff;可以通过bc-ffffff;
  7. 设置width: 50%;可以通过w_50。

类名的设定只要遵循以下几个原则:

  1. key中没有短横线,则直接取首字母,key中有短横线,则取短横线分割之后的每个首字母。
  2. value中没有短横线,直接取首字母,value中有短横线,则取短横线分割之后的每个首字母。
  3. 将上面取到的两部分用短横线拼接起来,这样就构成了简写类名。
  4. 如果属性是颜色,那么短横线后面就直接拼接去掉#的颜色值,或者完整英文。
  5. 如果属性是宽高等数值类型,那么默单位为px,短横线后面直接拼接数值即可,如果是负值那么就用两个短横线连接,如果是百分比值那么就用下划线连接。如果是其他单位,那么需要在最后面明确指定。
  6. 对于有冲突的属性,比如min-width和max-width简写都是mw,那么就需要前缀全拼,即minw-50或maxw-50。
_data 属性

一般我们在为组件做数据绑定的时候使用_data,如el-table就是默认为这个,因此我们的一些自定义组件或者其他的数据绑定都统一定为_data。

default 属性

这个属性规定了组件的默认渲染内容,我们可以理解为是一个默认插槽,当它单独存在的时候那么可以直接写default来指定属性,但是如果存在其他的插槽,则需要写成完整的形式,如:'#default''#header'等。

理论上来说,任意的组件都有default插槽,default中又可以包含任意的组件,但是实际开发中,我们不会把一个表格作为按钮的默认插槽,在程序方面没有做限制,需要开发人员自己去遵守。

所有的插槽必须为数组的形式来包含其他组件,除了纯文本组件,它的default可以是一个纯字符串。