我们以之前做的后台文章管理模块为例,实现组件拆分、组件之间互相传值、方法调用、代码封装等功能。
准备工作
在 src/componments
里面新建 articles
文件夹,用于存放我们拆分出来的子组件。
拆分面包屑
1、在 src/componments/articles
里面新建 BreadComponent.vue
组件
<template>
<div>
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item><a href="/">新闻管理</a></el-breadcrumb-item>
<el-breadcrumb-item>新闻列表</el-breadcrumb-item>
</el-breadcrumb>
<el-divider></el-divider>
</div>
</template>
2、在 views/articles/ListView.vue
中
<template>
<div>
<!--面包屑-->
<Bread />
.
.
</div>
</template>
<script>
import Bread from "@/components/articles/BreadComponent";
.
.
export default {
components: {
Bread,
},
.
.
}
</script>
拆分工具栏
1、在 src/componments/articles
里面新建 ToolsComponent.vue
组件
<template>
<div class="controls">
<!--通过 $parent 方法访问父组件的 showCreateForm 方法-->
<el-button type="primary" @click="$parent.showCreateForm">新增</el-button>
<!--通过 $parent 方法访问父组件的 handleMultipleDelete 方法-->
<el-popconfirm
title="确定要批量删除吗?"
@confirm="$parent.handleMultipleDelete"
>
<el-button type="danger" slot="reference">批量删除</el-button>
</el-popconfirm>
</div>
</template>
2、在 views/articles/ListView.vue
中
<template>
<div>
.
.
<!--工具栏-->
<Tools />
.
.
</div>
</template>
<script>
.
.
import Tools from "@/components/articles/ToolsComponent";
.
.
export default {
components: {
.
.
Tools,
},
.
.
methods:{
// 显示新增表单
showCreateForm() {},
// 批量删除
handleMultipleDelete() {
const length = this.multipleSelection.length;
if (length == 0) {
this.$message.error("你必须选择一条以上记录后,再做操作!");
return;
}
const checkedId = this.multipleSelection.map((item) => {
return item.id;
});
this.$confirm("此操作将删除到回收站, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(async () => {
const res = await multipleDeleteArticle({ checkedId: checkedId });
console.log(res);
});
},
}
}
</script>
拆分搜索框
1、在 src/componments/articles
里面新建 SearchComponent.vue
组件
<template>
<div>
<!--通过 $parent 方法调用父组件的 searchData 属性和 init 方法-->
<el-form
:inline="true"
:model="$parent.searchData"
class="demo-form-inline"
>
<el-form-item label="标题">
<el-input
v-model="$parent.searchData.title"
placeholder="请填写标题"
clearable
@clear="$parent.init"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSearch">查询</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
methods: {
// 绑定点击查询按钮执行搜索
onSearch() {
// 通过 $emit 方法 访问父组件自定义的 handleSearch 事件
this.$emit("handleSearch");
},
},
};
</script>
2、在 views/articles/ListView.vue
中
<template>
<div>
.
.
<!--搜索:绑定子组件需要的自定义事件-->
<Search @handleSearch="init" />
.
.
</div>
</template>
<script>
.
.
import Search from "@/components/articles/SearchComponent";
.
.
export default {
components: {
.
.
Search,
},
.
.
}
</script>
拆分表格
1、在 src/componments/articles
里面新建 TableComponent.vue
组件
<template>
<div>
<el-card>
<el-table
v-loading="loading"
ref="multipleTable"
:data="articles"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column label="编号" prop="id"></el-table-column>
<el-table-column prop="title" label="标题"></el-table-column>
<el-table-column label="创建时间">
<template slot-scope="scope">{{
scope.row.createdAt | dateFormat
}}</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" @click="handleEdit(scope.row)"
>编辑</el-button
>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<div class="block" style="margin-top: 20px">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pagination.currentPage"
:page-sizes="[10, 20, 30, 40]"
:page-size="pagination.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total"
>
</el-pagination>
</div>
</el-card>
</div>
</template>
2、在 views/articles/ListView.vue
中
.
.
<!--表格:通过属性 articles 把获取到的 tableData 的数据传给子组件,pagination亦同。通过 tef 给表格起个名字叫 myTable-->
<Table ref="myTable" :articles="tableData" :pagination="pagination" />
.
.
表格虽然拿过来了,但是我们要确认几个东西,这些变量或方法都是缺一不可的,如:
- articles
- handleSelectionChange
- handleSizeChange
- handleCurrentChange
- pagination.currentPage
- pagination.pageSize
- pagination.total
所以 js
部分代码如下:
<script>
export default {
// 接收父组件传过来的属性
props: ["articles", "pagination"],
data() {
return {
multipleSelection: [],
};
},
methods: {
handleSelectionChange(val) {
this.multipleSelection = val;
},
handleSizeChange(val) {
this.searchData.pageSize = val;
this.init();
},
handleCurrentChange(val) {
this.searchData.currentPage = val;
this.init();
},
},
};
</script>
最终 TableComponent.vue
代码,如下
<template>
<div>
<el-card>
<el-table
v-loading="$parent.loading"
ref="multipleTable"
:data="articles"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column label="编号" prop="id"></el-table-column>
<el-table-column prop="title" label="标题"></el-table-column>
<el-table-column label="创建时间">
<template slot-scope="scope">{{
scope.row.createdAt | dateFormat
}}</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" @click="handleEdit(scope.row)"
>编辑</el-button
>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.row)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<div class="block" style="margin-top: 20px">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pagination.currentPage"
:page-sizes="[10, 20, 30, 40]"
:page-size="pagination.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total"
>
</el-pagination>
</div>
</el-card>
</div>
</template>
<script>
import { deleteArticle, multipleDeleteArticle } from "@/api/articles";
export default {
props: ["articles", "pagination"],
data() {
return {
multipleSelection: [],
};
},
methods: {
handleSizeChange(val) {
this.$parent.pagination.pageSize = val;
this.$parent.init();
},
handleCurrentChange(val) {
this.$parent.pagination.currentPage = val;
this.$parent.init();
},
// 删除单条
async handleDelete(row) {
const res = await deleteArticle(row.id);
this.$message.success(res.message);
this.$parent.init();
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
async multipleDelete() {
const length = this.multipleSelection.length;
if (length == 0) {
this.$message.error("你必须选择一条以上记录后,再做操作!");
return;
}
const checkedId = this.multipleSelection.map((item) => {
return item.id;
});
this.$confirm("此操作将删除到回收站, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(async () => {
const res = await multipleDeleteArticle(checkedId);
this.$message.success(res.message);
this.$parent.init();
});
},
},
};
</script>
首页增加如下方法
// 批量删除,调用子组件的方法
handleMultipleDelete() {
this.$refs.myTable.multipleDelete();
},