圆月山庄资源网 Design By www.vgjia.com

前言

在公司实习使用vue+element-ui框架进行前端开发,使用表格el-table较为多,有些业务逻辑比较相似,有些地方使用的重复性高,如果多个页面使用相同的功能,就要多次重复写逻辑上差不多的代码,所以打算对表格这个组件进行封装,将相同的代码和逻辑封装在一起,把不同的业务逻辑抽离出来。话不多说,下面就来实现一下吧。

一、原生el-tbale代码——简单の封装

这里直接引用官方的基础使用模板,直接抄过来("htmlcode">

 <template>
  <el-table
   :data="tableData"
   style="width: 100%">
   <el-table-column
    prop="date"
    label="日期"
    width="180">
   </el-table-column>
   <el-table-column
    prop="name"
    label="姓名"
    width="180">
   </el-table-column>
   <el-table-column
    prop="address"
    label="地址">
   </el-table-column>
  </el-table>
 </template>

 <script>
  export default {
   data() {
    return {
     tableData: [{
      date: '2016-05-02',
      name: '王小虎',
      address: '上海市普陀区金沙江路 1518 弄'
     }, {
      date: '2016-05-04',
      name: '王小虎',
      address: '上海市普陀区金沙江路 1517 弄'
     }, {
      date: '2016-05-01',
      name: '王小虎',
      address: '上海市普陀区金沙江路 1519 弄'
     }, {
      date: '2016-05-03',
      name: '王小虎',
      address: '上海市普陀区金沙江路 1516 弄'
     }]
    }
   }
  }
 </script>

表格の样子

element el-table表格的二次封装实现(附表格高度自适应)

封装后

<template>
 <el-table :data="tableData" style="width: 100%">
  <template v-for="(item, key) in header">
   <el-table-column
    :key="key"
    :prop="itm.prop "
    :label="itm.label "
    :width="itm.width "
   >
   </el-table-column>
  </template>
 </el-table>
</template>

<script>
export default {
 data() {
  return {
   header: [
    { prop: "date", label: "日期", width: "180" },
    { prop: "name", label: "姓名", width: "180" },
    { prop: "address", label: "地址" }
   ],
   tableData: [
    {
     date: "2016-05-02",
     name: "王小虎",
     address: "上海市普陀区金沙江路 1518 弄"
    },
    {
     date: "2016-05-04",
     name: "王小虎",
     address: "上海市普陀区金沙江路 1517 弄"
    },
    {
     date: "2016-05-01",
     name: "王小虎",
     address: "上海市普陀区金沙江路 1519 弄"
    },
    {
     date: "2016-05-03",
     name: "王小虎",
     address: "上海市普陀区金沙江路 1516 弄"
    }
   ]
  };
 }
};
</script>

现在数据还比较少,可能看不出封装组件封装的优势,但是相对于之前代码,这里逻辑上看起来更加清晰,而且修改列的时候直接改动data中的header数据即可,不用再去html代码中去“开刀”( ̄▽ ̄)/。上面是最最最简单的封装了,严格来说只是简单的抽离了一下代码中的数据结构,在正常的业务中肯定不止这么简单的封装,接下来才是重点─━ _ ─━",那就是render函数,关于render可以参考一下这篇博客,使用render函数就可以轻而易举的将这部分逻辑代码抽离出来了。

el-table真正の二次封装

二次封装源代码

<template>
 <el-table
  empty-text="暂无数据"
  ref="table"
  :data="tableList"
  border
  stripe
  fit
  highlight-current-row
  :height="inTableHeight"
  @selection-change="selectionChange"
  @row-click="rowClick"
 >
  <!-- 选择框 -->
  <el-table-column
   v-if="select"
   type="selection"
   fixed="left"
   width="55"
   align="center"
  />
  <template v-for="(itm, idx) in header">
   <!-- 特殊处理列 -->
   <el-table-column
    v-if="itm.render"
    :key="idx"
    :prop="itm.prop "
    :label="itm.label "
    :width="itm.width "
    :sortable="itm.sortable "
    :align="itm.align "
    :fixed="itm.fixed "
    :show-overflow-tooltip="itm.tooltip"
    min-width="50"
   >
    <template slot-scope="scope">
     <ex-slot
      :render="itm.render"
      :row="scope.row"
      :index="scope.$index"
      :column="itm"
     />
    </template>
   </el-table-column>
   <!-- 正常列 -->
   <el-table-column
    v-else
    :key="idx"
    :prop="itm.prop "
    :label="itm.label "
    :width="itm.width "
    :sortable="itm.sortable "
    :align="itm.align "
    :fixed="itm.fixed "
    :formatter="itm.formatter"
    :show-overflow-tooltip="itm.tooltip"
    min-width="50"
   />
  </template>
 </el-table>
</template>

<script>
// 自定义内容的组件
var exSlot = {
 functional: true,
 props: {
  row: Object,
  render: Function,
  index: Number,
  column: {
   type: Object,
   default: null
  }
 },
 render: (h, context) => {
  const params = {
   row: context.props.row,
   index: context.props.index
  };
  if (context.props.column) params.column = context.props.column;
  return context.props.render(h, params);
 }
};

export default {
 components: { exSlot },
 props: {
  tableList: {
   type: Array,
   default: () => []
  },
  header: {
   type: Array,
   default: () => []
  },
  select: {
   type: Boolean,
   default: () => false
  },
  height: {
   type: [Number, String, Function],
   default: () => null
  }
 },
 data() {
  return {
   inTableHeight: null
  };
 },
 created() {
  //该阶段可以接收父组件的传递参数
  this.inTableHeight = this.height;
 },
 mounted() {
  this.$nextTick(() => {
   //表格高度自适应浏览器大小
   this.changeTableHight();
   if (!this.height) {
    window.onresize = () => {
     this.changeTableHight();
    };
   }
  });
 },
 destroyed() {
  //高度自适应事件注销
  window.onresize = null;
 },
 watch: {
  /**
   * 数据变化后 高度自适应
   */
  tableList() {
   this.$nextTick(() => {
    this.changeTableHight();
   });
  }
 },
 methods: {
  /**
   * 选择框选择后更改,事件分发
   */
  selectionChange(selection) {
   this.$emit("selection-change", selection);
  },
  /**
   * 点击事件
   */
  rowClick(row, column, event) {
   this.$emit("row-click", row, column, event);
  },
  /**
   * 高度自适应
   * 当表格展示空间小于460按460px展示,大于的时候高度填充
   */
  changeTableHight() {
   if (this.height) {
    //如果有传进来高度就取消自适应
    this.inTableHeight = this.height;
    this.$refs.table.doLayout();
    return;
   }
   let tableHeight = window.innerHeight || document.body.clientHeight;
   //高度设置
   let disTop = this.$refs.table.$el;
   //如果表格上方有元素则减去这些高度适应窗口,66是底下留白部分
   tableHeight -= disTop.offsetTop + 66;
   if (disTop.offsetParent) tableHeight -= disTop.offsetParent.offsetTop;
   this.inTableHeight = tableHeight < 460 "htmlcode">
<template>
 <div class="hello">
  <xd-table :table-list="tableData" :header="header" height="300"></xd-table>
 </div>
</template>

<script>
export default {
 name: "HelloWorld",
 data() {
  return {
   header: [
    { prop: "w", label: "w" },
    { prop: "x", label: "x",
     formatter: (row) => {
      return row.x.toFixed(3);
     },
    },
    { prop: "d", label: "d",
     formatter: (row) => {
      return row.d.toFixed(2);
     },
    },
    {
     label: "操作",
     render: (h, data) => {
      return (
       <el-button
        type="primary"
        onClick={() => {
         this.handleClick(data.row);
        }}
       >
        点我获取行数据
       </el-button>
      );
     },
    },
   ],
   tableData: [
    { w: 1, x: 99.25123, d: 0.23892 },
    { w: 1, x: 255.6666, d: 0.99134 },
   ],
  };
 },
 methods: {
  handleClick(row) {
   console.log(row);
  },
 },
};
</script>

引用组件之前一定要记得先注册,这里我只使用了几个属性,其他属性没有使用,因为是demo,主要还是展示render内嵌代码的方法,还有一个就是官方formatter方法的使用。
有一个需要注意点就是render内我使用了JSX模板语法这里需要在VUE项目中单独去配置一下JSX语法,如果不想使用JSX,直接写也可以,因为不使用JSX语法写出来的内嵌模板代码比较难读所以我就不展示了,个人建议还是使用JSX语法,虽然和原生vue有些地方使用方法不太一样。

效果截图

element el-table表格的二次封装实现(附表格高度自适应)

结语

这次封装vue组件,花了我将近半个月的时间,从刚开始的接触到发现bug然后去修改,来来回回终于精简封装出现在这个二次封装的组件,可能对于熟悉vue和element的人来说这个封装其实很简单,但是对于我来说这个算是我这段实习期封装的比较好的一个组件了吧,当然除了封装这个组件还有别的事在做,不可能放着公司的活不干(哈哈哈哈︿( ̄︶ ̄)︿),总之在封装组件过程中学习到了不少东西,也算是一个大大的进步,于是来写一篇博客来记录一下

标签:
element,el-table二次封装,element,el-table,封装

圆月山庄资源网 Design By www.vgjia.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
圆月山庄资源网 Design By www.vgjia.com

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。