封装element ui的table组件,vueelement表单封装

  封装element ui的table组件,vueelement表单封装

  本文主要介绍如何封装vue元素的table表组件,帮助你更好的理解和使用Vue框架。感兴趣的朋友可以了解一下。

  封装Vue组件时,我还是会交叉使用功能组件。关于功能组件,我们可以把它看作是组件中的一个函数,其中参数是渲染上下文,返回值是渲染的HTML(VNode)。适用于外部组件只是内部组件的逻辑封装,但渲染的模板结构变化不大,且必须无状态、实例化的情况。无状态意味着它不具备创建、挂载、更新等生命周期功能。Vue,实例化意味着它没有响应数据data和这个上下文。

  先说一个简单的Vue功能组件的例子,然后根据这个例子详细介绍。

  导出默认值{

  功能性:真的,

  道具:{},

  render(createElement,context) {

  返回createElement(span , hello world )

  }

  }

  Vue提供了一个功能开关,当设置为true时,可以使组件成为无状态的实例化功能组件。因为只是一个功能,渲染的成本比较小。

  函数组件中的Render函数提供了两个参数,createElement和context。让我们来学习第一个参数,createElement。

  CreateElement用于创建虚拟DOM节点VNode。它接收三个参数。第一个参数可以是DOM节点字符串、Vue组件或返回字符串或Vue组件的函数。第二个参数是对象,可选,定义渲染组件所需的参数;第三个参数是一个子虚拟节点,它可以是一个由createElement函数创建的组件、一个普通的字符串(如“hello world”)、一个数组或一个返回字符串或Vue组件的函数。

  CreateElement有几点需要注意:

  如果createElement的第一个参数是组件,第三个参数可以省略,即使写了也是无效的。

  render函数可以监听on事件中组件$emit发出的事件。

  在2.3.0之前的版本中,如果一个功能组件想要接收prop,prop选项是必需的。在2.3.0或更高版本中,可以省略props选项,组件上的所有属性将自动隐式解析为prop。

  函数组件中Render的第二个参数是context上下文,通过它可以访问数据、道具、槽、子对象和父对象。

  在2.5.0及以上版本中,如果使用单文件组件,那么基于模板的功能组件可以声明如下:模板功能/模板。但是,如果Vue组件中的render函数存在,Vue构造函数将不会从提取自template选项或el选项指定的mount元素的HTML模板中编译呈现函数。也就是说,templete和render函数不能共存于一个组件中。如果组件中有template,那么即使有render函数也不会执行render函数,因为template选项的优先级高于render选项。

  至此,Vue功能组件的引入基本完成。我们来看看Element的表组件是如何被功能组件封装的。

  效果图:

  

1、所封装的table组件:

  模板

  差异

  El-table:data= CFG . data style= width:100% v-on= CFG . on v-bind= attrs v-loading= loading

  El-table-column v-if= CFG . has checkbox v-bind= selection attrs type= selection width= 55 label= xx /

  El-table-column v-for= n in CFG . headers :prop= n . prop :label= n . label :key= n . prop v-bind= {.columnAttrs,n.attrs}

  模板插槽范围=“{ row }”

  slot:name= n . prop :row= row cell:config= n :data= row //slot

  /模板

  /El-表格-列

  /el-table

  el分页

  class=分页

  v-if=showPage

  layout=总计,大小,上一页,分页,下一页,跳转

  :page-size=[2,3,6,11]

  :page-size=page.size

  :total=page.total

  :current-page=page.page

  @current-change=loadPage

  @size-change=sizeChange

  /

  /div

  /模板

  脚本

  从导入单元格每个单元格

  导出默认值{

  组件:{

  细胞,

  },

  道具:{

  配置:对象,

  },

  data(){

  返回{

  装:真的,

  columnAttrs: {

  对齐:"左",

  可调整大小:假的,

  },

  cfg: {

  on: this.getTableEvents(),

  属性:{

  边框:真的,

  条纹:真的,

  },

  数据:[],

  .this.config,

  },

  页面:{

  size: this.config.size 10,

  第一页,

  总计:0,

  },

  已检查:[],

  }

  },

  已创建(){

  这个。load();

  },

  计算值:{

  selectionAttrs(){

  让{可选择,保留选择=假}=这个。config { },obj={ };

  //复选框是否可以被选中

  if(selectable== function 可选类型){

  Object.assign(obj,{

  可选,

  })

  }

  //保留选择仅对类型=选择的列有效,类型为布尔型,为真实的则会在数据更新之后保留之前选中的数据(需指定行键)

  if(reserveSelection){

  Object.assign(obj,{

  保留选择:保留选择,

  })

  }

  返回目标文件

  },

  attrs(){

  let {config: {spanMethod,rowKey},CFG:{ attrs } }=this;

  //合并单元格-跨度方法是父组件传过来的合并单元格的方法,请参照元素合并单元格

  if(span method type of span method== function ){

  对象.分配(属性,{

   span-method: spanMethod,

  })

  }

  //表格跨页选中,需要设置行键和储备选择,储备选择只能且必须设置在类型为选择的埃尔-表格-列上

  if(行键的行键类型== function ){

  对象.分配(属性,{

   row-key: rowKey,

  })

  }

  返回属性;

  },

  showPage(){

  设{size,total }=this.page

  返回大小合计;

  },

  },

  方法:{

  getTableEvents(){

  设{ has checkbox=false }=this。配置 { },事件={},_ this=this

  if(hasCheckbox){

  //绑定事件

  对象.分配(事件,{

  选择-更改{

  _这个。选中=v;

  },

  });

  }

  返回事件;

  },

  //获取勾选的行

  getChecked(){

  返回这个,检查过了

  },

  //请求数据

  load(p={}){

  设{ size,page }=this.page,{ load data=()=promise。resolve({ })}=这个。配置;

  this.loading=true

  //这里加载数据的参数在初始化时只有分页所需的页,面,张,版和尺寸,至于接口需要的其他参数,是在父组件的加载数据中传递

  loadData({.p,page,size}).然后(({data,total})={

  这个。CFG。数据=数据;

  这个。页面。page=页面;

  这个。页面。总计=合计;

  this.loading=false

  });

  },

  加载页面(索引){

  this.page.page=index

  这个。load();

  },

  尺寸变化(大小){

  this.page.size=size

  这个。load();

  },

  //一般在点击查询按钮或局部刷新表格列表时,可调用此方法,如果不传参数,则默认从第一页开始

  reload(p={}){

  this.page.page=1

  这个。载荷(p);

  },

  },

  }

  /脚本

  

2、汇总表格每一列的cell.js:

  将*作为组件从导入./组件;

  让empty=-

  导出默认值{

  道具:{

  配置:对象,

  数据:对象,

  },

  功能性:真的,

  render: (h,c)={

  设{props: {config={},data={ } }=c,{prop,type=Default}=config,value=data[prop] config.value,isEmpty=value=== value===undefined;

  return isEmpty?h(组件。默认,{props: {value:empty } }):h(Components[type],{ props:{ value,empty,data,config } });

  }

  }

  

3、本次封装将每一列的渲染单独分开成多个vue组件,最后再合并在一个components.js文件中一起进行匹配。

  1)整合文件components.js:

  "导入日期自"。/Date ;

  从导入默认值./默认;

  从导入货币./币;

  从""导入枚举./Enum ;

  从导入操作./Action ;

  从导入链接./Link ;

  从导入格式./格式;

  从导入Popover ./Popover ;

  导出{

  默认,

  日期,

  货币,

  枚举,

  行动,

  链接,

  格式,

  Popover,

  }

  2)日期列Date.vue

  模板功能

  span { { props。值日期(道具。格式)} }/span

  /模板

  3)默认列Default.vue

  模板功能

  span{{props.value}}/span

  /模板

  4)金额千分位列货币。某视频剪辑软件

  模板功能

  span { { props。价值货币} }/span

  /模板

  5)映射列Enum.js

  设mapid和key=list=list。减少((c,i)=({.c,[i.key]: i}),{ });

  让状态={

  订单:mapIdAndKey([

  {

  id:"草稿",

  密钥:"已创建",

  瓦尔: 未提交,

  },

  {

  id:"待定",

  关键字:"批准中",

  瓦尔: 审批中,

  },

  {

  id:"拒绝",

  按键:"拒绝",

  瓦尔: 审批驳回,

  },

  {

  id:"拒绝",

  关键:"拒绝",

  瓦尔: 审批拒绝,

  },

  {

  id:"签名",

  关键字:合同签署,

  瓦尔: 合同签署中,

  },

  {

  id:"签名完成",

  关键字:合同_已签署,

  瓦尔: 合同签署成功,

  },

  {

  id:“借出完成”,

  关键:"租借",

  瓦尔: 放款成功,

  },

  {

  id:“借出拒绝”,

  关键字:贷款_拒绝,

  瓦尔: 放款驳回,

  },

  {

  id:"取消",

  按键:"取消",

  瓦尔: 取消成功,

  },

  {

  id:"入端",

  关键字: IN_LOAN ,

  瓦尔: 放款审批中,

  },

  ]),

  监视器:mapIdAndKey([

  {

  密钥:"00",

  瓦尔: 未监控,

  },

  {

  密钥:"01",

  瓦尔: 监控中,

  },

  ]),

  }

  导出默认值{

  功能性:真的,

  render(h,{props: {value,Enum,empty},parent}){

  let enums=Object.assign({},STATUS,parent .$store.getters.dictionary),

  {name= ,getVal=(values,v)=values[v]}=Enum,_value=getVal(enums[name],value);

  if( _value===未定义)返回h(span ,_value===未定义?空:_ value);

  设{id,val }=_ value

  返回h(span ,{staticClass: id},[h(span ,val)]);

  }

  }

  6)操作列Action.js

  const get citons=(h,value,data)={

  let result=value.filter(n={

  设{ filter=()=true }=n;

  返回filter.call(n,data);

  });

  return result.map(a=h(span ,{class: btn ,on: {click: ()=a.click(data)},key: a.prop},a.label))

  }

  导出默认值{

  功能性:真的,

  render: (h,{props: {value,data}})={

  返回h(div ,{class: action},getAcitons(h,value,data))

  },

  }

  7)带有可跳转链接的列Link.vue

  模板

  router-link :to={ path,query:params } { { value } }/router-link

  /模板

  脚本

  导出默认值{

  道具:{

  数据:对象,

  值:字符串,

  查询:{

  类型:功能,

  默认值:()={

  返回{

  路径: ,

  有效负载:{}

  }

  }

  },

  },

  计算值:{

  //路由小路

  路径(){

  const { path }=this。查询(这个。数据)

  返回路径

  },

  params(){

  const { payload }=this。查询(这个。数据)

  返回有效载荷

  },

  },

  }

  /脚本

  8)自定义想要展示的数据格式Format.vue

  模板功能

  div v-html=道具。格式(道具。value,props.data) /

  /模板

  9)当内容过多需要省略并在鼠标移入后弹出一个提示窗显示全部内容的列Popover.vue

  模板功能

  埃尔-波普沃

  位置=顶部开始

  宽度=300

  触发器=悬停

  波普,波普

  :content=props.value

  span slot= reference class= popover-txt { props。value } }/span

  /el-popover

  /模板

  样式范围。popover-txt{

  溢出:隐藏;

  文本溢出:省略号;

  空白:nowrap

  显示:块;

  光标:指针;

  }

  /风格

  从以上代码中可以看出,我既使用了基于提出函数类型的函数式组件也使用了基于模板的函数式组件,主要是为了在封装时的方便,毕竟使用提出这个最接近编译器的函数还是有点麻烦的,不如基于模板的函数式组件来的方便。

  

4、使用封装后的表格table组件

  1)不使用插槽:

  模板

  div style= margin:20px;

  El-button type= primary v-if= excel导出 @ click=下载获取勾选的表格数据/el-button

  table:config= config ref= table /

  /div

  /模板

  脚本

  从" @/组件/表格"导入表格

  导出默认值{

  组件:{

  表,

  },

  data() {

  返回{

  配置:{

  标题:[

  {道具: 合同代码,标签:业务编号,属性:{width: 200,align: center}},

  {prop: payeeAcctName ,标签: 收款账户名,type: Link ,query: row=this.query(row),attrs: {width: 260,align: right}},

  {prop: tradeAmt ,标签: 付款金额,键入:货币 },

  {属性: 状态,标签:操作状态,类型: Enum ,Enum: {name: order}},

  {属性: 统计,标签:预警统计,键入: Format ,format: val=this.format(val)},//自定义展示自己想要的数据格式

  {属性: 原因,标签:原因,键入: Popover},

  {道具: 支付时间,标签:付款时间,类型:日期,格式: yyyy-MM-dd hh:mm:ss},//不设置格式的话,日期格式默认为年/月/日

  {prop:监视器状态,标签: 当前监控状态,类型: Enum ,Enum: {name: monitor}},

  ].concat(this.getActions()),

  //通过接口获取列表数据-这里的参数p就是子组件传过来的包含分页的参数

  加载数据:p=请求。张贴(权限/列表,{.this.setParams(),p}),

  hasCheckbox: true,

  可选择的,

  reserveSelection: false,

  rowKey: row=row.id,

  },

  状态:"01",

  权限:[处理,通过,拒绝,重新申请,导出]

  }

  },

  计算值:{

  句柄(){

  返回这个。许可。some(n=n== handle );

  },

  pass() {

  归还这个。许可。some(n=n== pass );

  },

  拒绝(){

  返回这个。许可。一些(n=n==拒绝);

  },

  拒绝(){

  归还这个。许可。一些(n=n==拒绝);

  },

  excelExport(){

  返回这个。许可。一些(n=n==处理)这个。许可。一些(n=n== export );

  },

  },

  方法:{

  getActions(){

  return {prop: action ,name:操作,类型:"操作",值:[

  {标签: 查看,点击:data={console.log(data)}},

  {标签: 办理,点击:data={},filter:({ status })=status== CREATED this。句柄},

  {标签: 通过,点击:data={},filter:({ status })=status==传递此。通过},

  {标签: 驳回,点击:data={},filter:({ status })=status== REJECT this。拒绝},

  {标签: 拒绝,点击:data={},filter:({ status })=status== CREATED this。拒绝},

  ]}

  },

  setParams(){

  返回{

  名称: 测试,

  状态:"01",

  类型:"已创建",

  }

  },

  查询(行){

  返回{

  路径:"/otherElTable ",//路由小路

  有效负载:{

  id: row.id,

  类型:"链接"

  }

  }

  },

  格式(瓦尔){

  设str=

  val.forEach(t={

  str=" span style=" margin-right:5px .t . total /span ;

  })

  返回字符串;

  },

  可选({状态}){

  退货状态==拒绝?假:真

  },

  下载(){

  console.log(这个. refs.table.getChecked())

  },

  },

  };

  /脚本

  风格。动作跨度{右边距:10px颜色:# 359C67光标:指针;}

  /风格

  2)使用插槽:

  表:config=config ref=table

  template #statistic={row}

  div v-html=循环(行。统计)/div

  /模板

  template #payeeAcctName={row}

  {{row.payeeAcctName}}

  /模板

  模板#tradeAmt={row}

  {{row.tradeAmt currency}}

  /模板

  模板v型槽:原因="{ row } "

  模板v-if=!row.reason-/template

  埃尔-波普沃

  五-否则

  位置=顶部开始

  宽度=300

  触发器=悬停

  波普,波普

  :content=row.reason

  span slot= reference class= popover-txt { row。原因} }/span

  /el-popover

  /模板

  模板#payTime={row}

  { { row。paytime date( yyyy-MM-DD hh:MM:ss )} }

  /模板

  模板# customize="{ row } "

  {{customize(row.customize)}}

  /模板

  template #opt={row}

  div class=动作

  跨度查看/span

  span v-if=row.status==已创建"句柄"办理/span

  span v-if= row。状态==通过通过通过/span

  span v-if=row.status==REJECT 拒绝驳回/span

  span v-if=row.status==拒绝拒绝拒绝/span

  /div

  /模板

  /表格

  脚本

  从" @/组件/表格"导入表格

  导出默认值{

  组件:{

  表,

  },

  data(){

  返回{

  配置:{

  标题:[

  {prop: contractCode ,label:业务编号,attrs: {width: 200,align: center}},

  {prop: payeeAcctName ,label:收款账户名称,attrs: {width: 260,align: right}},

  {prop: tradeAmt ,label:付款金额 },

  {属性:状态,标签:操作状态,类型:枚举,枚举:{名称:订单 }},

  {prop:统计,label:警报统计 },

  {道具:付款时间,标签:付款时间 },

  {道具:原因,标签:原因 },

  {prop: monitorStatus ,label:当前监视状态,type: enum ,enum: {name: monitor}},

  {prop: customize ,label:自定义演示,type: format ,format:val=this . customize(val)},

  {prop: opt ,label: operation},

  ],

  loadData: ()=Promise.resolve({

  数据:[

  {ID: 1,合同代码:,PayeeAcctname:中国银行上海分行,TradeAMT: 503869.265 ,状态: 00 ,支付时间:1593585652530,

  统计数据:[

  {级别:3,总数:5},

  {级别:2,总数:7},

  {级别:1,总计:20},

  {级别:0,总计:0}

  ],

  自定义:[中国,上海,浦东新区]

  },

  {ID: 2,合同代码: GLP-YG-B3-1111 ,收款人姓名:中国邮政上海分公司,交易金额: 78956.85 ,状态:已创建,付款时间:1593416718317,

  原因:Popover的属性和Tooltip很像,都是基于Vue-popper开发的,所以对于重复的属性,请参考Tooltip的文档,不做详细解释。’,

  },

  {ID: 3,合同代码: HT1592985730310 ,收款人姓名:招商银行上海分行,交易金额: 963587123 ,状态:通过,付款时间:1593420950772,监控状态: 01},

  {id: 4,合同代码: pi239 ,付款人姓名:广州物流有限公司,交易金额: 875123966 ,状态:拒绝,付款时间:1593496609363},

  {ID: 5,合同代码: 0701001 ,收款人姓名:中国建设银行上海分行,交易金额: 125879125 ,状态:拒绝,付款时间:1593585489177},

  ],

  }),

  },

  权限:[处理,通过,拒绝,重新申请,导出],

  }

  },

  计算值:{

  句柄(){

  返回this . permission . some(n=n== handle );

  },

  pass() {

  return this . permission . some(n=n== pass );

  },

  拒绝(){

  返回this . permission . some(n=n== reject );

  },

  拒绝(){

  return this . permission . some(n=n==拒绝);

  },

  excelExport(){

  返回this . permission . some(n=n== handle )this . permission . some(n=n== export );

  },

  },

  方法:{

  查询(行){

  返回{

  路径:“/otherElTable”,//,//路由路径

  有效负载:{

  id: row.id,

  类型:“链接”

  }

  }

  },

  循环(val){

  如果(!val)返回-

  设str=“”;

  val.forEach(t={

  str=" span style=" margin-right:5px。 t . total /span ;

  })

  返回字符串;

  },

  自定义(v){

  回v?v[0] v[1] v[2] : -

  }

  }

  }

  /脚本

  在两种不同的使用模式下,第一种不基于槽位,第二种基于槽位。通过比较这两种方式,可以看出在第二种方式中,所有使用插槽的列都不再定义headers数组中的type字段。即使定义了类型,也不起作用。起作用的是插槽,concat不再用于拼接操作列。操作栏也是用槽来渲染的,但是如果很多栏都是用槽来实现的,利己主义者感觉页面看起来不那么整齐。

  顺便说一句,由于我们已经封装了大多数场景的实现,人们没有必要通过使用插槽来做任何不必要的事情。尽量保持页面整洁。如果你真的认为在headers数组之后连接一个操作列有点笨拙,那么你只需要以slot的形式实现操作列。这篇博客中提到的插槽实现只是为了给你多一个选择。

  最后,关于千量的实现和时间戳的格式化,这里不需要粘贴代码,自己就可以实现。

  最近想到了封装的table组件,想知道在原有封装的基础上是否还有其他的实现方法。比如我不想在原来定义的headers数组后面串接一个操作列,或者表格的某一列的数据处理方法没有包含在我们之前封装的那些方法中,或者作为一个第一次使用这个表格组件的前端开发人员,我不习惯你的编写风格,那么我可以在你封装的基础上写一些处理方法吗?答案是肯定的。当然,我们说既然组件已经封装好了,大家就要按照一个套路来,省时省力。为什么不做呢?但是,如果我们抱着学习的态度,以比别人多一技之长为出发点,多学习,多思考,多做事,总是有利于进步的。只是在实际开发过程中,要尽量选择一种封装方式,然后要共同遵守这个协议。

  其实说了这么多废话,这个改动并不多,只是在原包的基础上加了槽而已。看完这篇博客,你一定记得在我的封装代码中有一个处理每一列数据的特殊代码:Cell :config=n :data=row/

  对,就是这样。关于这个我不想多说,上面已经介绍过了。这次主要用槽。

  这个slot API,由VUE官网和各种网上文章介绍,已经解释清楚了。大致可以分为默认槽(有人称之为匿名槽)、命名槽和作用域槽。关于它们的介绍,可以参考官网或者网上的各种文章。这种变化主要使用命名槽和作用域槽。命名槽,顾名思义,就是有名字的槽。这个包中使用的插槽的名称来自表中每一列的prop。作用域槽在这个包中的作用主要是通过子组件的槽把值传递给父组件。它的实现形式有点类似于vue父组件传递值给子组件,只是两个组件接收值的方式不同。简而言之,这个改变实现起来非常简单,就是在Cell :config=n :data=row/外面包装一层命名槽就够了。slot:name= n . prop :row= row cell:config= n :data= row //slot

  就酱。

  接下来,我们可以回答上面的问题。看答案:

  表:config=config ref=table

  模板#payTime={row}

  { { row . paytime date( yyyy-MM-DD hh:MM:ss )} }

  /模板

  模板# customize=“{ row }”

  {{customize(row.customize)}}

  /模板

  template #opt={row}

  div class=动作

  Span视图/span

  Span-if= row.status==已创建 handle 句柄/span

  Span-if= row.status== pass 通过/span

  Span-if= row.status== reject 拒绝/span

  Span-if= row.status== reject 拒绝/span

  /div

  /模板

  /表格

  以上是针对一些特殊情况,你不想用我最初包装的方法来实现。然后,我会为您提供另一项“特殊服务”。请注意,如果您自己使用插槽来呈现数据,那么在headers数组中,您需要提供表格标题的呈现,而不添加类型字段。

  例如,当我们第一次呈现表的日期列时,我们这样写:{prop: payTime ,label: payment time ,type: date ,format: yyyy-mm-DD HH: mm: ss}

  那么如果你自己用槽来渲染数据,这里的写法就会变成这样:{prop: payTime ,label: payment time}

  同样,在我们定义操作列之前,在headers数组之后连接一个数组。如果您自己使用slots来呈现数据,则不需要连接另一个数组,但是可以向headers数组添加另一个{prop: opt ,label: operation}。

  其实这个改动就是在原来的基础上重新包装一层槽。对于那些不需要我们自己处理数据,只需要直接显示接口返回的数据的情况,我们在使用这个封装的table组件时不需要做任何特殊的处理,也不需要像上面使用的slot那样定义,只要仍然像以前一样在headers数组中正常定义即可。由于插槽的原因,您没有定义命名插槽或默认插槽,所以插槽中显示的是单元格:config=n :data=row/

  我明白了。

  对了,你说我不想用槽来处理日期和千金额的列,你还是可以按照我上面介绍的槽的原理在headers数组中定义。没关系:

  {prop: tradeAmt ,标签:支付金额,类型:货币 },

  {属性:支付时间,标签:支付时间,类型:日期 },

  写到这里,其实我想说的是,即使加了槽,对之前的使用方式基本没有影响。你可以随心所欲的使用,但我只是给你提供了更多的选择。

  如果你真的不想用槽,想保持页面的整洁,在Cell:config= n :data= row /这段代码外面包一层槽也没关系,用我上面的介绍就行了。

  绍的第一种使用方法就可以了。

  作者:小坏

  出处:http://tnnyang.cnblogs.com

  以上就是如何封装Vue Element的table表格组件的详细内容,更多关于封装Vue Element的table表格组件的资料请关注我们其它相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: