elastic-list
特性
- 支持数据双向绑定
v-model
- 适配 element-ui 的
el-table
- 支持 JSON 数组(
[{}, {}]
)和原始类型数组([1, 2]
) - 支持对行进行新增、删除、拖拉拽排序
- 支持对行的数量上限、下限进行限制
- 自定义新增元素的默认值
- 全局或局部引入,参数支持全局或局部配置
element-ui 集成说明:
- element-ui 是以外置依赖的方式引入的 所以不必担心代码体积和版本不一致等问题
- 集成风格是非侵入式的
- 支持
el-table
的所有参数(且可全局配置) - 支持
el-table
的所有事件 - 支持
el-table
的所有slot el-table-column
以slot形式传入
- 适配 element-ui 的
el-form
组件 支持 el-form
的全局 disabled
安装
npm add elastic-list
import 'elastic-list/dist/style.css'
import ElasticList from 'elastic-list'
components: { ElasticList }
Vue.use(ElasticList)
示例
Example for el-table
<ElasticList v-model="value" :elTableProps="{}">
<el-table-column label="姓名" prop="name"/>
<el-table-column label="年龄" prop="age"/>
</ElasticList>
自定义操作列和添加按钮:
<ElasticList v-model="value">
<el-table-column label="姓名" prop="name"/>
<el-table-column label="年龄" prop="age"/>
<template #operation-column="{showDeleteButton,deleteRow}">
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button>其他按钮</el-button>
<el-button
type="danger"
circle
icon="el-icon-delete"
@click="() => { deleteRow(scope.$index) }"
v-show="showDeleteButton"
/>
</template>
</el-table-column>
</template>
<template v-slot:add-row-trigger="{addRow}">
<el-button @click="addRow">增加一行</el-button>
</template>
</ElasticList>
Example for lists
reference-type array:
<el-form :model="form">
<ElasticList v-model="form.list">
<template v-slot="{item,index,showDeleteButton,deleteRow}">
<div>
<i
class="el-icon-circle-close"
@click="deleteRow(index)"
v-show="showDeleteButton"
/>
<el-form-item label="名称" :prop="'list.' + index + '.name'">
<el-input v-model="item.name"/>
</el-form-item>
<el-form-item label="排序" :prop="'list.' + index + '.sort'">
<el-input-number v-model="item.sort"/>
</el-form-item>
</div>
</template>
</ElasticList>
</el-form>
value-type array:
<ElasticList v-model="value">
<template v-slot="{item,index,showDeleteButton,deleteRow}">
<div>
<el-input v-model="value[index]"/>
<i v-show="showDeleteButton" class="el-icon-circle-close" @click="deleteRow(index)"/>
</div>
</template>
<template v-slot:add-row-trigger="{addRow}">
<el-button @click="addRow">自定义增加行按钮</el-button>
</template>
</ElasticList>
Props
参数名 | 说明 | 类型 | 合法值 | 默认值 |
---|
v-model / value | 列表绑定值 | array | | |
elTableProps | el-table 配置 | object | | |
sortable | 是否开启拖拉拽排序 | boolean | | true |
disabled | 禁用模式下无法新增、删除、排序 | boolean | | false |
count | 行数限制 | number, [number, number] | | |
defaultRowValue | 新增行的默认值 | (item: any, index: number) => any | | {} / '' |
... | sortablejs 配置 | | | |
elTableProps
默认值:
{
border: true,
fit: true,
stripe: true,
highlightCurrentRow: true,
}
配置方式:与默认值 进行混入
sortablejs 配置
默认值:
{
filter: 'input,textarea,.el-rate',
preventOnFilter: false,
animation: 500,
}
配置方式:与默认值 进行混入
count
比如你想限制不能超过5行:
Vue.use(ElasticList, {
count: 5
})
如果你还想限制不能低于2行:
Vue.use(ElasticList, {
count: [2, 5]
})
defaultRowValue
如果没有指定,则会根据value的值推断使用 {}
或 ''
可以手动指定,支持 Function,Function 的返回值将作为新增项
组件内部会对其进行深拷贝
Vue.use(ElasticList, {
defaultRowValue (i) {
return i
}
})
Slots
名称 | 说明 |
---|
add-row-trigger | 增加行的触发按钮 |
operation-column | el-table 最后一列(用于删除行等操作) |
placeholder | value 为空时的占位符 |
... | el-table 所有 slot |
Events
- 支持 sortablejs 所有事件
- 支持
el-table
所有事件
<ElasticList
@select="onSelect"
@sort="onSort"
>
</ElasticList>
拖动触发范围
默认是整行均可以拖动 如果你想要指定触发元素:
<ElasticList v-model="value" handle=".handle">
<el-table-column type="index">
<template slot-scope="scope">
<span class="handle">
{{ '# ' + (scope.$index + 1) }}
</span>
</template>
</el-table-column>
<el-table-column label="姓名" prop="name"/>
</ElasticList>
由于在输入框内拖动时,用户的用意往往是选中输入内容而不是拖动排序,所以默认在输入框内不触发排序(可配置)
value 监听
组件内不会监听非对象数组类型 value 的后续变化 如果 value 在初始化后需要修改,可使用以下方式:
为什么?
- 如果数组元素被绑定到输入框之类的可以在界面上直接编辑的地方 每次输入都会触发重绘 导致无法连续输入
<template>
<div>
<ElasticList
ref="elasticList"
>
</ElasticList>
</div>
</template>
<script>
export default {
created () {
this.$POST().then(res => {
this.$refs.elasticList.setValue(res.data)
})
},
}
</script>
或者
<template>
<div>
<ElasticList
v-model="value"
v-if="loading"
>
</ElasticList>
</div>
</template>
<script>
export default {
data () {
return {
value: [],
loading: true
}
},
created () {
this.$POST()
.then(res => {
this.value = res.data
})
.finally(() => {
this.loading = false
})
},
}
</script>