前言
element-uiu组件中关于表单动态创建已有详细介绍动态增减表单项,我们通过该介绍一步步向目标靠近;
利用表单动态删减
效果如下:
示例1
<template>
<div>
<h2 style="margin-bottom: 20px; margin-top: 20px">订单管理页面</h2>
<el-form :model="form" ref="form" label-width="80px" :inline="true">
<div v-for="(item, index) in form.dynamicItem" :key="index">
<el-form-item label="姓名" :prop="'dynamicItem.' + index + '.name'" :rules="{required: true, message: '姓名不能为空', trigger: 'blur'}">
<el-input v-model="item.name"></el-input>
</el-form-item>
<el-form-item label="手机号" :prop="'dynamicItem.' + index + '.phone'" :rules="[
{required: true, message: '手机号不能为空', trigger: 'blur'},
{ pattern: /^1[34578]\d{9}$/, message: '目前只支持中国大陆的手机号码' }]">
<el-input v-model="item.phone"></el-input>
</el-form-item>
<el-form-item label="地区" :prop="'dynamicItem.' + index + '.area'" :rules="{required: true, message: '地区不能为空', trigger: 'blur'}">
<el-input v-model="item.area"></el-input>
</el-form-item>
<el-form-item label="操作">
<el-button v-if="index+1 === form.dynamicItem.length" type="primary" @click="addItem(index)">增加</el-button>
<el-button type="info" @click="deleteItem(item, index)">删除</el-button>
</el-form-item>
</div>
</el-form>
</div>
</template>
<script>
export default {
name: 'Ordermanage',
data() {
return {
form: {
dynamicItem: [{
name: '',
phone: '',
area: ''
}]
}
}
},
methods: {
addItem(index) {
this.form.dynamicItem.push({
name: this.form.dynamicItem[index].name,
phone: this.form.dynamicItem[index].phone,
area: this.form.dynamicItem[index].area
})
},
deleteItem(item, index) {
this.form.dynamicItem.splice(index, 1)
}
}
}
</script>
注意
- 此处el-input中的v-model要写成item.key,若是写成了form.dynamicItem.key则变动一条数据,其余数据也会跟着改变;
- 此处新增按钮只出现在最新的一条数据上,若每行都有新增按钮,则要将v-if条件删掉,并且addItem方法也不能使用数组的push方法,应该使用数据任意位置插入方法;代码如下:
<el-form-item label="操作">
<el-button type="primary" @click="addItem(item, index)">增加</el-button>
<el-button type="info" @click="deleteItem(item, index)">删除</el-button>
</el-form-item>
addItem(val, index) {
this.form.dynamicItem.splice(index, 0, JSON.parse(JSON.stringify(val)))
},
- 删除按钮可设置第一行不可见或不可用,以防用户将模板行删掉;
<el-button v-if="index !== 0" type="info" @click="deleteItem(item, index)">删除</el-button>
或
deleteItem(item, index) {
if(index === 0) {
alert('第一行不可删除')
} else {
this.form.dynamicItem.splice(index, 1)
}
}
利用表格动态增减
上面用表单的方法虽然实现了我们的动态增减功能,但是表头标题每次复制时都会重现一行,有些冗余,基于此,如果我们利用表格形式,只复制表格内容,表头标题只出现一次,岂不美哉?
<template>
<div>
<h2 style="margin-bottom: 20px; margin-top: 20px">订单管理页面</h2>
<el-table :data="form.dynamicItem">
<el-table-column label="姓名">
<template slot-scope="scope">
<el-input size="mini" v-model="scope.row.name"></el-input>
</template>
</el-table-column>
<el-table-column label="手机号">
<template slot-scope="scope">
<el-input size="mini" v-model="scope.row.phone"></el-input>
</template>
</el-table-column>
<el-table-column label="地区">
<template slot-scope="scope">
<el-input size="mini" v-model="scope.row.area"></el-input>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" @click="addItem(scope.row, scope.$index)">新增</el-button>
<el-button type="info" @click="deleteItem(scope.row, scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
其余部分与表单方法一样;
结合表单与表格实现动态增减
上述方法虽然弥补了表单缺陷,但是表格组件中无对数据的校验,所以将二者进行结合如下:
示例如下:
示例2
<template>
<div>
<h2 style="margin-bottom: 20px; margin-top: 20px">订单管理页面</h2>
<el-form :model="form" ref="form" label-width="80px" :inline="true">
<el-table :data="form.dynamicItem">
<el-table-column label="姓名" align="center">
<template slot-scope="scope">
<el-form-item :prop="'dynamicItem.' + scope.$index + '.name'" :rules="{required: true, message: '姓名不能为空', trigger: 'blur'}">
<el-input v-model="scope.row.name"></el-input>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="手机号" align="center">
<template slot-scope="scope">
<el-form-item :prop="'dynamicItem.' + scope.$index + '.phone'" :rules="[
{required: true, message: '手机号不能为空', trigger: 'blur'},
{ pattern: /^1[34578]\d{9}$/, message: '目前只支持中国大陆的手机号码' }]">
<el-input v-model="scope.row.phone"></el-input>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="地区" align="center">
<template slot-scope="scope">
<el-form-item :prop="'dynamicItem.' + scope.$index + '.area'" :rules="{required: true, message: '地区不能为空', trigger: 'blur'}">
<el-input v-model="scope.row.area"></el-input>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-form-item>
<el-button type="primary" @click="addItem(scope.row, scope.$index)">增加</el-button>
<el-button type="info" @click="deleteItem(scope.row, scope.$index)">删除</el-button>
</el-form-item>
</template>
</el-table-column>
</el-table>
</el-form>
<div style="text-align: center">
<span slot="footer" class="dialog-footer">
<el-button type="primary" style="margin-left: -18px; margin-top: 20px" @click="saveItem()">保 存</el-button>
<el-button @click="cancleItem()">取 消</el-button>
</span>
</div>
</div>
</div>
</template>
复制表格文本自动解析数据
下面继续在该文件中新增功能,使其能够实现:粘贴excel文本中数据,复制到文本框中,即可实现自动解析到每行,功能实现如下所示:
示例3
代码实现如下:
<h3>复制文本于下方,实现自动解析</h3>
<el-input v-model="copy" type="text" class="copyInput" placeholder="复制表格内容并粘贴" @paste.native="paste" style="width: 500px; margin-bottom: 20px; margin-top: 20px"></el-input>
paste(e) {
const source = e.clipboardData.getData('Text')
// 首先对源头进行解析
const rows = source.split('\n') // 拆成很多行
const keys = Object.keys(this.form.dynamicItem[0]) // key的名
this.form.dynamicItem = [] // 将初始表格数据置空,否则会有一行空行
for (let i = 0; i < rows.length; i++) {
if (rows[i] !== '') {
// 如果某一行不是空,再按列拆分
const columns = rows[i].split('\t') // 已经按列划分
const dataone = {} // 声明一行数组
for (let j = 0; j < columns.length; j++) {
// 读取tableData里的key值
// 每一列对应数据传入dataone
dataone[keys[j]] = columns[j]
}
this.form.dynamicItem.push(dataone)
}
}
}
补充
splice可根据参数个数和形式的不同,实现删除指定元素或插入元素、替换元素等功能,只能用于数组,但是slice方法可用于数组和字符串,表示“切片”;
- 一个参数arr.splice(i)
参数只有一个的时候,表示删除数组中索引为i及i之后的所有元素。返回删除的元素,数组直接被修改
当i为非负整数时,表示删除数组中索引为i及i之后位置上所有的元素;
当i为负整数时,索引从后往前计算,最后一个索引是-1,倒数第二位是-2。以此类推。也是用于删除数组索引为i及之后的所有元素;
const arrdata = ['小A', '小B', '小C', '小D', '小E', '小F']
console.log(arrdata.splice(0), '看看删除的是啥') // ['小A', '小B', '小C', '小D', '小E', '小F']
console.log(arrdata, '看看arrdata是什么') // []
- 两个参数arr.splice(i, j)
有两个参数,要保证该两个参数必须是整数。表示从数组中索引为i开始删除,一共删除j个元素;
返回删除的元素,数组直接被修改
const arrdata = ['小A', '小B', '小C', '小D', '小E', '小F']
console.log(arrdata.splice(0, 2), '看看删除的是啥') // ['小A', '小B']
console.log(arrdata, '看看arrdata是什么') // ['小C', '小D', '小E', '小F']
- 三个参数arr.splice(i, j, e1, e2, ...)
i和j皆是整数,和上述要一样,i表示索引的起始位置,j表示删除的个数,e1、e2、...及之后的参数表示删除相应元素之后要添加的元素;返回删除的元素,数组直接被修改;
若j为0,表示一个元素也不删除,则元素从i前一个位置开始插入;
若j>0,表示从i位置开始(包括i位置),删除j个元素,然后从i后面开始插入;
- arr.slice(i, j)表示将数组/字符串从[i, j)切片,然后返回取出的片段,不改变原数组/字符串