3-04-案例-Table案例

效果展示

创建项目

  1. 创建项目
1
2
3
4
5
6
7
8
9
npm init vite-app table

cd table

npm i

npm i less -D

npm i axios -S
  1. 设置全局样式

在index.css中:

1
2
3
4
5
6
7
8
9
10
11
:root {

font-size: 12px;

}

body {

padding: 5px;

}
  1. 引入Bootstrap.css

将Bootstrap.css复制到static/css文件夹下面

在main.js中:

1
import './static/css/Bootstrap.css';
  1. 封装axios

创建api/api.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import axios from 'axios';

axios.defaults.baseURL = 'https://www.escook.cn';

export const MyRequest;

在main.js中:

import { MyRequest } from './api/api.js';

const app = createApp(App);

app.config.globalProperties.$http = MyRequest;

app.mount('#app');

封装数据

在App.vue中:

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
<script>

export default {

data() {

return {

goodList: []

}

},

created() {

this.getGoodList();

},

methods: {

async getGoodList() {

const { data: res } = await this.$http.get('/api/goods');

if (res.status !== 0) return alert('商品列表获取失败!');

this.goodList = res.data;

}

}

}

</script>

创建组件MyTable.vue,注册到App.vue中,并传入数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>

<my-table :data="goodList"></my-table>

</template>

<script>

import MyTable from './components/MyTable.vue';

export default {

components: { MyTable }

}

</script>

实现header具名插槽

  1. 实现header
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>

<table>

<thead>

<tr>

<slot name="header"></slot>

</tr>

</thead>

<tbody></tbody>

</table>

</template>
  1. 在App.vue中渲染表头:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>

<my-table>

<template #header>

<th>序号</th>

<th>商品名称</th>

<th>价格</th>

<th>标签</th>

<th>操作</th>

</template>

</my-table>

</template>

实现body作用域插槽

  1. 实现body:
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
<template>

<table>

...

<tbody>

<tr v-for="item in data" :key="item.id">

<slot name="body" :item="item"></slot>

</tr>

</tbody>

</table>

</template>

<script>

export default {

props: {

data: {

type: Array,

required: true

}

}

}

</script>
  1. 在App.vue中渲染body
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
<template>

<my-table>

...

<template #body="{ item }">

<td>{{ item.id }}</td>

<td>{{ item.goods_name }}</td>

<td>¥{{ item.goods_price }}</td>

<td>

<input class="form-control form-control-sm form-ipt" type="text"
v-model.trim="item.inputValue" v-if="item.inputVisible" />

<button class="btn btn-primary btn-sm" v-else
@click="item.inputVisible = true">+Tag</button>

<div class="badge badge-warning tag" v-for="tag in item.tags"
:key="tag">{{ tag }}<div>

</td>

<td>

<button class="btn btn-danger btn-sm">删除</button>

</td>

</template>

</my-table>

</template>

<style>

.form-ipt {

width: 80px;

display: inline;

}

.tag {

margin: 0 4px;

}

</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
<template>

...

<button @click="onDelete(item.id)">...</button>

...

</template>

<script>

export default {

...

methods: {

onDelete(id) {

this.goodList = this.goodList.filter(x => x.id !== id);

}

}

}

</script>

## 实现显示组件获得焦点

<template>

...

<input ... v-focus />

...

</template>

<script>

export default {

directives: {

focus(el) {

el.focus();

}

}

}

</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
35
36
37
<template>

...

<input ... @blur="onAddTag(item)">

...

</template>

<script>

export default {

methods: {

onAddTag(item) {

const val = item.inputValue;

item.inputValue = '';

item.inputVisible = false;

// 检查是否重复

if (!val || item.tags.indexOf(val) !== -1) return;

item.tags.push(val);

}

}

}

</script>

添加按键功能

按下回车键添加标签,按下esc键清空输入框:

1
2
<input ... @keyup.enter="onAddTag(item)"
@keyup.esc="item.inputValue=''" />

参考:

Vue3.0-23.Table案例 -
介绍案例的效果以及主要实现步骤

Vue3.0-24.Table案例 -
初始化项目

Vue3.0-25.Table案例 -
请求商品列表的数据

Vue3.0-26.Table案例 -
封装my-table组件并声明data数据源

Vue3.0-27.Table案例 -
把表头区域封装为header具名插槽

Vue3.0-28.Table案例 -
把表格主体区域封装为body作用域插槽

Vue3.0-29.Table案例 -
实现删除商品的功能

Vue3.0-30.Table案例 -
循环渲染Tag标签

Vue3.0-31.Table案例 -
实现input和button的按需显示

Vue3.0-32.Table案例 -
实现文本框自动获得焦点的功能

Vue3.0-33.Table案例 -
文本框失去焦点自动隐藏

Vue3.0-34.Table案例 -
实现新增Tag标签的功能


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!