vue后台管理、APP项目总结集合
文章目录
- 后台管理界面
- APP
- 项目整体总结
别慌,内容看起来多,其实都是一些小干货啦
后台管理界面
搭建一个vue项目:
配置相应的环境,如安装node,vue,webpack(最好安装一下淘宝镜像 cnpm)
使用node自带镜像或者淘宝镜像安装vue脚手架和webpack
cnpm install webpack -gcnpm install -g vue-cli 安装完成之后用 webpack -v和vue -V查看安装的版本
在本地合适位置创建一个文件夹并命名(例如 vue-demo)
打开cmd使用cd进入到这个文件夹的位置
使用命令
vue init webpack vue_demo //创建一个名叫vue_demo的vue项目 (解释一下这个命令,这个命令的意思是初始化一个项目,其中webpack是构建工具,也就是整个项目是基于webpack的。其中vue_demo是整个项目文件夹的名称,这个文件夹会自动生成在你指定的目录中。注意这里的项目名称不要使用大写字母)
上述选择说明:
Project name——项目名称(直接回车就是默认你之前写的第一条命令后面那个名字),也可以自定义一个 Project description——项目的描述 Author——项目作者开发者 Vue build——默认选择 Install vue-router?——是否创建路由,这个一般选择yes,也可以自己创建路由 Use ESLint to lint your code?——是否使用eslint规范你的代码,一般选择yes Should we run `npm install` for you after the project has been created? (recommended)是否使用镜像安装依赖包
根据提示,进入到项目文件夹里,使用npm run dev 启动项目
然后出现这个就代表你的vue项目创建成功了,通过给出的地址,就可以进如到初始化的项目中
这是创建完的项目的文件目录结构,主要文件在src里面,node_modules是刚刚项目创建过程中,使用npm install命令创建的依赖包,整个项目所需的资源文件都在这个里面,其中src里面的components文件夹里面存放的是vue的单文件组件,用来存放组件的文件夹,router文件夹里面的index.vue是用来写vue路由的文件,实现页面间的跳转,APP.vue是项目的主文件,也是入口文件,main.js是vue实例的挂载地,通过这个文件,我们可以导入我们所需的资源文件,例如一些初始化css文件,assets是资源文件,可以存放一些项目所需的图片图标等
封装全局axios请求:
// axios 配置 import axios from 'axios' import store from './store' import router from './router'//创建 axios 实例 let instance = axios.create({baseURL: "", //本地打开项目访问地址,切记需要上线是要改为服务器地址timeout: 5000, // 请求超过5秒即超时返回错误headers: { 'Content-Type': 'application/json;charset=UTF-8' }, })instance.interceptors.request.use(config => {if (store.getters.token) { // 若存在token,则每个Http Header都加上tokenconfig.headers.Authorization = `token ${store.getters.token}`console.log('拿到token')}console.log('request请求配置', config)return config},err => {return Promise.reject(err)//基于promise的axios})// http response 拦截器 instance.interceptors.response.use(response => {console.log('成功响应:', response)return response},error => {if (error.response) {switch (error.response.status) {case 401:// 返回 401 (未授权) 清除 token 并跳转到登录页面store.commit('BIND_LOGOUT')router.replace({path: '/login',query: {redirect: router.currentRoute.fullPath}})breakdefault:console.log('服务器出错,请稍后重试!')alert('服务器出错,请稍后重试!')}}return Promise.reject(error.response) // 返回接口返回的错误信息} ) export default {//将请求暴露到全局// 注册userRegister(data) {return instance.post('/api/register', data)//这个地址是后端给你的,前缀一般都是统一api},// 登录userLogin(data) {return instance.post('/api/login', data)},//get请求getsome() {return instance.get('/api/some')//get请求使用方法}, } 但是这只是封装,并不能使用,需要使用跨域进行代理,否则,不同端可能会无法访问
跨域代理
//跨域写在vue.config.js里面 module.exports = {runtimeCompiler: true,publicPath: './', // 设置打包文件相对路径, baseUrl 已被官方不建议使用devServer: {// host: 'localhost',port: 8081,// disableHostCheck: true,open: process.platform === 'darwin', //配置自动启动浏览器https: false,hotOnly: false,proxy: { // 跨域请求代理'': {//这里的''里面的内容意思就是用''里面的内容代替你的后端接口地址,一般写apitarget: '', // 后端接口地址changeOrigin: true,ws: false,pathRewrite: {'^': ''//后端接口地址}}}},productionSourceMap: true, // 生产环境是否生成 sourceMap 文件// configureWebpack: {// performance:{ // webpack打包压缩限制报错这里禁掉这个warning信息// hints: false// }// } } 设置好之后就可以使用axios(前提后端得有接口哈)发送请求了
路由部分
import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' Vue.use(Router)export default new Router({routes: [{path: '/',name: 'HelloWorld',component: HelloWorld}] }) //创建全局导航钩子(这个.是跟在new Router()后面的) .beforeEach((to, from, next) => {if (to.meta.title) { // 路由发生变化修改页面titledocument.title = to.meta.title}if (to.meta.requireLogin) {if (store.getters.token) {if (Object.keys(from.query).length === 0) { // 判断路由来源是否有query,处理不是目的跳转的情况next()} else {let redirect = from.query.redirect // 如果来源路由有queryif (to.path === redirect) { // 避免 next 无限循环next()} else {next({ path: redirect }) // 跳转到目的路由}}} else {next({path: '/login',query: { redirect: to.fullPath } // 将跳转的路由path作为参数,登录成功后跳转到该路由})}} else {next()} })
打印实现
//首先,引入第三方的打印插件npm install vue-print-nb --save //引入之后,在需要打印的模块使用v-print指令,即可实现打印 例如 <el-button v-print="'#printTest'"> 这里v-print后面的 #printTest 是绑定的需要打印的模块 <div id="printTest">这里是打印的地方(这里放打印的内容,表格等)</div>
登陆校验
//登陆和注册时都使用vue里面rule校验规则,例如 data(){ let checkName = (rule, value, callback) => {//校验函数if (value === '') {callback(new Error('请输入用户名'))} else {callback()}} let validatePass = (rule, value, callback) => {//校验函数if (value === "") {callback(new Error("请输入密码"))} else {callback()} } return {ruleForm: {//定义ruleForm保存输入内容name: '',pass: ''},rules: {//定义rules规则,将校验函数添加至rules规则中进行校验name: [{ validator: checkName, trigger: 'change' }],pass: [{ validator: validatePass, trigger: 'change' }],} } }
注册
//在注册部分发送的密码要加密,可以采用md5加密方式
//加密方式
import CryptoJS from 'crypto-js' // 引用 md5 加密
axios.uregister({username: encodeURIComponent(this.ruleForm.username),password: CryptoJS.MD5(this.ruleForm.pass).toString(),//这里使用CryptoJS.MD5().toString()方法加密发送给后端的密码phone: this.ruleForm.phone,code: this.ruleForm.smscode
}).then(res => {console.log("^^^")
})
APP
APP开发,采用的是Hbuliderx编辑器,使用了colorui、uvew等组件库,同时也使用了uniapp自带组件库
文件结构
当我们创建了一个uniapp项目后,大致的文件结构就是这样的(介绍有可能不是很准确,有需要可以参考官网哈)
- 首先,common文件夹下面就是存放封装好的请求的文件,其中request.js是主要的封装文件(下文有介绍),http.apis.js文件是存放请求函数的,index.js主要是存放一些请求配置的
- comments文件夹下面存放的主要是引用的组件
- js_sdk存放的是配置一些特殊接口的sdk
- node_modules是依赖包
- pages下是写APP中整体页面的,下面分散多个页面的文件(.vue)
- static文件夹是存放一些资源文件的
- store文件夹使用来存放缓存文件的,其中index文件下文有介绍
- unpackage文件夹里面可以存放APP整体的图片和在线打包后的apk文件
- APP.vue是项目的主入口文件
- main.js是主文件
- manifest.json文件是全局配置文件
- pages.json文件用于存放各个页面路径以及设置全局页面的统一样式
首先通过promise对uniapp的自带的request请求进行封装
1、首先创建一个request.js文件,再定义基地址 const base_url = "http://……/app/" 2、实现封装请求 // 请求接口封装 const requests = (_options, errorlog = true, mask = true, redirect = null) => {return new Promise((resolve, reject) => {// 是否显示加载模糊if (mask) {uni.showLoading({title: '正在加载中...',mask: true});}let _data = {}let _header = {}if (_options.hasOwnProperty("data")) {_data = _options.data//console.log(_data)测试传递的参数是否准确}if (_options.hasOwnProperty("header")) {_header = $.extend(header, _options.header)//将参数中的header传递给后端,这里使用了jQuery的方法,但是也可以不使用,直接将参数中的header给这里的_header}console.log( _options.url.indexOf("://") == -1 ? base_url + _options.url : _options.url)//测试请求地址是否正确uni.request({url: _options.url.indexOf("://") == -1 ? base_url + _options.url : _options.url,//请求地址method: _options.method,//请求方法data: _data,//请求的数据header: _header,//请求头success: (res) => {if (res.statusCode >= 500) {return}if (res.statusCode < 300) {if (res.data.code != '200' && res.data.msg != 'OK') {//通过判断后端传回来的数据是否满足要求uni.showToast({icon: 'none',title: res.data.msg})}console.log(res.data)resolve(res.data)//成功,则进入resolve()方法中,将传回来的参数传递给需要的then方法} else {// 未登录状态或者登陆状态失效。需要提示重新登陆。if (res.statusCode == 401) {uni.showModal({title: '需要登录',content: "此功能需要登录使用哦",showCancel: false,confirmText: '去登录',success: function(res) {// uni.redirectTo({// url: '/pages/login/login.vue'// });}})} else if (errorlog) {let str = ""for (let key in res.data) {str += res.data[key] + '\n'}uni.showModal({title: "错误",content: str,showCancel: false,confirmText: '知道了',success: function() {if (redirect) {uni.reLaunch({//uniapp中的relaunch方法是关闭所有页面,跳转到目的页面url: redirect})}}})}}},fail: (err) => {if (mask) {uni.showToast({icon: 'none',title: '服务器错误~请联系管理员',duration: 4000})}reject(err)//错误则进入到reject方法中},complete: () => {if (mask) {uni.hideLoading() // 完成uni.showLoading回滚}}});}) }
//接着导出这个请求 module.exports = {requests: requests, }
//再创建一个http.api.js文件 //这个文件专门存放请求函数 //例如import api from '@/common/request.js'//先引入刚刚封装好的请求方法,api作为别名调用方法// 登陆 function Login(options, errorlog = true, mask = true){//使用es6语法,使用默认参数return api.requests({url:'/login',//这个地址就是后端给你的接口文档里面的method: 'post',//请求方法data:options//从页面传递过来的参数,发送给后端}) } //接着把写好的请求暴露到全局 export default {Login }
在登陆界面是这样的
this.$httpApis.Login({//这里的$httpApis是在main.js里面挂载到vue实例上的(见下方main.js),所以可以在全局引用//这个对象就是需要传递给后端的数据loginname:_this.phoneData,password:_this.passData }).then(res => {console.log(res)// 简单验证下登录(不安全)if(res.code == 200){console.log("登陆成功")uni.reLaunch({ url: './home',});}else if(res.code == 401){_this.isRotate = falseuni.showToast({icon: 'none',position: 'bottom',title: res.msg});}uni.hideLoading(); }).catch(err => {uni.hideLoading(); })
main.jsimport Vue from 'vue'// 将请求类挂载到 Vue 实例上Vue.prototype.$httpApis = httpApis// 将请求路径挂载到 Vue 实例上Vue.prototype.$api = api
缓存
缓存在前端十分重要,可以避免很多不必要的重复请求,过多的重复性请求会占用后端资源,影响性能,vue提供了一种缓存管理机制——vuex,但是我这个项目中使用的是uniapp开发一个APP,使用vuex会导致一个很严重的问题>在页面刷新之后会导致vuex里面的存储内容被刷新掉,导致缓存效果失败。uniapp里面自带了缓存的api,但是存储很多信息时就会导致信息错乱,没有条理,所以我就采用vuex和uniapp自带的uni.setstorage()方法结合的方式,实现了信息条理化存储,实现demo如下
//此处为store下的index.js import Vue from 'vue' import Vuex from 'vuex'Vue.use(Vuex)const store = new Vuex.Store({//vuex知识具体请看vuex官网state: {hasLogin:false, //用户是否登录userInfo:{} //用户数据},mutations: {// 登录Login(state,user){//登陆函数,登陆成功后调用,缓存需要缓存的信息//登录状态为已登录state.hasLogin = truestate.userInfo = user//储存用户数据到本地uni.setStorage({key: 'userInfo',data: user,});console.log('登陆成功')console.log(state.hasLogin,state.userInfo)},// 退出登录logout(state,user){//登录状态为未登录state.hasLogin = falsestate.userInfo = {}//删除本地储存uni.removeSavedFile({key: 'userInfo',})console.log('退出登录')console.log(state.hasLogin,state.userInfo)}},modules: {} })export default store;
login.vue
import { mapMutations } from 'vuex'//从vuex中引入mapMutations methods: { ...mapMutations(['Login']),//将this.login映射为this.$store.commit('login') this.$httpApis.Login({loginname:_this.phoneData,password:_this.passData }) .then(res => {console.log(res)// 简单验证下登录(不安全)if(res.code == 200){_this.isRotate=falselet userInfo={"username":res.data.userinfo.name,"nickname":res.data.userinfo.userid,"token":res.data.token,} //保存用户信息和tokenthis.Login(userInfo);//调用vuex中的登陆函数,存入缓存console.log("登陆成功")uni.reLaunch({ url: '../home/home',});} }
APP内某个页面跳转到一个网页
在uniapp中有专门存放网页的标签,但是在项目中,甲方给我们提供跳转的网站的后缀是.action结尾的网址,使用这个标签会失效,显示无法加载网页资源,所以不得不换一种方式,想到了h5的plus.runtime.openURL方法,但是使用这个方法也存在问题,解决如下(重点)
使用h5的plus方法,必须在uniapp项目内进行申明(这一点在uniapp官方文档有介绍) 即// #ifdef APP-PLUSH5代码 // #endif plus.runtime.openURL()方法是打开手机自带的浏览器打开指定网页(电脑基座调试无效,必须手机基座调试) getMsg(){// #ifdef APP-PLUSplus.runtime.openURL('https://aaaa/bb.action')//.action结尾的网址// #endif } 但是使用了这个方法还是没办法跳转,原因是配置文件没有写好跳转必须的条件 在manifest.json文件中,在打包配置中加上 "schemes" : [ "test" ]//测试 加上之后,在手机基座上调试就可以实现任何形式正确安全的网页的跳转其他形式的网页需要在app内部进行访问,所以还是需要使用webview标签,但是直接写webview会有很多的不方便,所以可以新建一个文件,专门存放需要跳转的网页,再通过主页面传递url地址,就可以实现跳转 uni.navigateTo({url:'./webView?url=' + 'https://aaaa/bbb.aspx',//传递参数的形式和接受方法uniapp中有介绍(目的页面即./webView,在onload中接受传递过去的参数) }) 如:onLoad(res) {this.url = res.url;//res.url就是传递过来的地址}
uniapp获取设备的MAC地址
uniapp内没有获取设备信息的api,所以,只有靠万能的h5来获取设备的信息,基本信息都很简单,加上编译条件后,直接调用api就完事,但是要获取mac地址,却没有专门的api,如下获取mac地址,uniapp和h5通吃
//获取mac地址 var net = plus.android.importClass("java.net.NetworkInterface")//调用java的库 var wl0 = net.getByName('wlan0') var macByte = wl0.getHardwareAddress() var mac = ''; for (var i = 0; i < macByte.length; i++) { var tmp = ""; var num = macByte[i]; if (num < 0) { tmp =(255+num+1).toString(16); } else { tmp = num.toString(16); } if (tmp.length == 1) { tmp = "0" + tmp; } mac += tmp; //这里的mac的值就是用户的mac地址
顺便说一下,一般app都有启动页,所以上面所说的设备信息一般也是在启动页的时候获取,启动需要做的还有预加载第一个呈现在用户眼前的界面,以免数据获取延迟,体验不佳,当然还要异步获取用户的其他信息,比如位置信息等,放入缓存,以便后续直接获取
获取不同机型屏幕上方的custom(就是手机的展示信息,如时间,电量,信号,网速,还有摄像头等等)高度,以便自适应头部导航栏
方法一:
// colorui 获取设备屏幕大小,计算不同的custom(在APP.vue中的onLaunch函数中加入这个函数) uni.getSystemInfo({success: function(e) {// #ifndef MPVue.prototype.StatusBar = e.statusBarHeight;if (e.platform == 'android') {Vue.prototype.CustomBar = e.statusBarHeight + 50;} else {Vue.prototype.CustomBar = e.statusBarHeight + 45;};// #endif// #ifdef MP-WEIXINVue.prototype.StatusBar = e.statusBarHeight;let custom = wx.getMenuButtonBoundingClientRect();Vue.prototype.Custom = custom;Vue.prototype.CustomBar = custom.bottom + custom.top - e.statusBarHeight;// #endif // #ifdef MP-ALIPAYVue.prototype.StatusBar = e.statusBarHeight;Vue.prototype.CustomBar = e.statusBarHeight + e.titleBarHeight;// #endif} }) //在其他界面直接使用this.CustomBar即是屏幕上方的custom的高度,再结合实际代码就解决头部导航栏自适应的问题了,但是这是colorui中的方法,所以灵活性不高,建议方法二
方法二:
使用css变量(官方有自带的直接后去高度的css变量) <view class="headerCustom" :style="'--height'"><!-- 此容器是响应不同型号手机上方状态栏高度,作为空容器,撑起上方高度 --> </view> .headerCustom{height: var(--status-bar-height);//这是官方的css变量,用于获取不同手机型号上方状态栏的高度 } 相对于第一种,更简便而且灵活,自己设计头部导航栏,不香嘛
项目中有一个地方用到了简单的三级联动,但是因为是用来插件,所以不太方便展示,下篇博文出一个三级联动的demo,此处仅附带demo图片
项目整体总结
整个项目,主要需要我做两块,一块是后台管理的部分(自适应APP端),一部分是APP部分,是一个前后端分离的项目,同时也是我上手学vue一段时间后的第一个项目,其中有很多不足,大多数时间都是在搬砖,但是还是领悟了一点点前后端分离的概念。
首先,前后端分离不是说前端和后端完全只是管自己的那一部分,是逻辑上的分离,不表示前后端人员的分离,如交流接口等,逻辑上分离是指前端只需要告诉后端需要什么类型的什么数据,基本就可以开始写页面了,等待后端写好接口,通过请求将数据渲染到页面上就OK了,后端也是只需要了解到需要写什么接口,链接数据库,写数据接口和接口文档应该就可以了,当然后端在必要的时候处理应该处理的业务逻辑,在前端尽量少的处理逻辑,逻辑处理能交给后端的就交给后端,确实是前端需要处理的逻辑,才由前端来写。
其次,前端方面,需要写好请求的封装函数,方便调用而且可以提高效率、减少代码的冗余,这次后台管理使用的是axios请求,封装好了axios,只需要写调用接口的函数就可以实现前后端链接了,需要注意跨域的问题;APP使用的是promise封装uniapp自带的request请求,封装完成之后也是同样的套路,由于知识浅薄,封装方法都是嫖自于百度。
最后,整体项目还未完成,但是我退出了(和老师提前协商好了的),因为我在做项目的过程中发现虽然我可以学到很多前后端链接的知识,但是学到的基础知识基本没有,大部分都是百度找方法,搬砖搬砖搬砖(使用组件库和各种插件),所以我想退出来,好好沉淀一下学习更多的知识,以便后续能更好的进行实战,当然也不是完全放弃这个项目,只是不参与这个项目开发了而已,之前写过的代码仍然是我维护。
个人总结:学的太少,基础不是很扎实,算法思想不强,vue基础一般,学到了前后端的连接原理,了解了一个全栈项目是如何运行的,通过项目发现自我、认识自我,真的很有用,那样也不会一度膨胀,浪费韶华。
学的越多,没学的越多,正如你知道的越多,不知道的越多!
vue后台管理、APP项目总结集合相关推荐
- 从0到1完成一个Vue后台管理项目(九、引入Breadcrumb面包屑,更改bug)
往期 从0到1完成一个Vue后台管理项目(一.创建项目) 从0到1完成一个Vue后台管理项目(二.使用element-ui) 从0到1完成一个Vue后台管理项目(三.使用SCSS/LESS,安装图标库 ...
- vue后台管理知识点、难点总结01
vue后台管理知识点.难点总结 1.upload时,png格式的不能上传????(不对) 2 js中的项目应用什么时候用async和await 3 添加或者编辑的时候报错:Error in v-on ...
- 1.电子商城后台管理平台项目概况
一.项目介绍 随着信息化的发展,电商也随着互联网的发展日益状态.为了整理之前所学,这里将做一个电子商城后台管理系统. 二.项目需求 电子商城后台管理平台包含账号管理(保存用户信息).用户登录.退出登录 ...
- 美多后台管理和项目环境搭建
美多后台管理 Django框架已经提供了一个Admin管理后台,但是Admin的本身的页面可修改的页面布局效果比较少,无法满足公司定制页面需求,这时候就需要独立开发一套后台管理系统,满足公司对后台数据 ...
- “好家园房产中介网后台管理”python项目
一.语言和环境 1.实现语言:python语言. 2.环境要求:pycharm + mysql. 二.实现功能 使用flask技术开发"好家园房产中介网"的后台管理功能,具体实现功 ...
- Z-Admin后台管理轻量级项目模板V0.3
Z-Admin 轻量化的后台管理模板 下载及预览 https://gitee.com/zhangqian0828/z-admin 项目特点 springBoot单体架构 集成前端页面,接口使用前后端分 ...
- uni-app+vue+后台管理实现记账流水功能的移动应用
记账小程序,实现用户可以通过小程序来记录自己的支出收入账单,以及查看流水 2.还设置有PC端可以按时间来查询准确的流水记录 3.小程序是通过uni-app其中运用vue框架+vant(UI框架)设计的 ...
- Vue后台管理页面总体结构及主要功能设计
后台管理页面总体结构为:顶部左侧为系统标题,顶部右侧为用户图标及改密.退出菜单.中间左侧为功能菜单,中间右侧为操作区域,可以用el-row配合el-col来实现布局.其中导航菜单可以用el-menu配 ...
- 搭建Vue后台管理项目
从0开始快速搭建一个后台管理系统,搭建好之后就是下面这种形式 安装node环境:下载地址:Node.js 安装脚手架:npm install -g @vue/cli 创建vue项目:vue creat ...
最新文章
- 使用SKIP-GRANT-TABLES 解决 MYSQL ROOT密码丢失
- 互联网协议第六版部署提速 阿里专家详解全套安全解决方案
- Android中实现Bitmap在自定义View中的放大与拖动
- pythondict增加-python字典键值对的添加和遍历方法
- python3 列表取交集_常用序列数据类型列表
- Exploiting the Syntax-Model Consistency for Neural Relation Extraction-学习笔记
- Linux版APP超级签名分发系统源码
- 洛谷 P3732 [HAOI2017]供给侧改革【trie树】
- BZOJ 1024: [SCOI2009]生日快乐
- JMETER 分布式踩过的坑及填坑方法
- python训练手势分类器_从Scikit Learn中保存的训练分类器进行预测
- 【源码更新】活动报名登记预约问卷表单系统微信小程序支持导入导出自定义表单填报字段
- 谷歌、亚马逊在区块链都耽搁了什么 竟让后起的脸书名声大噪
- Jmeter 使用详解、性能压测分析与性能优化思路
- css动画-animation各个属性详解
- 人工神经网络的算法原理,深度神经网络工作原理
- 学会php想转学java好学吗_Java和PHP哪个好学
- Jsp Servlet 学生公寓管理系统
- freebsd安装应用
- 网狐棋牌 SQL Server 数据库配置