Vue实战【封装一个简单的列表组件,实现增删改查】
文章目录
- 🌟前言
- 🌟table组件封装
- 🌟父组件(展示表格的页面)
- 🌟控制台查看父子组件通信是否成功
- 🌟Vue2父子组件传递参数
- 🌟写在最后
- 🌟JSON包里写函数,关注博主不迷路
🌟前言
大家好,上一期的Vue实战都阅读了吗?上一期主要是对Vuex的一个基本操作,通过Vuex我们可以实现全局的状态(数据)共享,以便与我们更好的实现一些需求。
不知道大家在日常工作当中是否被频繁的列表增删改查困扰,功能很简单但确实是非常繁琐的一项工作;今天这一期呢我会从Vue2父子组件如何传值并结合Element来封装一个简单的列表组件;一次封装,多次复用。
🌟table组件封装
在你的component目录下创建一个Table.vue:
<template>
<el-card class="box-card" style="width: 100%;height: 100%">
<div class="btnBox">
<el-button v-for="(item,index) in tableOperation" :key="index" :type="item.type" size="small" @[eventName]="handleClick(item.fun, multipleSelection)">{{ item.label }}</el-button>
</div>
<el-table
style="margin-bottom: 20px"
:data="tableData"
size="small"
row-class-name="row"
cell-class-name="column"
:highlight-current-row="true"
fit
@selection-change="handleSelectionChange"
>
<!--这是是为了将表格设置成带有选择框的表格-->
<el-table-column
type="selection"
width="55"
/>
<el-table-column
v-for="(item, index) in tableLabel"
:key="index"
align="center"
:prop="item.prop"
:width="item.width"
:label="item.label"
/>
</el-table>
<div class="block" style="text-align: end">
<el-pagination
background
:current-page="1"
:page-sizes="[10, 20, 30, 40]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="tableData.length"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</el-card>
</template>
<script>
export default {
name: 'Table',
// 因为是子组件,要接受父组件传递的数据,所以这里我们定义props
props: {
tableData: { // 父组件传递过来的表格数据
type: Array,
default: () => {
return []
}
},
tableLabel: { // 父组件传递过来的表头数据
type: Array,
default: () => {
return []
}
},
tableOperation: { // 父组件传递过来的操作按钮数据
type: Array,
default: () => {
return []
}
}
},
data() {
return {
eventName: 'click', // 点击按钮绑定的方法,这样写法也可以去绑定一些其他的比如change等方法
multipleSelection: [] // 这个数组用来保存被选择行的数据,顺序是按照你勾选的顺序来排序的
}
},
methods: {
// @selection-change方法可以监听到表格里哪一行被选中,类型是数组;
// 然后我们将它赋值给定义好的 multipleSelection
handleSelectionChange(val) {
this.multipleSelection = val
},
// 动态绑定操作按钮的点击事件(按钮是父组件传递过来循环出来的,所以我们给按钮定义一个方法)
// 接收两个参数,一个是fun(string类型),一个是row(array类型,也就是我们选中行的数据)
// 这里的某个按钮时传递的参数
// 比如我点击的是编辑,那这时的fun就是 'edit',执行的方法就是下边的this.edit(row)
handleClick(fun,row) {
this[fun](row)
},
edit(row) {
if (!row.length) {
this.$message.error('请勾选数据后操作')
return false
} else if (row.length > 2) {
this.$message.error('当前仅支持单条数据操作')
return false
} else {
console.log('子组件点击编辑,触发父组件方法;并传递数据', row)
// 通过$meit通知父组件propClick方法,并传递两个参数:'edit'和row
this.$emit('propClick', 'edit', row)
}
},
look(row) {
if (!row.length) {
this.$message.error('请勾选数据后操作')
return false
} else if (row.length > 2) {
this.$message.error('当前仅支持单条数据操作')
return false
} else {
console.log('子组件点击查看,触发父组件方法;并传递数据', row)
// 通过$meit通知父组件propClick方法,并传递两个参数:'edit'和row
this.$emit('propClick', 'look', row)
}
},
delete(row) {
if (!row.length) {
this.$message.error('请勾选数据后操作')
return false
} else if (row.length > 2) {
this.$message.error('当前仅支持单条数据操作')
return false
} else {
console.log('子组件点击删除,触发父组件方法;并传递数据', row)
// 通过$meit通知父组件propClick方法,并传递两个参数:'edit'和row
this.$emit('propClick', 'del', row)
}
},
handleSizeChange(val) {
console.log(`每页 ${val} 条`)
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`)
}
}
}
</script>
<style scoped>
</style>
table组件封装好了,就可以在父组件里使用啦。
🌟父组件(展示表格的页面)
创建一个父组件(也就是你的页面),我这里起名index.vue大家可以随意;
<template>
<div v-loading="tableLoading" class="dashboard-container">
<!--子组件位置-->
<!--自定义table-data,table-label,table-operation三个属性,分别传递我们需要的数据-->
<!--自定义@propClick方法,用来接收子组件的通知并执行定义的btnClick方法-->
<myTable
:table-data="tableData"
:table-label="tableLabel"
:table-operation="tableOperation"
@propClick="btnClick" />
</div>
</template>
<script>
import { mapGetters } from 'vuex'
// 根据你的table组件引入到父组件里
import myTable from '@/components/Table/table'
export default {
name: 'Dashboard',
// 并在父组件的compoments里边注册
components: {
myTable
},
computed: {
...mapGetters([
'name'
])
},
// eslint-disable-next-line vue/order-in-components
data() {
return {
tableLoading: true,
// 子组件的表格数据
tableData: [
{ id: 1, date: '2018-07-24', sales: 23.34, sale: 137597.76, const: 102203.71, profit: 35394.05 },
{ id: 2, date: '2018-07-24', sales: 23.34, sale: 137597.76, const: 102203.71, profit: 35394.05 },
{ id: 3, date: '2018-07-24', sales: 23.34, sale: 137597.76, const: 102203.71, profit: 35394.05 },
{ id: 4, date: '2018-07-24', sales: 23.34, sale: 137597.76, const: 102203.71, profit: 35394.05 },
{ id: 5, date: '2018-07-24', sales: 23.34, sale: 137597.76, const: 102203.71, profit: 35394.05 },
{ id: 6, date: '2018-07-24', sales: 23.34, sale: 137597.76, const: 102203.71, profit: 35394.05 },
{ id: 7, date: '2018-07-24', sales: 23.34, sale: 137597.76, const: 102203.71, profit: 35394.05 },
{ id: 8, date: '2018-07-24', sales: 23.34, sale: 137597.76, const: 102203.71, profit: 35394.05 },
{ id: 9, date: '2018-07-24', sales: 23.34, sale: 137597.76, const: 102203.71, profit: 35394.05 },
{ id: 10, date: '2018-07-24', sales: 23.34, sale: 137597.76, const: 102203.71, profit: 35394.05 },
{ id: 11, date: '2018-07-24', sales: 23.34, sale: 137597.76, const: 102203.71, profit: 35394.05 },
{ id: 12, date: '2018-07-24', sales: 23.34, sale: 137597.76, const: 102203.71, profit: 35394.05 }
],
// 子组件的表头数据
tableLabel: [
{ label: 'ID', width: '40', prop: 'id' },
{ label: '日期', width: '', prop: 'date' },
{ label: '销售量', width: '', prop: 'sales' },
{ label: '销售额', width: '', prop: 'sale' },
{ label: '成本', width: '', prop: 'const' },
{ label: '利润', width: '', prop: 'profit' }
],
// 子组件的操作按钮
tableOperation: [
{ label: '编辑', fun: 'edit', type: 'primary' },
{ label: '查看', fun: 'look', type: 'success' },
{ label: '删除', fun: 'delete', type: 'danger' }
]
}
},
mounted() {
setTimeout(() => {
this.tableLoading = false
this.$message.success('数据加载成功')
}, 1000)
},
methods: {
// 当父组件接收到了子组件this.$emit的通知后就会执行这个方法来接收子组件点击传递过来的数据
btnClick(fun, row) {
if (fun === 'edit') {
console.log('子组件点击了编辑,父组件收到子组件传递的数据', row)
} else if (fun === 'look') {
console.log('子组件点击了查看,父组件收到子组件传递的数据', row)
} else if (fun === 'del') {
console.log('子组件点击了删除,父组件收到子组件传递的数据', row)
}
}
}
}
</script>
<style lang="scss" scoped>
.dashboard {
&-container {
/*width: 100%;*/
margin: 30px;
height: 88vh;
}
&-text {
font-size: 30px;
line-height: 46px;
}
}
</style>
🌟控制台查看父子组件通信是否成功
列表增删改查
🌟Vue2父子组件传递参数
接下来我们来复习一下父子组件传递参数的方法吧
父组件向子组件传递数据:
父组件通过 props 给子组件下发数据
- 在父组件内为子组件添加自定义属性,例如我上边的table-data,table-label,table-operation三个属性,并为其绑定数据;如果是动态绑定就需要加上 :,反则不用加。
- 子组件内通过定义props来接受数据;并且有以下几个参数配置;
属性 | 值 | 说明 |
---|---|---|
type | 原生构造器 | 参数的类型 |
default | any | 参数的默认值,数组/对象的默认值应当由一个工厂函数返回 |
required | true/false | 参数是否必传 |
validator | function | 自定义验证函数 |
Vue.component('example', {
props: {
// 基础类型检测 (`null` 指允许任何类型)
propA: Number,
// 可能是多种类型
propB: [String, Number],
// 必传且是字符串
propC: {
type: String,
required: true
},
// 数值且有默认值
propD: {
type: Number,
default: 100
},
// 数组/对象的默认值应当由一个工厂函数返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
},
propG: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
子组件向父组件传递数据:
子组件通过事件给父组件发送消息
每个 Vue 实例都实现了事件接口,即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName, optionalPayload) 触发事件
1. 主要方法在父组件里。
2. 在父组件里添加自定义事件,自定义事件触发执行主要方法。
3. 在子组件里写一个通知方法( this.$emit(‘自定义事件’,参数) )用来告诉父组件执行自定义事件。
4. 在需要触发这个事件的元素上添加触发事件(例:@click=“子组件里的通知方法”)
<!-- 子组件 -->
<template>
<el-card class="box-card" style="width: 100%;height: 100%">
<div class="btnBox">
<el-button
v-for="(item,index) in tableOperation"
:key="index"
:type="item.type"
size="small"
@click="handleClick(item.fun, multipleSelection)">{{ item.label }}
</el-button>
</div>
</el-card>
</template>
<script>
export default {
name: 'Table',
methods: {
add(row) {
console.log('子组件点击新增,触发父组件里的自定义事件-propClick')
this.$emit('propClick', 'add')
}
}
}
</script>
<style scoped>
</style>
<!-- 父组件 -->
<template>
<div v-loading="tableLoading" class="dashboard-container">
<myTable @propClick="btnClick" />
</div>
</template>
<script>
import myTable from '@/components/Table/table'
export default {
name: 'Dashboard',
components: {
myTable
},
methods: {
//自定义事件-propClick触发该方法, 接收子组件点击按钮数据
btnClick(fun, row) {
if (fun === 'edit') {
console.log('子组件点击了编辑,父组件收到子组件传递的数据', row)
// 这里就可以去写我们需要调用的接口呀,数据处理逻辑呀等等
} else if (fun === 'look') {
console.log('子组件点击了查看,父组件收到子组件传递的数据', row)
// 这里就可以去写我们需要调用的接口呀,数据处理逻辑呀等等
} else if (fun === 'del') {
console.log('子组件点击了删除,父组件收到子组件传递的数据', row)
// 这里就可以去写我们需要调用的接口呀,数据处理逻辑呀等等
}
}
}
}
</script>
🌟写在最后
这篇文章通过父子组件通信并结合Element封装了一个简单的增删改查列表组件,你是否学会了呢?很多复杂的功能都是通过基础知识举一反三得来的,小伙伴一定记的尝试哦。后续会为小伙伴们持续更新Vue的一些实战小魔法!各位小伙伴让我们 let’s be prepared at all times!
🌟JSON包里写函数,关注博主不迷路
✨原创不易,还希望各位大佬支持一下!
👍 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富!