多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
我们新建一个文章的添加与列表功能,当新建一篇文章时,让它所属设计和开发两个分类。大家可以根据此方法的制作过程,应用到其他功能模块中。 1.文章功能的所有页面创建 按照之前分类功能页面创建文章功能的所有页面。 (1)设置文章页面的路由 ![](https://img.kancloud.cn/a2/1a/a21a76557d5caf4fdbfa9745512de7b2_1490x936.png) (2)在主页面Main.vue组件的导航中加入文章页面的跳转按钮 ![](https://img.kancloud.cn/04/05/040555a6d25662f5ed1bfd86e5535d52_1490x936.png) 此时点击导航按钮就可以跳转了。 (3)创建文章页面-ArticleSet.vue组件 整体框架不变与CategorySet.vue相同,将除查询上级分类以外的接口名categories改为articles,上级分类parentOptions改成所属分类categories。 ``` <template> <div> <h1>{{id ? '编辑' : '创建'}}文章</h1> <el-form label-width="80px" style="margin-top:20px;" @submit.native.prevent="save"> <el-form-item label="所属分类"> <!-- 寻找上级分类categories --> <!-- 为了添加多个上级分类,需要在后边加一个multiple,就可以进行多选了。传输数据为数组格式 --> <el-select v-model="model.categories" multiple> <el-option v-for="item in categories" :key="item._id" :label="item.name" :value="item._id"></el-option> </el-select> </el-form-item> <el-form-item label="文章标题"> <el-input v-model="model.name"></el-input> </el-form-item> <el-form-item> <el-button type="primary" native-type="submit">保存</el-button> </el-form-item> </el-form> </div> </template> <script> export default { props: { id: {} }, data(){ return { model: {}, categories: [], } }, methods: { async save(){ let res if(this.id){ res = await this.$http.put('articles/' + this.id, this.model) }else{ res = await this.$http.post('articles', this.model) } console.log("en?",res) this.$router.push('/articles/list') this.$message({ type: 'success', message: '保存成功' }) }, async fetch(){ const res = await this.$http.get('articles/' + this.id) this.model = res.data }, async fetchCategories(){ const res = await this.$http.get('categories') this.categories = res.data } }, created(){ this.id && this.fetch() this.fetchCategories() } } </script> ``` ![](https://img.kancloud.cn/47/ff/47ffb85f1449a532e65df3430ff70c3e_1268x730.png) (4)文章列表页面-ArticleList.vue组件 ``` <template> <div> <h1>分类列表</h1> <el-table :data="items"> <el-table-column prop="_id" label="ID" width="220"> </el-table-column> <el-table-column prop="categories.name" label="所属分类"> </el-table-column> <el-table-column prop="categories[0].name,categories[1].name" label="所属分类"> <template slot-scope="scope"> {{scope.row.categories[0].name}},{{scope.row.categories[1].name}} </template> </el-table-column> <el-table-column prop="name" label="文章标题"> </el-table-column> <el-table-column fixed="right" label="操作" width="100"> <template slot-scope="scope"> <el-button type="text" size="small" @click="$router.push('/articles/edit/' + scope.row._id)">编辑</el-button> <el-button @click="remove(scope.row)" type="text" size="small">删除</el-button> </template> </el-table-column> </el-table> </div> </template> <script> export default { data() { return { items: [] } }, methods: { async fetch(){ const res = await this.$http.get('articles') this.items = res.data }, remove(row){ this.$confirm('是否确定要删除文章"' + row.name + '"?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(async () => { // 要想使用await,函数必须使用async // await异步执行,待调用接口获取数据完成后再将值传给res,进行下一步操作 const res = await this.$http.delete('articles/' + row._id) this.$message({ type: 'success', message: '删除成功!' }); if(res.status == 200){ // 接口调用成功后,刷新页面 this.fetch() } }).catch(() => { this.$message({ type: 'info', message: '已取消删除' }); }); } }, created() { this.fetch() } } </script> ``` ![](https://img.kancloud.cn/6f/d9/6fd974731687f1426f411be7ab4edae2_1268x730.png) (5)创建文章数据库模型Article.js server/models/Article.js: ``` // 引入mongoose插件,插件db.js已经用require引入到server的最高层文件index.js,所以可以直接引用 const mongoose = require('mongoose') // 使用mongoose的架构方法定义此数据表category,定义字段和类型 const schema = new mongoose.Schema({ name: { type: String }, // 因为以id为查询依据,故使用mongodb特有的类型架构————objectId。 // 并ref挂载到分类模型本身,指在分类模型Category中查找。 categories: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'Category' }], }) // 导出mongoose模型 module.exports = mongoose.model('Article', schema) ``` (6)文章功能接口 server/router/admin/index.js复制categories接口,改接口地址和接口名,引入Article模型 ![](https://img.kancloud.cn/1e/77/1e7786840f80cac974a7779e3ca8cc3b_1218x1185.png) 此时测试文章功能: ![](https://img.kancloud.cn/0d/a5/0da53b22e2b0d4663fb4fbf1b4799818_1268x730.png) ![](https://img.kancloud.cn/c5/5e/c55ed7e358ad047f4cffdb5676df7f21_1268x353.png) 没问题。 2.总结 (1)上传多个上级分类 multiple标签方法。以数组方式上传到数据库模型,模型中定义的字段和类型要用数组形式包括: ![](https://img.kancloud.cn/a8/13/a813d0aef4fefa00e57bfba3aff6c5c0_1218x710.png) (2)显示多个上级分类 el-table-column不能以数组方式显示在页面中,但可以使用prop将多个数据放在标签中,然后用vue的v-model双向绑定显示该行内包含的数据。 ![](https://img.kancloud.cn/cc/5c/cc5caea1fc05b04ffd80fdb9eccf7456_1218x710.png) 数据来源在vue.js devtools中层层查找。 ![](https://img.kancloud.cn/cd/76/cd76b7ebeecebb0dd7c66a43a98b8815_1268x730.png) (3)关于服务端接口的整合 目前服务器接口中,每增加一个模块功能就需要新添加一系列相似接口。 ![](https://img.kancloud.cn/1d/98/1d98fbc43029902250dba81c27b1d2e5_1218x1248.png) 所以下篇文章我们学习一下接口的整合:通用CRUD接口。将接口地址和接口名写成变量,服务端接收admin端传入的接口名赋值到接口变量中,以实现接口的复用,减轻服务端接口频繁杂乱的压力。