Vue技巧Element Table二次封装实战示例

目录
  • 前言
  • 思考
  • 实践
  • filterPane.vue
    • 明确目标
    • 传入数据结构整理
      • timeSelect
      • elinput
      • elselect
    • 开始封装
  • tablePane.vue
    • 明确目标
    • 传入数据结构整理
      • tool
      • cols
      • pageData
      • operation
    • tablePane.vue配置项Cols详解
    • 开始封装
  • 实战
  • 结尾

前言

由于重构后台管理项目中有好多表格页面, 举个栗子

这表格看着还挺好看,写起来叫人直呼XX,多动脑子少掉发,少走弯路多省鞋。

写了一个后感觉太麻烦了,于是我奋笔疾书,利用Vue+Element Table重新封装出了一套表格组件

3分钟就可以实现一个表格页面的骚操作,你值得拥有

思考

看了表格咱们简单的把它们划分了下功能区

  • 最先入场的选手是最上方一排整整齐齐有点严肃的搜索功能区
  • 其次入场的是略带个性的表格功能区
  • 然后入场的是全能综合性型选手表格内容区域
  • 最后入场的是有着长腿带着长队的分页组件区域

诶,让我们思考下最复杂的地方在哪里?

下面我用个图来标注下咱们接下来需要拿下的高地

总的来说表格内容这一块最不可控,他可能有多选、序号、图片、状态、时间、操作列......

实践

咱们把搜索层写成一个组件filterPane.vue

把表格分成一个组件tablePane.vue

表格组件tablePane.vue包括功能区、表格内容区、分页

filterPane.vue

明确目标

搜索层一般包括日期选择器、输入框、select下拉选择器等+搜索功能、重置功能

传入数据结构整理

// 搜索栏组件
 filterData:{
   timeSelect:true,    //是否显示日期控件
   elinput:[
     {
       name:'姓名',    //提示语
       key:'userName',  //字段名
       width:100        //宽度
     }
   ],
   elselect:[
     {
       name:'部门',
       key:'department',
       width:100
       option:[{
         key:1,
         value:'技术部'
       }]
     }
   ]
 }

timeSelect

  • 类型 Boolean 是否显示时间选择器

elinput

  • 类型 Array 输入框选项,子对象内

name为输入框的placeholder

key为字段名

elselect

  • 类型 Array select下拉框选项,子对象内

name为输入框的placeholder

key为字段名

option为select下拉选项

开始封装

<template>
  <div>
    <div class="filter-container">
      <el-date-picker
        v-if="filterData.timeSelect"
        v-model="dateRange"
        style="width: 300px"
        type="daterange"
        start-placeholder="开始日期"
        end-placeholder="结束日期"
        :default-time="['', '']"
        :picker-options="pickerOptions"
        class="filter-item"
      />
      <template v-if="filterData.elinput">
        <el-input
          v-for="(item,index) in filterData.elinput"
          :key="index"
          v-model="listQuery[item.key]"
          :placeholder="item.name"
          :style="{'width':item.width?item.width+'px':'200px'}"
          class="filter-item"
        />
      </template>
      <template v-if="filterData.elselect">
        <el-select
          v-for="(item,index) in filterData.elselect"
          :key="index"
          v-model="listQuery[item.key]"
          :placeholder="item.name"
          clearable
          :style="{'width':item.width?item.width+'px':'90px'}"
          class="filter-item"
        >
          <el-option
            v-for="i in item.option"
            :key="i.key"
            :label="i.value"
            :value="i.key"
          />
        </el-select>
      </template>
      <div class="btn">
        <el-button class="filter-item" type="primary" @click="handleSearch">
          搜索
        </el-button>
        <el-button class="filter-item" type="warning" @click="handleRest">
          重置
        </el-button>
      </div>
    </div>
  </div>
</template>
<script>
// 搜索栏组件
// filterData:{
//   timeSelect:true,
//   elinput:[
//     {
//       name:'姓名',
//       key:'userName'
//     }
//   ],
//   elselect:[
//     {
//       name:'部门',
//       key:'department'
//       option:[{
//         key:1,
//         value:'技术部'
//       }]
//     }
//   ]
// }
export default {
  props: {
    // eslint-disable-next-line vue/require-default-prop
    filterData: {
      type: Object
    }
  },
  data() {
    return {
      pickerOptions: {
        disabledDate(time) {
          return time.getTime() > Date.now()
        }
      },
      dateRange: ['', ''],
      listQuery: {}
    }
  },
  watch: {
    'filterData'(val) {
      console.log(val)
      if (val.elinput.length > 0) {
        val.elinput.map(item => {
          this.listQuery[item.key] = ''
        })
      }
      if (val.elselect.length > 0) {
        val.elinput.map(item => {
          this.listQuery[item.key] = ''
        })
      }
    },
    //缓存进页面想清空可用
    'filterData.rest': {
      handler: function(val) {
        if (val) {
          this.handleRest()
        }
      },
      deep: true
    }
  },
  methods: {
    handleSearch() {
      console.log('搜索成功', this.listQuery)
      const data = this.$global.deepClone(this.listQuery)
      if (this.dateRange && this.dateRange[0] !== '') {
        const startTime = this.$moment(this.dateRange[0]).format('YYYY-MM-DD') + ' 00:00:00'
        const endTime = this.$moment(this.dateRange[1]).format('YYYY-MM-DD') + ' 23:59:59'
        data.beginDate = startTime
        data.endDate = endTime
      }
      Object.keys(data).forEach(function(key) {
        if (data[key] === '') {
          delete data[key]
        }
      })
      this.$emit('filterMsg', data)
    },
    handleRest() {
      const data = this.$global.deepClone(this.listQuery)
      Object.keys(data).forEach(function(key) {
        data[key] = ''
      })
      this.listQuery = data
      this.dateRange = ['', '']
      console.log('重置成功', this.listQuery)
    }
  }
}
</script>
<style  scoped lang='scss'>
.filter-item{
  margin-left: 10px;
  display: inline-block;
}
.filter-container .filter-item:nth-of-type(1){
  margin-left: 0px;
}
.btn{
  display: inline-block;
  margin-left: 10px;
}
</style>

tablePane.vue

明确目标

实现表格功能行、实现表格基本功能、实现分页功能

传入数据结构整理

  dataSource: {
          tool:[
            {
              name: '新增用户', //按钮名称
              key: 1,  // 唯一标识符
              permission: 2010106, // 权限点
              type: '',  // 使用element自带按钮类型
              bgColor: '#67c23a', // 自定义背景色
              handleClick: this.handleAdd //自定义事件
            },
          ]
         data: [], // 表格数据
         cols: [], // 表格的列数据
         isSelection: false, // 表格有多选时设置
         selectable: function(val) {//禁用部分行多选
          if (val.isVideoStatus === 1) {
            return false
          } else {
            return true
          }
        },
         handleSelectionChange:(val)=>{} //点击行选中多选返回选中数组
         isOperation: true, // 表格有操作列时设置
         isIndex: true, // 列表序号
         loading: true, // loading
         pageData: {
          total: 0, // 总条数
          pageSize: 10, // 每页数量
          pageNum: 1 // 页码
         }
         operation: {
           // 表格有操作列时设置
           label: '操作', // 列名
           width: '350', // 根据实际情况给宽度
           data: [
             {
               label: '冻结', // 操作名称
               permission:'' //权限点
               type: 'info', //按钮类型
               handleRow: function(){} // 自定义事件
             },
           ]
         }
       },

tool

  • 类型 Array
  • 默认值 [ ]

配置表格工具列

 dataSource: {
         tool:[
           {
             name: '新增用户', //按钮名称
             key: 1,  // 唯一标识符
             permission: 2010106, // 权限点
             type: '',  // 使用element自带按钮类型
             bgColor: '#67c23a', // 自定义背景色
             handleClick: this.handleAdd //自定义事件
           },
         ]
  }

cols

  • 类型 Array
  • 默认值 [ ] 配置表头
 dataSource: {
         cols:[
            {
               label: '标题',                       //列名
               prop: 'belongUserId',                //字段名称
               width: 100                           //列宽度
            },
            {
               label: '副标题(季)',
               prop: 'subtitle',
               isCodeTableFormatter: function(val) {//过滤器
                 if (val.subtitle === 0) {
                   return '无'
                 } else {
                   return val.subtitle
                 }
               },
               width: 100
            },
             {
               label: '创建时间',
               prop: 'createTime',
               isCodeTableFormatter: function(val) {//时间过滤器
                 return timeFormat(val.createTime)
               },
               width: 150
             }
         ]
  }

pageData

  • 类型 Object
  • 默认值 { } 配置分页
 dataSource: {
        pageData: {
         total: 0, // 总条数
         pageSize: 10, // 每页数量
         pageNum: 1, // 页码
         pageSize:[5,10,15,20]// 每页数量
        }
 }

operation

  • 类型 Object
  • 默认值 { } 配置操作列
dataSource: {
       operation: {
         // 表格有操作列时设置
         label: '操作', // 列名
         width: '350', // 根据实际情况给宽度
         data: [
           {
             label: '修改', // 操作名称
             permission:'1001' //权限点
             type: 'info', //按钮类型icon为图表类型
             handleRow: function(){} // 自定义事件
           },
           {
             label: '修改', // 操作名称
             permission:'1001' //权限点
             type: 'icon', //按钮类型icon为图表类型
             icon:'el-icon-plus'
             handleRow: function(){} // 自定义事件
           }
         ]
       }
}

tablePane.vue配置项Cols详解

  • 普通列
cols:[
   {
       label: '标题',
       prop: 'title',
       width: 200
    }
]
  • 普通列字体颜色改变
cols:[
  {
    label: '状态',
    prop: 'status',
    isTemplate: function(val) {
      if (val === 1) {
        return '禁言中'
      } else {
        return '已解禁'
      }
    },
    isTemplateClass: function(val) {
      if (val === 1) {
        return 'color-red'
      } else {
        return 'color-green'
      }
    }
  }
]
  • 带filter过滤器列
cols:[
   {
      label: '推送时间',
      prop: 'pushTime',
      isCodeTableFormatter: function(val) {
        return timeFormat(val.pushTime)
      }
    },
    {
      label: '状态',
      prop: 'status',
      isCodeTableFormatter: function(val) {
        if(val.status===1){
          return '成功'
        }else{
          return '失败'
        }
      }
    }
]
  • 带图标列
cols:[
  {
     label: '目标类型',
     prop: 'targetType',
     isIcon: true,
     filter: function(val) {
       if (val === 4) {
         return '特定用户'
       } else if (val === 3) {
         return '新注册用户'
       } else if (val === 2) {
         return '标签用户'
       } else if (val === 1) {
         return '全部用户'
       }
     },
     icon: function(val) {
       if (val === 4) {
         return 'el-icon-mobile'
       } else {
         return false
       }
     },
     handlerClick: this.handlerClick
   }
]

开始封装

<template>
 <div>
   <div v-if="dataSource.tool" class="tool">
     <el-button
       v-for="(item) in dataSource.tool"
       :key="item.key"
       v-permission="item.permission"
       class="filter-item"
       :style="{'background':item.bgColor,borderColor:item.bgColor}"
       :type="item.type || 'primary'"
       @click="item.handleClick(item.name,$event)"
     >
       {{ item.name }}
     </el-button>
   </div>
   <el-table
     ref="table"
     v-loading="dataSource.loading"
     style="width: 100%;"
     :class="{ 'no-data': !dataSource.data || !dataSource.data.length }"
     :data="dataSource.data"
     @row-click="getRowData"
     @selection-change="dataSource.handleSelectionChange"
   >
     <!-- 是否有多选 -->
     <el-table-column
       v-if="dataSource.isSelection"
       :selectable="dataSource.selectable"
       type="selection"
       :width="dataSource.selectionWidth || 50"
       align="center"
     />
     <!-- 是否需要序号 -->
     <el-table-column
       v-if="dataSource.isIndex"
       type="index"
       label="序号"
       width="55"
       align="center"
     />
     <template v-for="item in dataSource.cols">
       <!-- 表格的列展示 特殊情况处理 比如要输入框 显示图片 -->
       <el-table-column
         v-if="item.isTemplate"
         :key="item.prop"
         v-bind="item"
       >
         <template slot-scope="scope">
           <!-- 比如要输入框 显示图片等等 自己定义 -->
           <slot :name="item.prop" :scope="scope" />
         </template>
       </el-table-column>
      <!-- 需要特殊颜色显示字体-->
       <el-table-column
         v-if="item.isSpecial"
         :key="item.prop"
         v-bind="item"
         align="center"
       >
         <template slot-scope="scope">
           <span :class="item.isSpecialClass(scope.row[scope.column.property])">{{ item.isSpecial(scope.row[scope.column.property]) }}</span>
         </template>
       </el-table-column>
       <!-- 需要带图标的某列,带回调事件-->
       <el-table-column
         v-if="item.isIcon"
         :key="item.prop"
         v-bind="item"
         align="center"
       >
         <template slot-scope="scope">
           <span>
             <span>{{ item.filter(scope.row[scope.column.property]) }}</span>
             <i v-if="item.icon" :class="[item.icon(scope.row[scope.column.property]),'icon-normal']" @click="item.handlerClick(scope.row)" />
           </span>
           <!-- 比如要输入框 显示图片等等 自己定义 -->
           <slot :name="item.prop" :scope="scope" />
         </template>
       </el-table-column>
       <!-- 图片带tooltip -->
       <el-table-column
         v-if="item.isImagePopover"
         :key="item.prop"
         v-bind="item"
         align="center"
       >
         <template slot-scope="scope">
           <el-popover
             placement="right"
             title=""
             trigger="hover"
           >
             <img class="image-popover" :src="scope.row[scope.column.property]+'?x-oss-process=image/quality,q_60'" alt="">
             <img slot="reference" class="reference-img" :src="scope.row[scope.column.property]+'?x-oss-process=image/quality,q_10'" alt="">
           </el-popover>
         </template>
       </el-table-column>
       <!-- 大部分适用 -->
       <el-table-column
         v-if="!item.isImagePopover && !item.isTemplate && !item.isSpecial&&!item.isIcon"
         :key="item.prop"
         v-bind="item.isCodeTableFormatter ? Object.assign({ formatter: item.isCodeTableFormatter }, item) : item"
         align="center"
         show-overflow-tooltip
       />
     </template>
     <!-- 是否有操作列 -->
     <!-- 没有数据时候不固定列 -->
     <el-table-column
       v-if="dataSource.isOperation"
       :show-overflow-tooltip="dataSource.operation.overflowTooltip"
       v-bind="dataSource.data && dataSource.data.length ? { fixed: 'right' } : null"
       style="margin-right:20px"
       class-name="handle-td"
       label-class-name="tc"
       :width="dataSource.operation.width"
       :label="dataSource.operation.label"
       align="center"
     >
       <!-- UI统一一排放3个,4个以上出现更多 -->
       <template slot-scope="scope">
         <!-- 三个一排的情况,去掉隐藏的按钮后的长度 -->
         <template v-if="dataSource.operation.data.length > 0">
           <div class="btn">
             <div v-for="(item) in dataSource.operation.data" :key="item.label">
               <template v-if="item.type!=='icon'">
                 <el-button
                   v-permission="item.permission"
                   v-bind="item"
                   :type="item.type?item.type:''"
                   size="mini"
                   @click.native.prevent="item.handleRow(scope.$index, scope.row, item.label)"
                 >
                   {{ item.label }}
                 </el-button>
               </template>
               <template v-else>
                 <i :class="[icon,item.icon]" v-bind="item" @click="item.handleRow(scope.$index, scope.row, item.label)" />
               </template>
             </div>
           </div>
         </template>
       </template>
     </el-table-column>
   </el-table>
   <div class="page">
     <el-pagination
       v-if="dataSource.pageData.total>0"
       :current-page="dataSource.pageData.pageNum"
       :page-sizes="dataSource.pageData.pageSizes?dataSource.pageData.pageSizes:[5,10,15,20]"
       :page-size="dataSource.pageData.pageSize"
       layout="total, sizes, prev, pager, next, jumper"
       :total="dataSource.pageData.total"
       @size-change="handleSizeChange"
       @current-change="handleCurrentChange"
     />
   </div>
 </div>
</template>
<script>
//  dataSource: {
//          tool:[
//            {
//              name: '新增用户', //按钮名称
//              key: 1,  // 唯一标识符
//              permission: 2010106, // 权限点
//              type: '',  // 使用element自带按钮类型
//              bgColor: '#67c23a', // 自定义背景色
//              handleClick: this.handleAdd //自定义事件
//            },
//          ]
//         data: [], // 表格数据
//         cols: [], // 表格的列数据
//         handleSelectionChange:(val)=>{} //点击行选中多选返回选中数组
//         isSelection: false, // 表格有多选时设置
//         isOperation: true, // 表格有操作列时设置
//         isIndex: true, // 列表序号
//         loading: true, // loading
//         pageData: {
//          total: 0, // 总条数
//          pageSize: 10, // 每页数量
//          pageNum: 1, // 页码
//          pageSize:[5,10,15,20]// 每页数量
//         }
//         operation: {
//           // 表格有操作列时设置
//           label: '操作', // 列名
//           width: '350', // 根据实际情况给宽度
//           data: [
//             {
//               label: '冻结', // 操作名称
//               permission:'' //权限点
//               type: 'info', //按钮类型
//               handleRow: function(){} // 自定义事件
//             },
//           ]
//         }
//       },
export default {
 // 接收父组件传递过来的值
 props: {
   //  表格数据和表格部分属性的对象
   // eslint-disable-next-line vue/require-default-prop
   dataSource: {
     type: Object
   }
 },
 data() {
   return {
   }
 },
 watch: {
   'dataSource.cols': { // 监听表格列变化
     deep: true,
     handler() {
       // 解决表格列变动的抖动问题
       this.$nextTick(this.$refs.table.doLayout)
     }
   }
 },
 methods: {
   handleAdd(name) {
     console.log(name)
     this.$emit('toolMsg', name)
   },
   handleRow(index, row, lable) {
     console.log(index, row, lable)
   },
   handleSizeChange(val) {
     this.$emit('changeSize', val)
     console.log(`每页 ${val} 条`)
   },
   handleCurrentChange(val) {
     this.$emit('changeNum', val)
     console.log(`当前页: ${val}`)
   },
   // 点击行即可选中
   getRowData(row) {
     this.$refs.table.toggleRowSelection(row)
   }
 }
}
</script>
<style lang="scss" scoped>
.page{
 margin-top: 20px;
}
.btn{
 display: flex;
 justify-content: center;
}
.btn div{
 margin-left: 5px;
}
.reference-img{
 width: 40px;
 height: 40px;
 background-size:100% 100%;
 border-radius: 4px;
}
.image-popover{
 width: 200px;
 height: 200px;
 background-size:100% 100%;
}
.icon {
 width: 25px;
 font-size: 20px;
 font-weight: bold;
}
</style>

实战

配置某页面,咱先看配置图片是不是省事多了,而且条理清楚

<template>
  <div class="app-container">
    <filter-pane :filter-data="filterData" @filterMsg="filterMsg" />
    <table-pane
      :data-source="dataSource"
      @changeSize="changeSize"
      @changeNum="changeNum"
    />
    <add :dialog-add="dialogAdd" @childMsg="childMsg" />
  </div>
</template>
<script>
import filterPane from '@/components/Table/filterPane'
import tablePane from '@/components/Table/tablePane'
import add from './components/add'
import { getVersionList, delVersion } from '@/api/user'
import { timeFormat } from '@/filters/index'
export default {
  name: 'Suggestion',
  components: { filterPane, tablePane, add },
  data() {
    return {
      // 搜索栏配置
      filterData: {
        timeSelect: false,
        elselect: [
          {
            name: '状态',
            width: 120,
            key: 'platform',
            option: [
              {
                key: '全部',
                value: '全部'
              },
              {
                key: 1,
                value: 'IOS'
              },
              {
                key: 2,
                value: '安卓'
              }
            ]
          }
        ]
      },
      // 表格配置
      dataSource: {
        tool: [{
          name: '新增版本',
          key: 1,
          permission: 2010701,
          handleClick: this.handleAdd
        }],
        data: [], // 表格数据
        cols: [
          {
            label: '发布时间',
            prop: 'appIssueTime',
            isCodeTableFormatter: function(val) {
              return timeFormat(val.appIssueTime)
            }
          },
          {
            label: 'APP名称',
            prop: 'appName'
          },
          {
            label: 'APP版本',
            prop: 'appVersion'
          },
          {
            label: '平台',
            prop: 'appPlatform',
            isCodeTableFormatter: function(val) {
              if (val.appPlatform === 1) {
                return 'IOS'
              } else {
                return 'Android'
              }
            }
          },
          {
            label: '是否自动更新',
            prop: 'appAutoUpdate',
            isCodeTableFormatter: function(val) {
              if (val.appAutoUpdate === 1) {
                return '是'
              } else {
                return '否'
              }
            }
          },
          {
            label: '更新描述',
            prop: 'appDesc',
            width: 300
          },
          {
            label: '下载地址',
            prop: 'downloadAddr'
          },
          {
            label: '发布人',
            prop: 'userName'
          }
        ], // 表格的列数据
        handleSelectionChange: this.handleSelectionChange,
        isSelection: false, // 表格有多选时设置
        isOperation: true, // 表格有操作列时设置
        isIndex: true, // 列表序号
        loading: true, // loading
        pageData: {
          total: 0, // 总条数
          pageSize: 10, // 每页数量
          pageNum: 1 // 页码
        },
        operation: {
          // 表格有操作列时设置
          label: '操作', // 列名
          width: '100', // 根据实际情况给宽度
          data: [
            {
              label: '删除', // 操作名称
              type: 'danger',
              permission: '2010702', // 后期这个操作的权限,用来控制权限
              handleRow: this.handleRow
            }
          ]
        }
      },
      dialogAdd: false,
      msg: {},
      selected: []
    }
  },
  created() {
    this.getList()
  },
  methods: {
    // 获取列表数据
    getList() {
      const data = {
        pageSize: this.dataSource.pageData.pageSize,
        pageNum: this.dataSource.pageData.pageNum
      }
      if (this.msg) {
        if (this.msg.platform === 'IOS') {
          data.platform = 1
        } else if (this.msg.platform === '安卓') {
          data.platform = 2
        }
      }
      this.dataSource.loading = true
      getVersionList(data).then(res => {
        this.dataSource.loading = false
        if (res.succeed) {
          if (res.data.total > 0) {
            this.dataSource.pageData.total = res.data.total
            this.dataSource.data = res.data.data
          } else {
            this.dataSource.data = []
            this.dataSource.pageData.total = 0
          }
        }
      })
    },
    // 搜索层事件
    filterMsg(msg) {
      this.msg = msg
      if (Object.keys(msg).length > 0) {
        this.getList(msg)
      } else {
        this.getList()
      }
    },
    // 子组件通信
    childMsg(msg) {
      if (msg.dialogAdd === false) {
        this.dialogAdd = false
      } else if (msg.refreshList) {
        this.getList()
      }
    },
    // 改变每页数量
    changeSize(size) {
      this.dataSource.pageData.pageSize = size
      this.getList()
    },
    // 改变页码
    changeNum(pageNum) {
      this.dataSource.pageData.pageNum = pageNum
      this.getList()
    },
    // 多选事件
    handleSelectionChange(val) {
      this.selected = val
    },
    // 表格上方工具栏回调
    handleAdd(index, row) {
      this.dialogAdd = true
    },
    // 表格操作列回调
    handleRow(index, row, lable) {
      if (lable === '删除') {
        this.$confirm('确认删除该版本?', '温馨提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          delVersion({ versionId: row.id }).then(res => {
            if (res.succeed) {
              this.$message.success('删除成功')
              this.getList()
            }
          })
        }).catch(() => {
        })
      }
    }
  }
}
</script>
<style  scoped lang='scss'>
</style>

结尾

filterPane.vuetablePane.vue已完成,有些特殊页面只需要复制下到当前特殊页面的components里改动下就

可以了,目前还在不断完善中,大家有什么问题可以提出来,也好进一步优化。

完整源文件在gitHub,可以下载直接使用,后续会持续更新

我给起了个名k-table以k开头代表快速的意思

以上就是Vue技巧Element Table二次封装实战示例的详细内容,更多关于Vue Element Table二次封装的资料请关注我们其它相关文章!

(0)

相关推荐

  • Vue Router4路由导航守卫实例全面解析

    目录 前言 一.什么是导航守卫 二.全局前置守卫 可选的第三个参数 next 三.全局解析守卫 四.全局后置钩子 五.路由独享的守卫 六.组件内的守卫 可用的配置 API 使用组合 API 七.完整的导航解析流程 前言 在写Vue项目的时候,少不了使用路由vue-router,而路由守卫是vue-router中一个非常重要的概念,也是非常重要的技巧.它能够很好的帮助开发者“监视”每一个跳转的路由. 一.什么是导航守卫 正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫

  • Vue ELement Table技巧表格业务需求实战示例

    目录 前言 常见业务 需求:合并行 思路分析 需求合并列 思路分析 前言 在我们日常开发中,表格业务基本是必不可少的,对于老手来说确实简单,家常便饭罢了,但是对于新手小白如何最快上手搞定需求呢?本文从思路开始着手,帮你快速搞定表格. 常见业务 需求:合并行 1. 合并条码一样的两行 2. 触摸高亮关闭,表格颜色重一点 思路分析 调取element Table的回调 通过给table传入span-method方法可以实现合并行或列,方法的参数是一个对象,里面包含当前行row.当前列column.当

  • Vue简单封装axios网络请求的方法

    目录 Vue简单封装axios网络请求 一.utils下的httpUtils.js: 二./api下的path.js: 三./api下的index.js: 四.组件中引入并请求: Vue简单封装axios网络请求 一.utils下的httpUtils.js: import axios from 'axios'; import querystring from 'querystring'; const errorHandler = (status, info) => { switch(status

  • vue3封装echarts组件最佳形式详解

    目录 思路 目录结构 组件代码 v-charts.vue useCharts.ts type.d.ts options/bar.ts 项目中使用 index.vue /hooks/useStatisDeviceByUserObject.ts 思路 项目中经常用到echarts,不做封装直接拿来使用也行,但不可避免要写很多重复的配置代码,封装稍不注意又会过度封装,丢失了扩展性和可读性.始终没有找到一个好的实践,偶然看到一篇文章,给了灵感.找到了一个目前认为用起来很舒服的封装. 结合项目需求,针对不

  • 手写可拖动穿梭框组件CustormTransfer vue实现示例

    目录 本文内容 最终效果图 组件html布局 穿梭框左侧内容 穿梭框右侧内容 穿梭框中间向左.向右按钮 把排序好的穿梭数据传给父组件 整体代码 小结 本文内容 需求是实现类似 el-transfer的组件,右侧框内容可以拖动排序: 手写div样式 + vuedraggable组件实现. 最终效果图 组件html布局 新建一个组件文件 CustormTransfer.vue,穿梭框 html 分为左中右三部分,使用flex布局使其横向布局,此时代码如下 <template> <div cl

  • petite vue的使用示例详解

    目录 题引: 特征及使用: 1. CDN引入: 2.module引入 3. 组件化 4. 模板组件 结尾: 题引: 这几天在公司没事做,于是上网看看有关vue的文章,忽然看到尤大大的一个文章:只有5kb大小的mini vue,好家伙,又整活了,这不得冲一冲嘛. 特征及使用: petite-vue体积更小,约5bk: 对渐进的增强更加的明显,特别是运用在服务端渲染的页面上更是便捷.系统看了一下,语法跟vue的语法绝大部分是一样了,除了增加了一些新的语法糖: 基于reactive进行响应式 peti

  • 尤大大新活petite-vue的实现

    目录 前言 简介 上活 简单使用 根作用域 指定挂载元素 生命周期 组件 全局状态管理 自定义指令 内置指令 不支持 总结 前言 打开尤大大的GitHub,发现多了个叫 petite-vue 的东西,好家伙,Vue3 和 Vite 还没学完呢,又开始整新东西了?本着学不死就往死里学的态度,咱还是来瞅瞅这到底是个啥东西吧,谁让他是咱的祖师爷呢! 简介 从名字来看可以知道 petite-vue 是一个 mini 版的vue,大小只有5.8kb,可以说是非常小了.据尤大大介绍,petite-vue 是

  • Vue技巧Element Table二次封装实战示例

    目录 前言 思考 实践 filterPane.vue 明确目标 传入数据结构整理 timeSelect elinput elselect 开始封装 tablePane.vue 明确目标 传入数据结构整理 tool cols pageData operation tablePane.vue配置项Cols详解 开始封装 实战 结尾 前言 由于重构后台管理项目中有好多表格页面, 举个栗子 这表格看着还挺好看,写起来叫人直呼XX,多动脑子少掉发,少走弯路多省鞋. 写了一个后感觉太麻烦了,于是我奋笔疾书,

  • 基于Vue+element-ui 的Table二次封装的实现

    本人第一次写这个 写的不好还望指出来 作为一个由于公司产品的升级然促使我从一个后端人员自学变成前端的开发人员 ! 公司做的数据管理系统所以离不开表格了 然后表格样式统一啥的就想到封装一个element-ui 里面的table+Pagination了 效果图 表格组件的引入与使用 <com-table title="监测数据" v-model="tableData4" @selection-change="handleSelectionChange&q

  • vue中axios的二次封装实例讲解

    我们做项目时,虽然axios也可以直接拿来用,但是对接口比较零散,不太好进行维护,也会产生大量的重复代码,所以我在这对axios进行了统一接口处理 第一步,先在src中的公共文件夹中如utils里新建request.js文件 import axios from 'axios' import router from '@/router/routers' import { Notification, MessageBox } from 'element-ui' import store from '

  • vue axios 二次封装的示例代码

    这段时间告诉项目需要,用到了vue. 刚开始搭框架的时候用的是vue-resource后面看到官方推荐axios就换过来了 顺便封装了一下 //引入axios import axios from 'axios' let cancel ,promiseArr = {} const CancelToken = axios.CancelToken; //请求拦截器 axios.interceptors.request.use(config => { //发起请求时,取消掉当前正在进行的相同请求 if

  • vue项目中axios请求网络接口封装的示例代码

    每个项目网络请求接口封装都是很重要的一块,第一次做Vue项目,我们的封装方法如下: (1).新建一个js文件,取名api.js (2).引入 axios ,mint-UI ,如下图: import axios from 'axios' import {MessageBox, Toast} from 'mint-ui' axios.defaults.timeout = 50000//默认请求超时时间 axios.defaults.headers = '请求头' (2).封装get方法 export

  • vue elementui 实现搜索栏子组件封装的示例代码

    目录 前言 需求 实现 子组件(search.vue) 父组件部分主要代码(index.vue) 前言 描述: 在基本项目中搜索栏.分页组件格式样式几乎是固定的,只是对应的数据不同,由于模块会随着需求的不断增加,可能会导致重复代码越来越多,这时可以用到子组件,需要将相同的模块代码统一封装,提高开发效率和页面统一.(自己的想法,只根据自己需求来说) 需求 实现 子组件(search.vue) html <template> <div class="search-main"

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

    前言 在公司实习使用vue+element-ui框架进行前端开发,使用表格el-table较为多,有些业务逻辑比较相似,有些地方使用的重复性高,如果多个页面使用相同的功能,就要多次重复写逻辑上差不多的代码,所以打算对表格这个组件进行封装,将相同的代码和逻辑封装在一起,把不同的业务逻辑抽离出来.话不多说,下面就来实现一下吧. 一.原生el-tbale代码--简单の封装 这里直接引用官方的基础使用模板,直接抄过来(✪ω✪),下面代码中主要是抽离html部分,可以看出每个el-table-column

  • Element使用el-table组件二次封装

    目录 前言 一.安装引入 二.封装功能 三.样式覆盖 四.使用组件 前言 在vue开发中使用element-ui的el-table时一般都需要进行封装以便于复用,提高开发效率,减少重复代码,这篇博客对el-table进行简单的二次封装: 一.安装引入 Element官方文档 npm安装element-ui: npm i element-ui -S 可以看文档按需引入,这里为了方便直接全局引入了: import Vue from 'vue' import App from './App.vue'

  • 基于element-ui表格的二次封装实现

    在项目中经常会使用到element的表格,如果每次都cv,也确实有点麻烦,基于这个情况我对表格进行了二次封装 写一个Table组件 首先先写表格样式 <el-table :data="tableData" :header-cell-style="headerStyle" :height="height" :border="border" @selection-change="handleSelectionCha

随机推荐