来源:阿闲博客Egg+Vue+Ssr下一代Web开发框架环境版本&&ModeEgg版本:^2.x.x;模式:MVCNode版本:^8.x.x+Npm版本:^5.x.x+Webpack版本:^4.x.xVue版本:^2.5.0模式:MVVMegg-view-vue-ssr版本:^3。x.x运行命令安装cli(非必须)npminstalleasywebpack-cli-g安装依赖npminstalllocalDevelopmentnpmrundevreleasemodenpmrunbuild启动应用npmstart项目结构及基本规范├──app│├──controller//控制器(模式:C层)││├──测试││└──测试。js│├──models//数据模型(模式:M层)││├──api//接口api│├──mocks//数据处理│├──app││└──home│├────extend│├──lib│├──middleware│├──mocks│├──proxy│├──router.js//服务端路由│├──view//view(模式:V层,toolsgenerated)││├──about//服务器编译的jsbundle文件││││└──about.js││├──home││││──home.js//服务器编译的jsbundle文件││└──layout//用于根据指定的layout生成相应的html页面,当服务端渲染失败时,使用客户端渲染││└──layout.html│└──web//view(front-endprojectdirectoryDevelopment-->Generationmode:Vlayer)│├──asset//存放公共js、css资源│├──framework//前端公共库和第三方库││├──fastclick│││└──fastclick.js││├──sdk││││├──sdk.js│├──storage││││└──storage.js││└──vue//公共代码vue相关││├──app.js//前后端调用入口,默认导入componet/directive/filter││├──component.js//组件入口,可以添加组件目录,类似如下指令││├──directive//指令目录,存放各种指令组件││├──directive.js//指令引用入口││└──filter.js//过滤器引用入口│├──page//前端页面和webpack构建目录,即webpack打包配置entryDir││├──home//每个页面都遵循相同的目录名、js文件名、scss文件名和vue文件名││││├──home.资产下有图片、公共图片和css│││││└──icon_more.png│││└──w-week//页面自带组件,公共组件放在widget下│││├──w-week.scss││└──w-week.vue││└──test//每一个页面后面都是目录名,js文件名,scss文件名,vue文件名同样││└──test.vue│├──store//介绍vuex的基本规范,可以分为模块││├──mutation-type.js││││└──mutations.js││└──store.js│└──component//公共业务组件,如loading、toast等,跟在目录名、js文件名、scss文件名、vue文件名相同│├──loading││├──loading.scss││└──loading.vue│├──测试││├──test.vue││└──test.scss│└──toast│├──toast.scss│└──toast.vue├──build//webpack自定义配置入口,会一样因为默认的Configurations被合并了(貌似很多,其实这里只是解释一下)│├──base││└──index.js//publicconfiguration│├──client//客户端webpack编译配置││├──dev.js│├──prod.js││└──index.js│├──server//服务端webpack编译配置││├──dev.js││├──prod.js││└──index.js│└──index.js├──配置│├──config.default.js│├──config.local.js│├──配置.prod.js│├──config.test.js│└──plugin.js├──doc├──index.js├──public//webpack编译目录结构,渲染文件搜索目录│├──manifest.json//资源依赖表│├──static│├──css││││├──home│││├──home.07012d33.css│││└──测试││├──test.4bbb32ce.css││├──img││├──change_top.4735c57.png││──└──intro.0e66266├──imgtest││└──test.js│└──vendor.js//生成的公共封装库nodejsserver层处理配置路由router/*文件目录:project/app/router.js*/module.exports=app=>{app.get('/',app.controller.home.home.index);app.get('/app/api/article/list',app.controller.app.app.list);应用程序。get('/app/api/article/:id',app.controller.app.app.detail);app.get('/app(/.+)?',app.controller.app.app.index);};Controller/*文件目录:project/app/controller/home/home.js*/constController=require('egg').Controller;constMocks=require('../../models/mocks/home/init');classHomeControllerextendsController{mocks(){const{ctx}=this;返回新模拟({ctx:ctx});}asyncindex(){//pageconst{ctx}=this;constmocks=this.mocks();awaitctx.render('index/index.js',{title:'eggvuessr',list:awaitmocks.index()//发送接口获取到的数据});}asyncpager(){//Interfaceconst{ctx}=this;constmocks=this.mocks();constpageIndex=ctx.query.pageIndex;constpageSize=ctx.query.pageSize;ctx.body=awaitmocks.index();//发送接口获取到的数据}};module.exports=HomeController;Controller:ctx对象通用说明获取页面参数(params)//get(46),例如:http://localhost:7001/app/detail/46constid=this.ctx.params.id;获取页面参数(查询)//获取(20),例如:http://localhost:7001/?page=20constpage=this.ctx.query.page;获取页面协议(protocol)//获取(20),例如:http://localhost:7001/?page=20constprotocol=this.ctx.protocol;呈现页面awaitctx.render('app/app.js',{});渲染界面数据this.ctx.body={title:'interface'};详细了解数据模型:API(必须传递页面协议值,否则使用config配置)/*文件目录:project/app/models/api/api.js*/constaxios=require('axios');constConfig=require('../../config/config');classApi{constructor(opts){console.log(88777);}fetch(_opt){varparam='',opt=Object.assign({baseHost:Config.apiHost,protocol:Config.apiProtocol,urlMap:'',url:'',method:'GET',type:'json',cookies:true,//布尔超时:10000,param:null,//{id:123}paramType:0//0表示参数以字符串形式提交,如"wen=12&xx=333";1表示参数以对象的形式提交,如"{wen:12,xx:33}"},_opt);//考虑redis缓存处理if(opt.urlMap!==''){opt.url=`${opt.baseHost}${opt.urlMap}`;}if(opt.protocol==='https'){opt.url=(opt.url).replace(/^http:(\/\/[\w])/,'https:$1');}console.log('opt.url',opt.url);if(opt.param!==null){for(varkeyinopt.param){if(typeofopt.param[key]!=='function'){param+='&'+key+'='+encodeURIComponent(opt.param[key]);}}param=param.substring(1);}returnaxios(opt.url,{method:opt.method,timeout:opt.timeout,data:(opt.paramType===0)?param:opt.param,withCredentials:opt.cookies}).then(function(response){returnresponse.data;}).catch(function(ex){return{error:true,url:ex};});}}//导出默认的Api;模块。exports=newApi();数据模型:mocks/*目录文件:project/app/models/mocks/app/init.js*/const{fetch}=require('../../api/api');classMocks{constructor(suppor){this.ctx=support.ctx;}index(){leturlMap='/menus',protocol=this.ctx.protocol;returnfetch({url:'http://m.aipai.com/mobile/apps/apps.php?module=gameIndex&func=newAsset&sort=click&appId=11616&page=3&pageSize=12',//urlMap:urlMap,protocol:协议,//ctx.protocol,method:'get',type:"jsonp",//param:param}).then(ret=>{//访问超时或资源地址错误if(typeofret.error!=='undefined'&&ret.error){//msg='网络错误';}else{}return退役;});}};module.exports=模拟;客户端获取服务器数据:serverData(withoutstoreandrouter)//使用计算属性computed:{title(){returnthis.serverData.title;},列表(){返回this.serverData.list;}},获取服务器数据:serverData(withstoreandrouter)/*目录文件:project/app/web/page/app/views/index.vue*/preFetch({state,dispatch,commit}){//执行仅在服务器端;preFetch比创建的执行得更快returnPromise.all([dispatch('FETCH_ARTICLE_LIST_PRE')])},beforeMount(){//只在客户端执行;created执行速度比beforeMountletserverData=this.$store.state.serverData;if(serverData.articleList&&serverData.articleList.length>0){this.$store.commit('SET_ARTICLE_LIST',serverData.articleList);}else{returnPromise.all([this.$store.dispatch('FETCH_ARTICLE_LIST')]);}}页面配置设置页面:标题、关键字、描述;导入CSS、JS;pluginCss:数组;标头导入csspluginJs:数组;标头导入jspluginFooterJs:array;底部导入js
