vue可编辑表格

这篇具有很好参考价值的文章主要介绍了vue可编辑表格。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

内容包含:校验。下拉框。输入框。日期控件

效果图

vue可编辑表格,vue.js,javascript,前端

vue可编辑表格,vue.js,javascript,前端

 vue可编辑表格,vue.js,javascript,前端

1.代码目录

vue可编辑表格,vue.js,javascript,前端

2.index.js

import SjjEditable from './src/editable.vue'
// import Vue from 'vue'

SjjEditable.install = function (Vue) {
  Vue.component(SjjEditable.name, SjjEditable)
}

export default SjjEditable

 3.utilsjs


export const getRowIndetity = (row, rowKey) => {
  if (!row) throw new Error('row is required when get row identity')
  if (typeof rowKey === 'string') {
    if (rowKey.indexOf('.') < 0) {
      return row[rowKey]
    }
    let key = rowKey.split('.')
    let current = row
    for (let i = 0; i < key.length; i++) {
      current = current[key[i]]
    }
    return current
  } else if (typeof rowKey === 'function') {
    return rowKey.bind(null, row)
  }
}

4.editable-column.vue

<template>
  <el-table-column v-if="isIndexTypeColumn(type)" :prop="prop" :type="type" :label="label" :width="width" :min-width="minWidth"/>

  <el-table-column v-else :prop="prop" :type="type" :label="label" :width="width" :min-width="minWidth" >
    <template slot-scope="scope">
      <el-form v-if="type && editing && editing[scope.$index] && editing[scope.$index][prop]" :model="scope.row" :rules="rules" @validate="handleValidate" :ref="`form_${scope.$index}_${prop}`">
        <el-form-item :prop="type === 'select' ? prop.replace(/(\_*)(text|txt)/ig, '') : prop" class="el-editable-form-item">
          <el-input autofocus v-if="type === 'text' || type === 'textarea'" :type="type" v-model="scope.row[prop]" class="el-editable-element" @change="handleChange"/>
          <el-date-picker v-else-if="type === 'date' || type === 'datetime'" v-model="scope.row[prop]" :type="type" class="el-editable-element" @change="handleChange" :format="format" :value-format="valueFormat"/>
          <el-select v-else-if="type === 'select'" v-model="scope.row[prop.replace(/(\_*)(text|txt)/ig, '')]" class="el-editable-element" @change="handleChange">
            <el-option v-for="(o,i) in options" :key="i" :value="o.value" :label="o.label || o.text" :disabled="o.disabled ? true:false"/>
          </el-select>
          <sjj-currency v-else-if="type === 'currency'" v-model="scope.row[prop]" class="el-editable-element" @change="handleChange"/>
        </el-form-item>
      </el-form>
      <div v-else :class="editedCell&&editedCell[scope.$index]&&editedCell[scope.$index][prop] ? 'is-edited' : ''">{{ scope.row[prop] }}</div>
    </template>
  </el-table-column>
</template>

<script>
import sjjCurrency from '../../currency/index.js'
import merge from 'element-ui/src/utils/merge'
import { getRowIndetity } from './utils.js'
export default {
  name: 'SjjEditableColumn',
  props: {
    type: {
      type: String,
      default: ''
    },
    label: String,
    className: String,
    labelClassName: String,
    prop: String,
    width: {},
    minWidth: {},
    index: [Number, Function],
    options: Array,
    format: { // 显示在输入框中的格式,默认为yyyy-MM-dd
      type: String,
      default: 'yyyy-MM-dd'
    },
    valueFormat: { // 绑定值得格式,默认为yyyy-MM-dd
      type: String,
      default: 'yyyy-MM-dd'
    }
  },
  components: {
    sjjCurrency
  },
  data () {
    return {
      validates: false,
      editedCell: {}, // 编辑成功过的cell们
      validatedRow: {}, // 已编辑的行
      validated: {} // 已编辑的cell
    }
  },
  mounted () {
    this.validated = this.$parent.$parent.edited
    this.validatedRow = this.$parent.$parent.editedRow
  },
  computed: {
    editing () {
      return this.$parent.$parent.editing || {}
    },
    tableData () {
      return this.$parent.$parent.tableData || []
    },
    originData () {
      return this.$parent.$parent.originData || []
    },
    rules () {
      return this.$parent.$parent.$props.rules || []
    }
  },
  methods: {
    isIndexTypeColumn (type) {
      return type === 'index' // ['selection', 'index', 'expand']
    },
    isDataColumn (type) {
      return ['text', 'textarea', 'date', 'datetime', 'select', 'currency'].indexOf(type) > -1
    },
    handleValidate (prop, validateFlag) {
      this.$parent.$parent.setValidateFlag(validateFlag)
      if (validateFlag) {
        this.editedCell = merge(this.editedCell, this.editing)
        let property = prop
        for (let rowIdx in this.editing) {
          if (this.$props.type === 'select') {
            property = this.$props.prop // property带text,prop是rules的属性
          }
          this.setEditedRow(rowIdx, prop, property)
        }
      }
    },
    handleChange (value) {
      for (let rowIdx in this.editing) {
        this.$emit('change', rowIdx, this.$props.prop, value)
      }
    },
    // validateColumn (rowIdx, value) {
    //   let prop = this.$props.prop
    //   if (this.$props.type === 'select') {
    //     prop = prop.replace(/(\_*)(text|txt)/ig, '')
    //   }
    //   this.$refs[`form_${rowIdx}_${prop}`].validate((valid, prop) => {})
    // },
    setEditedRow (rowIdx, prop, property) {
      let value = this.tableData[rowIdx][prop]
      let textValue = value
      if (this.$props.type === 'select') {
        let arr = this.$props.options.filter(o => {
          return o.value === value
        })
        if (arr.length) {
          textValue = arr[0].label || arr[0].text
        }
      }
      this.tableData[rowIdx][property] = textValue

      if (value !== this.originData[rowIdx][prop]) {
        let obj = {}
        obj[prop] = value
        if (this.$props.type === 'select') {
          obj[property] = textValue
        }
        if (this.validated.hasOwnProperty(rowIdx)) {
          this.validated[rowIdx] = merge(this.validated[rowIdx], obj)
        } else {
          let rowId = getRowIndetity(this.tableData[rowIdx], this.$parent.$parent.$props.rowKey)
          obj[this.$parent.$parent.$props.rowKey] = rowId
          this.validated[rowIdx] = obj
        }

        this.validatedRow[rowIdx] = merge({}, this.tableData[rowIdx])
      } else {
        if (this.editedCell[rowIdx]) {
          delete this.editedCell[rowIdx][property]
        }

        if (this.validated.hasOwnProperty(rowIdx)) {
          let equalFlag = true
          for (let k in this.validated[rowIdx]) {
            if (k === prop || k === property) {
              continue
            }
            if (this.validated[rowIdx][k] !== this.originData[rowIdx][k]) {
              equalFlag = false
              break
            }
          }
          if (equalFlag) {
            delete this.validated[rowIdx]
          } else {
            delete this.validated[rowIdx][prop]
            delete this.validated[rowIdx][property]
          }
        }
        if (this.validatedRow.hasOwnProperty(rowIdx)) {
          let equalFlag = true
          for (let k in this.validatedRow[rowIdx]) {
            if (k === prop || k === property) {
              continue
            }
            if (this.validatedRow[rowIdx][k] !== this.originData[rowIdx][k]) {
              equalFlag = false
              break
            }
          }
          if (equalFlag) {
            delete this.validatedRow[rowIdx]
          } else {
            this.validatedRow[rowIdx] = merge({}, this.tableData[rowIdx])
          }
        }
      }
      this.$parent.$parent.setEdited(this.validated)
      this.$parent.$parent.setEditedRow(this.validatedRow)
    }
  }
}
</script>

<style scoped>
  .is-edited {
    color: red;
  }
/* .sjj-editable-form-item {
  margin: 0;
}
.sjj-editable-element.el-input {
  line-height: normal;
}
.sjj-editable-form-item  /deep/ .el-form-item__content {
  line-height: normal;
}
.sjj-editable-form-item  /deep/ .el-form-item__error {
  position: relative;
}
.sjj-editable-form-item  /deep/ .el-input__inner {
  height: 0;
  line-height: 1;
  padding: 15px;
} */
/* >>> .el-table__row {
  height: 50px;
}
>>> .el-table td, .el-table th {
  padding: 4px 0;
} */
</style>

5.editable.vue

<template>
  <div class="el-editable">
    <el-table border :data="tableData" @cell-dblclick="handleCellDblClick" :row-key="rowKey" :height="height">
      <slot></slot>
    </el-table>
  </div>
</template>

<script>
import Vue from 'vue'
import merge from 'element-ui/src/utils/merge'
import { getRowIdentity } from 'element-ui/packages/table/src/util'
export default {
  name: 'SjjEditable',
  props: {
    data: {
      type: Array,
      default: Function,
      required: true
    },
    rowKey: {
      type: String,
      required: true
    },
    height: [String, Number],
    rules: {
      type: Object,
      required: true
    }
  },
  data () {
    return {
      originData: [], // 原始表格数据
      editing: {}, // 正在编辑对象
      validateFlag: null,
      editedRow: {}, // 编辑成功的row
      deditedRowData: [], // 编辑成功的行数据集
      edited: {}, // 编辑成功的cell
      editedData: [], // 编辑成功的单元格数据集
      slotChildren: []
    }
  },
  created () {
    this.setOriginData(this.data)
  },
  computed: {
    tableData () {
      if (!this.data) {
        return []
      }
      let arr = this.data.filter((d, idx) => {
        return d
      })
      return arr
    }
  },
  watch: {
    data (newVal, oldVal) {
      this.setOriginData(this.data)
    }
  },
  methods: {
    setOriginData (val) {
      if (!val) {
        this.originData = []
      } else {
        this.originData = val.map((d, idx) => {
          let obj = merge({}, d)
          return obj
        })
      }
    },
    setValidateFlag (val) {
      this.validateFlag = val
    },
    setEditedRow (val) {
      this.editedRow = val
    },
    setEdited (val) {
      this.edited = val
    },
    handleCellDblClick (row, column, cell, event) {
      // this.slotChildren = []
      // for (let i = 0; i < this.$slots.default.length; i++) {
      //   console.log(this.$slots.default[i].elm.nodeType)
      //   if (this.$slots.default[i].elm.nodeType !== 3) {
      //     this.slotChildren.push(this.$slots.default[i]) // 获得那些插入的按钮
      //   }
      // }
      // console.log(this.slotChildren[2])
      //if (Object.keys(this.editing).length && !this.validateFlag) {
        //return
      //}
      this.editing = {}
      let rowIdx = null
      for (let i = 0; i < this.tableData.length; i++) {
        let d = this.tableData[i]
        if (getRowIdentity(d, this.rowKey) === getRowIdentity(row, this.rowKey)) {
          rowIdx = i
        }
      }
      if (rowIdx !== null) {
        let obj = {}
        obj[column.property] = true
        Vue.set(this.editing, rowIdx, obj)
      }
    },
    getEditedRowData () {
      this.editedRowData = []
      for (let rowIdx in this.editedRow) {
        this.editedRowData.push(this.editedRow[rowIdx])
      }
      return this.editedRowData
    },
    getEditedData () {
      this.editedData = []
      for (let rowIdx in this.edited) {
        this.editedData.push(this.edited[rowIdx])
      }
      return this.editedData
    },
    isPass () {
      return this.validateFlag === null || this.validateFlag === true
    }
  }
}
</script>

6.使用

<template>
  <div class="phone">
    <el-button @click="getEditedRowData">查看已编辑行数据</el-button>
    <el-button @click="getEditedData">查看已编辑单元格数据</el-button>
    <sjj-editable :data="tableData" row-key="rowId" :rules="rules" ref="tb" style="margin-top: 20px">
      <sjj-editable-column type="index" label="序号" width="100"></sjj-editable-column>
      <sjj-editable-column prop="date" label="日期" type="date" @change="handleChangeDate"></sjj-editable-column>
      <sjj-editable-column prop='name' label="姓名" type="text" @change="handleChangeName"></sjj-editable-column>
      <sjj-editable-column prop="provinceText" label="城市" type="select" :options="options"></sjj-editable-column>
      <sjj-editable-column prop='address' label="地址" type="textarea"></sjj-editable-column>
      <sjj-editable-column prop='zip' label="邮编"></sjj-editable-column>
    </sjj-editable>

    <div style="margin-bottom: 20px;">
      <h3>Editable Attributes</h3>
      <el-table
        :data="tableData2"
        stripe
        border
        style="width: 100%">
        <el-table-column
          prop="parameter"
          label="参数"
          width="180">
        </el-table-column>
        <el-table-column
          prop="instructions"
          label="说明">
        </el-table-column>
        <el-table-column
          prop="type"
          label="类型"
          width="180">
        </el-table-column>
        <el-table-column
          prop="optionalValue"
          label="可选值"
          width="180">
        </el-table-column>
        <el-table-column
          prop="defaultValue"
          label="默认值"
          width="180">
        </el-table-column>
      </el-table>
    </div>

    <div style="margin-bottom: 20px;">
      <h3>Editable-Column Attributes</h3>
      <el-table
        :data="tableData3"
        stripe
        border
        style="width: 100%">
        <el-table-column
          prop="parameter"
          label="参数"
          width="180">
        </el-table-column>
        <el-table-column
          prop="instructions"
          label="说明">
        </el-table-column>
        <el-table-column
          prop="type"
          label="类型"
          width="180">
        </el-table-column>
        <el-table-column
          prop="optionalValue"
          label="可选值"
          width="180">
        </el-table-column>
        <el-table-column
          prop="defaultValue"
          label="默认值"
          width="180">
        </el-table-column>
      </el-table>
    </div>
    <div style="margin-bottom: 20px;">
      <h3>Editable Methods</h3>
      <el-table
        :data="tableData4"
        stripe
        border
        style="width: 100%">
        <el-table-column
          prop="name"
          label="方法名"
          width="180">
        </el-table-column>
        <el-table-column
          prop="instructions"
          label="说明">
        </el-table-column>
        <el-table-column
          prop="parameter"
          label="参数"
          width="180">
        </el-table-column>
        <el-table-column
          prop="valueType"
          label="返回值类型"
          width="180">
        </el-table-column>
        <el-table-column
          prop="valueFormat"
          label="返回值格式"
          width="180">
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>

<script>
import SjjEditable from '../../components/editable/index.js'
import SjjEditableColumn from '../../components/editable/src/editable-column'
export default {
  name: 'PhoneS',
  components: {
    SjjEditable,
    SjjEditableColumn
  },
  data () {
    return {
      options: [
        {
          value: '1',
          text: '上海'
        },
        {
          value: '2',
          text: '北京'
        },
        {
          value: '3',
          text: '杭州'
        }
      ],
      tableData: [
        {
          rowId: 'R001',
          date: '2021-08-17',
          name: '王小虎',
          province: '1',
          provinceText: '上海',
          city: '普陀',
          address: '上海市普陀区',
          zip: 200320,
          tag: '家'
        },
        {
          rowId: 'R002',
          date: '2021-08-18',
          name: '王小',
          province: '2',
          provinceText: '北京',
          city: '朝阳',
          address: '北京朝阳',
          zip: 200330,
          tag: '公司'
        }
      ],
      rules: {
        name: [
          { required: true, message: '请输入姓名', trigger: 'blur' },
          { min: 1, max: 3, message: '姓名不超过3个字符', trigger: 'blur' }
        ],
        address: [
          { required: true, message: '请输入地址', trigger: 'blur' }
        ],
        province: [
          { required: true, message: '请选择城市', trigger: 'change' }
        ],
        date: [
          { required: true, message: '请选择日期', trigger: 'change' }
        ]
      },
      tableData2: [
        {
          parameter: 'data',
          instructions: '表格数据,必输',
          type: 'Array',
          optionalValue: '-',
          defaultValue: '-'
        },
        {
          parameter: 'row-key',
          instructions: '行数据的key,必输',
          type: 'String',
          optionalValue: '-',
          defaultValue: '-'
        },
        {
          parameter: 'rules',
          instructions: '验证规则,必输',
          type: 'Object',
          optionalValue: '-',
          defaultValue: '-'
        },
        {
          parameter: 'height',
          instructions: '表格高度,默认为自动高度,如果height为number类型,单位px;如果height为String类型,则这个高度会设置为Table的style.height的值,Table的高度则会受控于外部样式',
          type: 'String/Number',
          optionalValue: '-',
          defaultValue: '-'
        }
      ],
      tableData3: [
        {
          parameter: 'type',
          instructions: '列属性,其中,不设置/index表示双击不可编辑',
          type: 'String',
          optionalValue: 'index/text/textarea/select/date/datetime/currency',
          defaultValue: '-'
        },
        {
          parameter: 'index',
          instructions: '如果设置了type=index,可以通过传递index属性来定义索引',
          type: 'String/Function(index)',
          optionalValue: '-',
          defaultValue: '-'
        },
        {
          parameter: 'options',
          instructions: '如果设置了type=select,通过传递options属性定义选项列表',
          type: 'Array',
          optionalValue: '-',
          defaultValue: '-'
        },
        {
          parameter: 'format',
          instructions: '如果设置了type=date,type=datetime,通过传递format实现定义显示在输入框中的格式',
          type: 'String',
          optionalValue: '-',
          defaultValue: 'yyyy-MM-dd'
        },
        {
          parameter: 'value-format',
          instructions: '如果设置了type=date,type=datetime,通过传递value-format属性定义绑定值得格式',
          type: 'String',
          optionalValue: '-',
          defaultValue: 'yyyy-MM-dd'
        },
        {
          parameter: 'label',
          instructions: '显示的标题',
          type: 'String',
          optionalValue: '-',
          defaultValue: '-'
        },
        {
          parameter: 'prop',
          instructions: '对应列内容的字段名',
          type: 'String',
          optionalValue: '-',
          defaultValue: '-'
        },
        {
          parameter: 'width',
          instructions: '固定列宽',
          type: 'String',
          optionalValue: '-',
          defaultValue: '-'
        },
        {
          parameter: 'min-width',
          instructions: '最小列宽,与width的却别是width是固定的,min-width会把剩余宽度按比例分配给设置了min-width的列',
          type: 'Array',
          optionalValue: '-',
          defaultValue: '-'
        }
      ],
      tableData4: [
        {
          name: 'getEditedRowData',
          instructions: '获取编辑过的整行数据集',
          parameter: '-',
          valueType: 'Array',
          valueFormat: '[ { data的某行 }, ... ]'
        },
        {
          name: 'getEditedData',
          instructions: '获取编辑过的行以及列的数据集',
          parameter: '-',
          valueType: 'Array',
          valueFormat: '[ { rowKey: value, prop1: cellValue1, prop2: cellValue2, ... }, ... ]'
        }
      ]
    }
  },
  methods: {
    getEditedRowData () {
      alert(JSON.stringify(this.$refs.tb.getEditedRowData()))
    },
    getEditedData () {
      alert(JSON.stringify(this.$refs.tb.getEditedData()))
    },
    handleChangeDate (rowIdx, prop, value) {
      console.log(`handle change date: ${rowIdx}--${prop}--${value}`)
    },
    handleChangeName (rowIdx, prop, value) {
      console.log(`handle change name: ${rowIdx}--${prop}--${value}`)
    }
  }
}
</script>

<style scoped>
/* .explain {
  margin: 20px 0;
}
.explain span {
  color: #409eff;
}
.phone /deep/ .el-card__body {
  height: 250px;
}
.phone /deep/ .el-row {
  margin-bottom: 20px;
} */
</style>

方法

vue可编辑表格,vue.js,javascript,前端

 vue可编辑表格,vue.js,javascript,前端

vue可编辑表格,vue.js,javascript,前端文章来源地址https://www.toymoban.com/news/detail-680858.html

到了这里,关于vue可编辑表格的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于Luckysheet实现的协同编辑在线表格支持在线导入数据库,前端导出,前端导入,后端导出

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 提示:这里可以添加本文要记录的大概内容: 这两年,在线表格协作工具越来越火,但开源界一直没有相关的实现,被垄断在几个大厂手上,随着Luckysheet 的横空出世,开源界终于也有一个漂亮能打的在

    2024年02月11日
    浏览(56)
  • Vue动态多级表头+行列合计+可编辑表格

    新建组件:Table.vue 新建组件: 可参考链接 https://blog.csdn.net/weixin_45275107/article/details/127509100 https://blog.csdn.net/weixin_39166851/article/details/130765957 https://blog.csdn.net/m0_67841039/article/details/131308126 https://blog.csdn.net/weixin_40881970/article/details/124699566

    2024年02月16日
    浏览(52)
  • Vue + ElementUI 实现可编辑表格及校验

    完整代码见文末 使用两个表单分别用于实现修改和新增处理。 通过一个 editIndex 变量判断是否是编辑状态来决定是否展示输入框,当点击指定行的修改后进行设置即可: 通过隐藏表头实现新增表格和修改表格的合并,同时表格数据只有 addRow : 当无数据时只展示新增行: 通

    2024年02月14日
    浏览(38)
  • Vue+Element UI弹窗实现表格编辑

    点击编辑按钮弹出Dialog js如下 时间格式化 3.1 方法一

    2024年02月12日
    浏览(41)
  • vue+element-ui+springboot 在线表格编辑

    方法: 编辑excel 格式为需要的样子,另存为html 打开files文件,复制html部分代码和样式到vue文件 将需要编辑的部分使用控件填入 代码: 特别地: 服装列数可变,需要动态变换,同时有的可编辑,有的不可编辑 增加表格行数,可通过增加memberList 数据进行动态添加和删除,无

    2024年01月24日
    浏览(47)
  • 【表格单元格可编辑】vue-elementul简单实现table表格点击单元格可编辑,点击单元格变成输入框修改数据

    这是最近遇到的功能,经常会需要一个表格可以编辑数据 类似于excel那种点击一下单元格就可以编辑数据,修改后鼠标移动出去 光标消失就会保存数据给后台 这里记录一下实现方法,其实也比较简单 就是通过角标来判断显示隐藏的 这里考虑到有些时候可能想要点击单元格不

    2024年02月09日
    浏览(42)
  • 使用vue-easytable实现仿excel表格,支持可编辑、添加删除行、虚拟表格等功能

    使用npm安装vue-easytable 在 main.js 中写入以下内容: 代码实现 效果  表格配置 参数 说明 类型 可选值 默认值 tableData 表格数据 Array - - footerData 表格footer 汇总数据,数据结构和 tableData 一致 Array - - columns 列配置,具体项见下表 columns 配置 Array - - showHeader 是否展示表头 Boolean -

    2024年02月08日
    浏览(55)
  • 【Vue/element】 el-table实现表格动态新增/插入/删除 表格行,可编辑单元格

    效果如下: 点击“新增一行”可以在表格最后新增一行,单元格内容可编辑 点击绿色+按钮,可在指定行的后面插入一行 点击红色-按钮,可以删除指定行 原理:表格 el-table 是通过动态循环 tableData 生成,只要对 tableData 数组进行增加删除元素,就可以达到效果 这里用了ele

    2024年02月16日
    浏览(62)
  • ant-design-vue表格Table行内新增、编辑、删除

    ant-design-vue表格Table进行单元格内新增、编辑、删除等操作 如图所示:

    2024年02月14日
    浏览(42)
  • 前端 富文本编辑器原理——从javascript、html、css开始入门

    大家好,我是yma16,本文分享关于前端 富文本编辑器原理——从javascript、html、css开始。 富文本编辑器 富文本编辑器是指具有格式化文本和图像编辑功能的文本编辑器 参考文档:https://w3c.github.io/selection-api/#abstract 全局属性 contenteditable 是一个枚举属性,表示元素是否可被用

    2024年02月08日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包