table案例
星月 8/23/2022 vue
# table案例
# 实现步骤
① 搭建项目的基本结构
② 请求商品列表的数据
③ 封装 MyTable 组件
④ 实现删除功能
⑤ 实现添加标签的功能
# 1. 搭建项目基本结构
# 1.1 初始化项目
- 在终端运行如下的命令,初始化 vite 项目:
npm init vite-app table-demo
1
- cd 到项目根目录,安装依赖项:
npm install
1
- 安装 less 依赖包:
npm i less -D
1
- 使用 vscode 打开项目,并在 vscode 集成的终端下运行如下的命令,把项目运行起来:
npm run dev
1
5.安装 axios:
npm install axios@0.21.0 -S
1
# 1.2 梳理项目结构
# 2. 代码部分
main.js 代码:
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'
import './assets/css/bootstrap.css'
import './index.css'
// 配置axios请求根路径
axios.defaults.baseURL = 'https://www.escook.cn'
const app = createApp(App)
// 将axios挂载到全局
app.config.globalProperties.$http = axios
app.mount('#app')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
index.css 代码:
:root {
font-size: 12px;
}
body {
padding: 8px;
}
1
2
3
4
5
6
2
3
4
5
6
MyTable 组件的封装要求 :
用户通过名为 data 的 prop 属性,为 MyTable.vue 组件指定数据源
在 MyTable.vue 组件中,预留名称为 header 的具名插槽
在 MyTable.vue 组件中,预留名称为 body 的作用域插槽
MyTable.vue 代码:
<template>
<div>MyTable 组件</div>
<div>
<table class="table table-striped">
<thead>
<tr>
<slot name="header"></slot>
</tr>
</thead>
<tbody>
<tr v-for="(item , index) in data" :key="item.id">
<!-- 为数据行的 td 预留的“作用域插槽” -->
<slot name="body" :row="item" :index="index"></slot>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
name: "MyTable",
props: {
// 表格的数据源
data: {
type: Array,
default: [],
require: true,
},
},
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
app.vue 代码:
<template>
<h2>app根组件</h2>
<MyTable :data="tablelist">
<template #header>
<th>#</th>
<th>商品名称</th>
<th>价格</th>
<th>标签</th>
<th>操作</th>
</template>
<template #body="{row,index}">
<td>{{ index + 1 }}</td>
<td>{{ row.goods_name }}</td>
<td>¥{{ row.goods_price }}</td>
<td class="mytags">
<!-- 循环渲染标签信息 -->
<input
type="text"
class="form-control form-control-sm ipt-tag"
v-focus
v-if="row.inputVisible"
v-model.trim="row.inputValue"
@blur="onInputConfirm(row)"
@keyup.enter="onInputConfirm(row)"
@keyup.esc="row.inputValue = ''"
>
<button type="button" class="btn btn-primary btn-sm" v-else @click="row.inputVisible = true">+Tag</button>
<span class="badge badge-warning ml-2" v-for="item in row.tags" :key="item">{{ item }}</span>
</td>
<td>
<button type="button" class="btn btn-danger btn-sm" @click="onRemove(row.id)">删除</button>
</td>
</template>
</MyTable>
</template>
<script>
import MyTable from './components/my-table/MyTable.vue'
export default {
name:'MyApp',
components:{
MyTable
},
data(){
return{
tablelist:[]
}
},
created(){
this.getlist()
},
methods: {
async getlist(){
const {data:res} = await this.$http('/api/goods')
if(res.status!==0)return console.log('获取列表数据失败!')
this.tablelist = res.data
},
// 删除功能
onRemove(id){
this.tablelist = this.tablelist.filter(x=>x.id !== id)
},
onInputConfirm(row){
// 1. 把用户在文本框中输入的值,预先转存到常量 val 中
const vla = row.inputValue
// 2. 清空文本框的值
row.inputValue = ''
// 3. 隐藏文本框
row.inputVisible = false
// 1.1 判断 val 的值是否为空,如果为空,则不进行添加
// 1.2 判断 val 的值是否已存在于 tags 数组中,防止重复添加
if(!vla || row.tags.indexOf(vla) !== -1) return
// 2. 将用户输入的内容,作为新标签 push 到当前行的 tags 数组中
row.tags.push(vla)
}
},
directives:{
focus(el){
el.focus()
}
}
}
</script>
<style lang="less" scoped>
.mytags{
display: flex;
}
.form-control{
width: 80px;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# 3. 功能演示
实现删除功能,单机即可删除当前项
实现添加标签的功能
回车或者input输入框失去焦点都判断,vla不为空,或者不重复,就添加到标签。
input失去焦点,标签添加,展示+Tag按钮。