学习NodeJs + VueJs (Express + ElementUI)制作王者荣耀 记录

    技术2022-07-29  78

    一些方法值得学习

    下载使用element-ui

    控制全局滚动条的样式, 直接添加在App.vue里面即可

    element-ul里面的el-rate组件有:max显示几颗星, show-score显示分数的属性

    element-ul里面的el-select有个multiple可以进行多选

    ::-webkit-scrollbar { width: 5px; height: 5px; } ::-webkit-scrollbar-thumb { background-color: #a1a3a9; border-radius: 3px; }

    模型Category,分为name: String, parent: mongoose.SchemaTypes.ObjectId,在前端的vue里面就只需要定义一个cateValue为空对象即可,在双向绑定数据的时候直接v-model=cateValue.name,v-mdoel=cateValue.parent。就不能像下面这样定义了。

    data () { return { cateValue: { name: '', parent: '' } } }

    或者写成下面的形式也可以, 不过好像很少见

    data () { return { cateValue: { name: null, parent: null } } }

    因为这样会使parent的值类型变成了String类型而当parent为空时就无法提交新的分类。就会出现无法强制转换类型的错误

    在写上返回状态码之后只有200才可以被前端接受到, 而403, 404的状态码返回就会直接在控制台报错

    res.json({}) // 可以获得res res.status(403).json({}) //报错

    使用axios这个插件的时候如果每个单文件请求都写http://localhost...之类的就太长了, 所以就直接使用它的一个方法

    const axios = require('axios') const http = axios.create({baseURL: 'http://localhost:8000'}) module.exports = http /****/ Vue.prototype.$http = http /****/ this.$http.get('/rest/...')

    将导出的方法变成Vue原型对象上的方法, 这样在其它vue单文件组件里就可以直接使用了, 而不需要再引入axios这个包, 这里获取这个默认根地址是$http.defaluts.baseURL

    有专门的富文本编辑插件vue2-editor

    axios 拦截器

    vue使用插槽slot

    //子组件 <slot :item="item"></slot> //父组件 <template slot-scope="prop"> <div>{{prop.item}}</div> </template> // 2.6以前的写法 //子组件 <slot name="items" :item="Categories"></slot> //父组件 <template #items{item}> <div v-for="value in item">value<div> </template> //2.6以后的动态插槽名, #为v-slot的缩写

    对于两个页面共用同一个组件, 可能出现数据没有变化或者清空

    <router-view :key="$route.path"></router-view> watch () { '$route()' { //判断参数 if(!this.$route.params.id) { } } } //自己写的, 缺点:复用的组件都需要写上

    聚合查询

    对于swiper这个组件里有默认的事件<swiper @slide-change></swiper>

    使用swiper每一个滑动页的高度不一样使用autoHeight:true这个参数来控制

    使用map来遍历数据控制台报错, 可能是数据本身的原型链上不包含map方法


    通用CRUD接口的学习

    在mongoose的使用时再加上useFindAndModify: false这个参数 分类下的所有接口基本写完就一共有5个接口, 而还有文章, 装备, 人物等等, 基本都是相同的操作, 就可以根据这个分类的接口改为通用的接口大概原理和请求某一接口下不同id的数据一样, 将请求的模型, 路由全部换成动态的. 便于自己理解,写的是一层层嵌套的第一层访问得是/admin, 第二层访问的是/rest/:resource, 第三层则是在resource下的接口例如'/','/:id',根据不同请求又会有不同的接口。主要是第二层, rest这个可以写也可以不写, 写上它是为了避免其他接口的影响, 而resource则根据前端的请求值的不同而不同。

    这里需要注意的是, 子路由在使用父路由的请求参数是需要加上mergeParams参数的, 来合并参数的

    const router = express.Router({ mergeParams: true })

    根据不同的请求就可以生成不同接口再配合规范命名,使用inflection包来处理单词的单复数问题。 require('inflection').classify(req.params.resource) 就可以将大写的转化成小写复数的形式

    这里不能直接写在底层路由的前面, 需要写成中间件的形式, 每个底层路由前都需要执行转换下

    const express = require('express') const router = express.Router() const Router = require('./admin/category') router.use('/rest/:resource', async (req, res, next) => { const modelName = require('inflection').classify(req.params.resource) req.Model = require(`../modle/${modelName}`) next() }, Router) module.exports = router

    上传图片

    先是使用了element-ui里面的图片上传组件,里面的on-success绑定的方法会返回res使用一个中间件的插件multer在element-ui里面的el-upload的上传图片组件name参数控制上传字段 引入multer, 给multer设置上传文件的路径 const multer = require('multer') const upload = multer({dest: __dirname + '/../../uploads'}) 中间件的形式使用, 单个文件就是upload.single('file'), 这个中间件会自动把信息存储在req.file里面还必须加上静态文件的托管, 让可以通过路径访问到图片 app.use('/uploads', express.static(__dirname + '/uploads'))

    这样就可以通过http://localhost:8000/uploads/图片名在前端页面中访问到并且渲染出来


    mongoose模型里的集合可以直接创建子集, 例如以下

    skills: [{ icon: {type: String}, name: {type: String}, description: {type: String}, tips: {type: String} }], partners: [{ hero: {type: mongoose.SchemaTypes.ObjectId, ref: 'Hero'}, description: {type: String} }]

    在mongoose里定义的模型的属性, 当作为返回值的时候, 如果对象或者字符串为空的话,那这两个属性不会随着res返回给前端。空数组的属性也会返回

    Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象,可以多个对象的合并, 用于对象的赋值

    有path就会与parmas冲突

    将之前的res.json()发送改为res.send(),json()返回json格式的,send返回任何类型

    登录校验

    登录 在登录的接口里应该是先校验用户名, 再校验密码, 后生成token返回给前端。设置请求头 前端获取保存在localStorege, 使用axois里的方法设置请求头, 这样在后台的页面里请求头都会有token的值。在需要检验的后台页面中, 从前端传来的token解密为用户的id值来与数据库的id值校验,判断是否为登录状态。当页面没有token或者没有用户的时候回抛出异常, 这里使用的是http-assert的包来捕获异常和抛出 const assert = requrie('http-assert') assert(value, 401, '错误信息') 使用express的全局捕获异常 app.use((err, req, res, next) => { res.status(err.status || 500).send({ errno: -1, message: err.message }) }) 在axois的设置里面, 给后台的前端页面用axios来请求数据的请求头都加上token的值, 不知道为什么在create里面加会出现问题 添加请求头http.interceptors.request.use(req => { if(localstorege.token) { req.headers.Authorization = 'Bearer ' + localstorege.token } return req }, err => { return Promise.reject(err) }) 再就是拦截从服务端返回的错误http.interceptors.response.use(res => { return res }, err => { Vue.prototype.$message({ type: 'error', message: err.response.data.message }) if(err.response.status != 200) { router.push('/login') } return Promise.reject(err) }) 这样所有需要在后台请求数据的接口都加上了token值来进行验证登录, 但是在后台中没有数据请求的页面就不会发生验证。我们可以在这个页面自己再去发送请求, 但是我们需要尽可能减少请求。提高性能。我们就在客户端做路由的登录拦截。// 给路由配置meta字段 path: '/login', name: 'Login', component: () => import('./views/Login.vue'), meta: { isPublic: true} // 表示这个路由是公开的 再用全局的导航守卫里判断一下meta里的isPublic值 router.beforeEach(to, from, next) => { if(!localstorege.token && !to.meta.isPublic) { next('/login') } next() //或者 let token = localStorage.token let needAuth = to.matched.some(item => item.meta.ispublic) if (!token && !needAuth) return next({ path: '/login' }) next() } 这样基本就是两层拦截校验了 参考router

    scss的学习和使用

    标签嵌套使用样式编程式的方法$color: ( 'primary': #db9e3f, 'green': #999, 'light': #f9f9f9, 'white': #fff, 'black': #000, 'dark': #222, ); 记得上面的变量后面需要加上分号 遍历@each $var in list { .text-#{$var} { text-align: $var } }

    vue.config.js的基本配置

    设置路径别名const path = require('path') function resolve(dir) { return path.join(__dirname, dir) //找到对于vue.config.js这个文件的相对路径 } module.exports = { chainwebpack (config) { config.resolve.alias .set('@', resolve('src')) .set('@scss', resolve('src/assets/scss')) } }

    浏览器技巧

    在浏览器中获取数据,使用方法与JQuery类似// $$('h3', 'li') h3为包含于li的dom $$('.hero-nav>li').map((el, index) => { return { categoryName: el.innerText, HeroList: $$('li', $$('.hero-list')[index]).map(li => { return { name: $$('h3', li)[0].innerText, avatar: $$('img', li)[0].src } }) } })

    注意

    在express中的全局捕获异常需要下载express5.0以上的版本(否则没有用)

    感谢b站的 全栈之巅 老师

    Processed: 0.010, SQL: 9