【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台

本项目是 学习Bilibili 全栈之巅 视频教程相关源码和体会
https://gitee.com/blaunicorn/node-vue-wangzherongyao
持续更新中…

2.10 英雄管理,比较复杂的英雄编辑页面

2.10.1 admin端Main.vue中创建英雄列表组(admin\src\views\Main.vue)

        <el-menu-item-group><template slot="title">英雄</template><el-menu-item index="/heroes/create">新建英雄</el-menu-item><el-menu-item index="/heroes/list">英雄列表</el-menu-item></el-menu-item-group>

2.10.2 新建HeroList.vue和HeroEdit.vue,并在route中增加路由

// admin\src\views\HeroEdit.vue<template><div class="about"><h1>{{id ? "编辑":"新建"}}英雄</h1><el-form label-width="120px" @submit.native.prevent="save"><el-form-item label="名称" ><el-input v-model="model.name"></el-input></el-form-item><el-form-item label="头像" ><!-- :action:表单提交地址,on-success:成功之后做什么,before-upload:上传之后做什么 --><el-uploadclass="avatar-uploader":action="$http.defaults.baseURL + '/upload'":show-file-list="false":on-success="afterUpload"><!-- 有图片显示图片,没有则显示上传图标,:src显示的图片 --><img v-if="model.avatar" :src="model.avatar" class="avatar"><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload></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:{name: '',avatar: ''},}},methods:{afterUpload(res){console.log(res)//vue提供的方法(赋值主体,赋值的属性,res.url),效果类似this.model.icon = res.url// this.$set(this.model,'avatar',res.url)//上面data中设置了属性就可以用这个方法了,推荐使用this.model.avatar = res.url},async save(){if(this.id){this.$http.put(`/rest/heroes/${this.id}`,this.model)}else{this.$http.post('/rest/heroes',this.model)}this.$router.push('/heroes/list')this.$message({type:'success',message:'保存成功'})},async fetch(){const res = await this.$http.get(`/rest/heroes/${this.id}`)this.model = res.data},async fetchParents(){const res = await this.$http.get(`/rest/items`)this.parents = res.data}},created(){this.fetchParents()this.id && this.fetch()}
}
</script><style>.avatar-uploader .el-upload {border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;}.avatar-uploader .el-upload:hover {border-color: #409EFF;}.avatar-uploader-icon {font-size: 28px;color: #8c939d;width: 178px;height: 178px;line-height: 178px;text-align: center;}.avatar {width: 178px;height: 178px;display: block;}
</style>
// admin\src\views\HeroList.vue
<template><div class="about"><h1>英雄列表</h1><el-table :data="items"><el-table-column prop="_id" label="ID" width="230"></el-table-column><el-table-column prop="name" label="名称"></el-table-column><el-table-column prop="avatar" label="头像"><template slot-scope="scope"><img :src="scope.row.avatar" alt="" style="height:3rem"></template></el-table-column><el-table-columnfixed="right"label="操作"width="100"><template slot-scope="scope"><el-button @click="$router.push(`/heroes/create/${scope.row._id}`)" type="text" size="small">编辑</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('/rest/heroes')this.items = res.data},async remove(row){this.$confirm(`是否要删除分类${row.name}`, '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(async() => {await this.$http.delete(`/rest/heroes/${row._id}`)this.$message({type: 'success',message: '删除成功!'});this.fetch()})}},created(){this.fetch()}
}
</script>

2.10.3 路由中引用HeroList.vue和HeroEdit.vue

// admin\src\router\index.js
import HeroEdit from '../views/HeroEdit.vue'
import HeroList from '../views/HeroList.vue'{path:'/heroes/create',component:HeroEdit},{path:'/heroes/List',component:HeroList},{path:'/heroes/create/:id',component:HeroEdit,props:true}

2.10.4、添加英雄模型Hero.js

// server\models\Hero.js
const mongoose = require('mongoose')const schema = new mongoose.Schema({name:{type:String},avatar:{type:String},title:{type:String},// 实现多选categories:[{type:mongoose.SchemaTypes.ObjectId,ref:'Category'}],// 评分scores:{difficult:{type:Number},skills:{type:Number},attack:{type:Number},survive:{type:Number}},// 多个技能skills:[{icon:{type:String},name:{type:String},description:{type:String},tips:{type:String}}],// 装备items1:[{type:mongoose.SchemaTypes.ObjectId,ref:'Item'}],items2:[{type:mongoose.SchemaTypes.ObjectId,ref:'Item'}],//使用技巧usageTips:{type:String},//对抗技巧battleTips:{type:String},//团战技巧teamTips:{type:String},//英雄关系partners:[{hero:{type:mongoose.SchemaTypes.ObjectId,ref:'Hero'},description:{type:String}}]
})module.exports = mongoose.model('Hero',schema)

2.10.5 实现复杂的英雄编辑录入页(HeroEdit.vue) (关联,多选,el-select, multiple)

<template><div class="about"><h1>{{id ? "编辑":"新建"}}英雄</h1><el-form label-width="120px" @submit.native.prevent="save"><el-form-item label="名称" ><el-input v-model="model.name"></el-input></el-form-item><el-form-item label="称号" ><el-input v-model="model.title"></el-input></el-form-item><el-form-item label="头像" ><!-- :action:表单提交地址,on-success:成功之后做什么,before-upload:上传之后做什么 --><el-uploadclass="avatar-uploader":action="$http.defaults.baseURL + '/upload'":show-file-list="false":on-success="afterUpload"><!-- 有图片显示图片,没有则显示上传图标,:src显示的图片 --><img v-if="model.avatar" :src="model.avatar" class="avatar"><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload></el-form-item><el-form-item label="类型" ><!-- 加multiple就可以多选 --><el-select v-model="model.categories" multiple ><el-option v-for="item of categories" :key="item._id" :label="item.name" :value="item._id"></el-option></el-select><!-- 分数 --><el-form-item label="难度" ><el-rate style="margin-top:0.6rem" :max="9" show-score v-model="model.scores.difficult"></el-rate></el-form-item><!-- 分数 --><el-form-item label="技能" ><el-rate style="margin-top:0.6rem" :max="9" show-score v-model="model.scores.skills"></el-rate></el-form-item><!-- 分数 --><el-form-item label="攻击" ><el-rate style="margin-top:0.6rem" :max="9" show-score v-model="model.scores.attack"></el-rate></el-form-item><!-- 分数 --><el-form-item label="生存" ><el-rate style="margin-top:0.6rem" :max="9" show-score v-model="model.scores.survive"></el-rate></el-form-item></el-form-item><el-form-item label="顺风出装" ><!-- 加multiple就可以多选 --><el-select v-model="model.items1" multiple ><el-option v-for="item of items" :key="item._id" :label="item.name" :value="item._id"></el-option></el-select></el-form-item><el-form-item label="逆风出装" ><!-- 加multiple就可以多选 --><el-select v-model="model.items2" multiple ><el-option v-for="item of items" :key="item._id" :label="item.name" :value="item._id"></el-option></el-select></el-form-item><el-form-item label="使用技巧"><el-input type="textarea" v-model="model.usageTips"></el-input></el-form-item><el-form-item label="对抗技巧"><el-input type="textarea" v-model="model.battleTips"></el-input></el-form-item><el-form-item label="团战技巧"><el-input type="textarea" v-model="model.teamTips"></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{categories:[],items:[],model:{name: '',avatar: '',scores:{difficult:0}},}},methods:{afterUpload(res){console.log(res)//vue提供的方法(赋值主体,赋值的属性,res.url),效果类似this.model.icon = res.url// this.$set(this.model,'avatar',res.url)//上面data中设置了属性就可以用这个方法了,推荐使用this.model.avatar = res.url},async save(){if(this.id){this.$http.put(`/rest/heroes/${this.id}`,this.model)}else{this.$http.post('/rest/heroes',this.model)}this.$router.push('/heroes/list')this.$message({type:'success',message:'保存成功'})},async fetch(){const res = await this.$http.get(`/rest/heroes/${this.id}`)// this.model = res.datathis.model = Object.assign({},this.model,res.data)},async fetchCategories(){const res = await this.$http.get(`/rest/categories`)this.categories = res.data},async fetchItems(){const res = await this.$http.get(`/rest/items`)this.items = res.data}},created(){this.fetchCategories()this.fetchItems()this.id && this.fetch()}
}
</script><style>.avatar-uploader .el-upload {border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;}.avatar-uploader .el-upload:hover {border-color: #409EFF;}.avatar-uploader-icon {font-size: 28px;color: #8c939d;width: 178px;height: 178px;line-height: 178px;text-align: center;}.avatar {width: 178px;height: 178px;display: block;}
</style>

2.12 英雄的技能编辑=》将英雄编辑页内容用tab包裹区分为basic 和skills 两个tab页

// admin\src\views\HeroEdit.vue
<el-tab-pane label="技能" name="skills"><!-- type默认为按钮,type="text"为文字链接样式 --><!-- 数据中skills必须是数组 --><el-button style="margin-bottom:1rem;" size="small" @click="model.skills.push({})"><i class="el-icon-plus"></i>添加技能</el-button><el-row type="flex" style="flex-wrap:wrap"><!-- :md="12"表示在普通屏幕上一行显示两个框 --><el-col :md="12" v-for="(item,i) in model.skills" :key="i"><el-form-item label="名称"><el-input v-model="item.name"></el-input></el-form-item><el-form-item label="图标"><!-- 将res.url赋值到item.icon上,res => item.icon = res.url --><!-- res => $set(item,'icon',res.url,将res.url赋值在item主体的icon属性上 --><el-uploadclass="avatar-uploader":action="$http.defaults.baseURL + '/upload'":show-file-list="false":on-success="res => $set(item,'icon',res.url)"><!-- 有图片显示图片,没有则显示上传图标,:src显示的图片 --><img v-if="item.icon" :src="item.icon" class="avatar"><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload></el-form-item><el-form-item label="描述"><!-- 大文本框 --><el-input v-model="item.description" type="textarea"></el-input></el-form-item><el-form-item label="小提示"><el-input v-model="item.tips" type="textarea"></el-input></el-form-item><el-form-item><el-button size="small" type="danger" @click="model.skills.splice(i,1)">删除</el-button></el-form-item></el-col></el-row></el-tab-pane></el-tabs>...
<script>export default {props: {id: {},},data() {return {categories: [],items: [],model: {skills: [],scores: {difficult: 0,},},parents: [],imageUrl: '',};},created() {this.fetchParents();this.fetchCategories();this.fetchItems();this.id && this.fetch(this.id);},methods: {afterUpload(res, file) {console.log(res, file);this.$set(this.model, 'avatar', res.url);// this.model.icon = res.url; // 可能会无法响应赋值,也可以先在data上定义好,就 不用set赋值了。// this.imageUrl = URL.createObjectURL(res.raw);},beforeAvatarUpload(file) {const isJPG = file.type === 'image/jpeg' || file.type === 'image/png';const isLt2M = file.size / 1024 / 1024 < 2;if (!isJPG) {this.$message.error('上传头像图片只能是 JPG 格式!');}if (!isLt2M) {this.$message.error('上传头像图片大小不能超过 2MB!');}return isJPG && isLt2M;},async fetch(id) {const res = await this.$http.get(`/rest/hero/${id}`);console.log(res);// 通过y一次浅拷贝,确保model中有多层属性this.model = Object.assign({}, this.model, res.data);// this.model = res.data;},async fetchParents() {const res = await this.$http.get(`/rest/hero/`);console.log(res);this.parents = res.data;},async fetchCategories() {const res = await this.$http.get(`/rest/categories/`);console.log(res);this.categories = res.data;},async fetchItems() {const res = await this.$http.get(`/rest/item/`);// console.log(res);this.items = res.data;},async save() {if (this.id) {const res = await this.$http.put(`/rest/hero/${this.id}`, this.model);console.log(res);this.$message({type: 'success',message: '编辑成功',});this.$router.push('/hero/list');return;}// async await 与  this.$http.post().then 相似const res = await this.$http.post('/rest/hero/', this.model);console.log(res);this.$message({type: 'success',message: '创建成功',});this.$router.push('/hero/list');},},};
</script>

学习【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台笔记(2.10-2.12)相关推荐

  1. 学习【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台笔记(2.8-2.9)

    [全栈之巅]Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台 本项目是 学习Bilibili 全栈之巅 视频教程相关源码和体会 https://gitee.com/blaunic ...

  2. 学习【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台笔记(1.1-2.5)

    [全栈之巅]Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台 本项目是 学习Bilibili 全栈之巅 视频教程相关源码和体会 https://gitee.com/blaunic ...

  3. 【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(4.1-4.10)

    [全栈之巅]Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(4.1-4.10) 本项目是 学习Bilibili 全栈之巅 视频教程相关源码和体会 https://git ...

  4. 【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(3.11-3.12)

    [全栈之巅]Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(3.11-3.12) 本项目是 学习Bilibili 全栈之巅 视频教程相关源码和体会 https://gi ...

  5. 【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(3.6-3.10)

    [全栈之巅]Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(3.6-3.10) 本项目是 学习Bilibili 全栈之巅 视频教程相关源码和体会 https://git ...

  6. 【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(3.16-3.20)

    [全栈之巅]Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(3.16-3.20) 本项目是 学习Bilibili 全栈之巅 视频教程相关源码和体会 https://gi ...

  7. 学习【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(2.17-2.20)

    学习[全栈之巅]Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(2.17-2.20) 本项目是 学习Bilibili 全栈之巅 视频教程相关源码和体会 https:// ...

  8. 【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(3.13-3.15)

    [全栈之巅]Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台学习笔记(3.13-3.15) 本项目是 学习Bilibili 全栈之巅 视频教程相关源码和体会 https://gi ...

  9. Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台

    前言 最近在跟着Johnny的全栈之巅系列视频教程学习使用NodeJS+Express+Element-UI+MongoDB等开发王者荣耀,服务端server,移动端web,admin,学到了不少东西 ...

最新文章

  1. .a 文件 和 so 文件
  2. 2019.6.18 校内测试 分析+题解
  3. JSP下Forward和Redirect的区别分析
  4. Eclipse Java注释模板设置
  5. python函数 global_Python global全局变量函数详解
  6. Oracle Explain Plan,hint解释与示例
  7. html div element,你能在TypeScript中扩展HTMLDivElement吗?
  8. java excel函数_JAVA实现EXCEL公式专题(四)——字符串函数
  9. 田永强:优秀的JavaScript模块是怎样炼成的
  10. android的多行文本框的值,Swift - 多行文本输入框(UITextView)
  11. HDU2066一个人的旅行(dijkstra)
  12. HDU 3832 Earth Hour
  13. 性能测试方案(计划)模板
  14. 【LaTeX】pdfTex error: pdflatex.exe (file simhei.ttf): cannot open TrueType font file for reading解决方案
  15. 掌握这几个 Java 性能调优技巧,95%的面试必问的Java性能调优知识点,
  16. 城市土地利用分布数据/城市功能区划分布数据/城市poi感兴趣点/植被类型分布
  17. 鱼塘钓鱼(fishing)
  18. 双向链表的结点增删细节(p->next->prior = s是啥意思,p->next->prior究竟代表下一个结点的prior指针还是p本身)
  19. Kettle安装完报错:Driver class org.gjt.mm.mysql.Driver could not be found
  20. 3GPP协议 25.105

热门文章

  1. 双色球(投注号码由6个红色球号码和1个蓝色球号码组成。红色号码从1-33中选择;蓝色球号码从1-16中选择。)
  2. 优酷L1刷入breed方法
  3. 分治算法——分金块、求残缺棋盘问题
  4. MathType公式统一格式化
  5. 动态规划法 第4关:求最长的单调递增子序列长度
  6. SVGO: Node.js 开发的 SVG 矢量图优化工具(svg压缩工具)
  7. 哈希算法SHA-512
  8. vimplus快捷键大全
  9. 网上商城项目(加入购物车)
  10. QQ登录界面因果图法设计测试用例