起因:这个项目分别需要开发一个手机端监测app(仅限安卓手机)和一个web端后台管理系统。对于web端我是比较熟悉的,但是对开发一个app很陌生,所以不知道如何下手?想必大家也经常在开发一个新的东西的时候也经常遇到不知如何选择哪个脚手架问题、因为一旦对方的脚手架不成熟的话,在开发的时候真的容易遇到很多无法即时排查和处理的bug。
所以如何尽可能规避其中的风险,我这里总结了一些方法,或许可以通过我的例子给大家一些参考。
那接下来,我将从框架选型、项目搭建、项目完善、项目落地四个角度分别总结我自己的经验,如果有说的不对的地方,也请大家多多指出和提出你宝贵的建议。
1.框架选型
在框架选型的过程中,我碰到一个这样的难题,因为我对react比较熟悉,而对于vue来说只能算是了解。对比下来想用uni-app来完成这个App,而uni-app搭建原生app是需要使用vue的,所以这正是我纠结要不要选这个框架的点。通过反复考量,我最终还是选择了用uni-app来搭建。
因为我觉得我们应该敢于尝试新的事物,需要摆脱舒适区,向拉伸区靠拢。
这样我们才能学到更多,不单单只是钱财,还有技能的成长!毕竟知识才是无价的。但是吧,大家还是要考虑多方因素,项目周期很短还是不要冒这个风险。
但是选完框架后,发现后面不知道该如何起手,因为对uni-app来说我简直更是一个小白。就新建项目而言,我就纠结了半天。
所以拿官网解释做个对比呗。
-
uni-app:开发一次,同时发布为Android、iOS原生App、小程序、H5等多个平台。
-
Wap2App:wap2app 是一个将现有M站(也称手机wap站,区别于pc的web站)快速发布成 App 的增强方案,通过 DCloud 的 wap2app 框架,进行简单的配置和必要的编程,即可完成M站的体验强化,达到原生应用的功能体验,进而再发布为原生安装包或流应用(给网页套个app外壳)。
-
5+App:HTML5 Plus移动App,简称5+App,是一种基于HTML、JS、CSS编写的运行于手机端的App,这种App可以通过扩展的JS API任意调用手机的原生能力,实现与原生App同样强大的功能和性能。
具体细节可以查看对比相关文档
在查看了gitee中的很多相关demo后,仔细对比了一下,我觉得使用uni-app或会最好!并且我也是使用了积木jeecg的demo,这也是我标题起从0.5到1的缘故,我认为站在巨人的肩膀上我们的才能把项目做的更好。它的组件对于我来说很齐全,也很契合我的项目,所以站在巨人的肩膀上开发真的很快。到这里,框架选型对于我来说算是比较顺利的!
顺便在这里补充一点,开发这个需要下载HBuilderX软件,使用下来感觉对比其他ide比较不习惯吧,我都是打开其他的ide编写代码,然后用这个软件运行。
2.项目搭建
2.1熟悉框架uniapp结构
下面是我照搬jeccg-uniapp项目简介来给大家梳理一下项目结构。
1.一个uni-app工程,默认包含如下目录及文件:
┌─components uni-app组件目录
│ └─comp-a.vue 可复用的a组件
├─hybrid 存放本地网页的目录,详见
├─platforms 存放各平台专用页面的目录,详见
├─pages 业务页面文件存放的目录
│├─index
││ └─index.vue index页面
│├─list
││ └─list.vue list页面
├─static 存放应用引用静态资源(如图片、视频等)的目录,**注意:**静态资源只能存放于此
├─wxcomponents 存放小程序组件的目录,详见
├─main.js Vue初始化入口文件
├─App.vue 应用配置,用来配置App全局样式以及监听 应用生命周期
├─manifest.json 配置应用名称、appid、logo、版本等打包信息,详见
└─pages.json 配置页面路由、导航条、选项卡等页面类信息,详见
2.这个项目包含的非uni-app工程默认的其他目录
┌─_docs 项目的一些文档日志存放目录
├─api 请求服务端的接口文件存放目录
├─common 通用的文件
│├─luch-request 存放的是大神封装的request请求插件目录
│├─router 存放路由配置的目录
│├─service 存放请求拦截和开发环境配置
│├─util 存放的一些工具类
├─plugin 存放项目插件的目录
└─store 状态管理目录
3.这个项目完整工程目录
2.2自定义tab导航栏和状态栏配置
用原生的tab导航栏和状态栏自然是很不错的,但是这样就没法个性化定制了。因为客户需要在顶部状态栏带有自己的品牌logo,加上名称和单位等三种情况(如下图这样),所以用原生的话好像不能实现,也或者我没找到,最终决定自己尝试写一下。
那我们开始实现我们所需要的效果,首先我们第一步要做的便是把原生的先禁掉。
2.2.1自定义tab导航栏
- 原生tabBar导航栏配置
// 配置tabbar导航栏
"tabBar": {
"borderStyle": "black",
"selectedColor": "#FB7299",
"color": "#444444",
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "static/tabbar/index.png",
"selectedIconPath": "static/tabbar/index-selected.png",
"text": "主页"
},{
"pagePath": "pages/mine/mine",
"iconPath": "static/tabbar/my.png",
"selectedIconPath": "static/tabbar/my-selected.png",
"text": "我的"
}
]
}
2.自定义tabBar,首先得把上方tabBar配置去掉,然后我们得把这个tabBar写在主页,并且我们启动的第一个页面也得是主页,如下:
(1)先设置启动主页
"pages": [
//pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
}
},
...
]
(2)在主页写tabBar,这里我使用了colorui组件库,具体使用可以参考colorui底部导航栏
我们的代码如下
<view class="cu-bar tabbar bg-white shadow foot">
<view :class="PageCur=='warningInfo'?'action text-blue':'action text-gray'" @click="NavChange"
data-cur="warningInfo">
<view class='iconfont iconfont-bottom-xs icon-gaojing'></view>
告警信息
</view>
<view :class="PageCur=='onAccess'?'action text-blue':'action text-gray'" @click="NavChange" data-cur="onAccess">
<view class='iconfont iconfont-bottom-xs icon-jiankong'></view>
实时监控
</view>
<view :class="PageCur=='inspectionTasks'?'action text-blue':'action text-gray'" @click="NavChange"
data-cur="inspectionTasks">
<view class='iconfont iconfont-bottom-xs icon-xunjian'></view>
巡检任务
</view>
<view :class="PageCur=='people'?'action text-blue':'action text-gray'" @click="NavChange"
data-cur="people">
<view class='iconfont iconfont-bottom-xs icon-yonghu'></view>
个人
</view>
</view>
(3)切换tabBar时动态显隐单页面
NavChange: function (e) {
this.PageCur = e.currentTarget.dataset.cur
},
<view :style="{'margin-top':barHeight+'px'}">
<people v-if="PageCur=='people'" :key="'people'+commponent1Key"></people>
<onAccess v-if="PageCur=='onAccess'" :key="'onAccess'+commponent2Key"></onAccess>
<warningInfo v-if="PageCur=='warningInfo'" :key="'warningInfo'+commponent3Key"></warningInfo>
<inspectionTasks v-if="PageCur=='inspectionTasks'" :key="'inspectionTasks'+commponent4Key"></inspectionTasks>
</view>
到这里你的tabBar就完成了。
(4)我们不能说界面做完了就完成了,我们还得学习下colorui tabbar的实现方法,这样才是真正的学到呀!
- .tabbar.foot通过position: fixed;bottom:0固定定位到最底部.
- .tabbar使用弹性布局display:flex,主轴(横轴)justify-content:
space-between使子节点平分间隔父节点
- .tabbar次轴(竖轴)align-items:center使子节点在垂直方向居中
- 子节点.action,flex:1,平分父节点空间
-
设置高度height:calc(100upx + env(safe-area-inset-bottom) / 2)和设置padding-bottom:
calc(env(safe-area-inset-bottom) / 2),使tabbar适配ios. -
单个tab适中:水平text-align: center,图标和文字居中。line-height:1使其上下间隔一致。
注:line-height定义: 与 font-size 的计算值之差(在 CSS 中成为“行间距”)分为两半,分别加到一个文本行内容的顶部和底部
.cu-bar {
display: flex;
position: relative;
align-items: center;
min-height: 100upx;
justify-content: space-between;
}
.cu-bar.foot {
position: fixed;
width: 100%;
bottom: 0;
z-index: 1024;
box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
}
.cu-bar.tabbar {
padding: 0;
height: calc(100upx + env(safe-area-inset-bottom) / 2);
padding-bottom: calc(env(safe-area-inset-bottom) / 2);
}
.cu-bar.tabbar.shadow {
box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
}
.cu-bar.tabbar .action {
font-size: 22upx;
position: relative;
flex: 1;
text-align: center;
padding: 0;
display: block;
height: auto;
line-height: 1;
margin: 0;
background-color: inherit;
overflow: initial;
}
2.2.2自定义顶部导航栏
- 原生导航栏—全局通用配置,在pages.json的
globalStyle
里进行各个参数配置,把navigationStyle设置为custom
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "Hello uniapp",
"navigationBarBackgroundColor": "#F8F8F8",
"navigationStyle": "custom", // 关键的全局取消原生导航栏
"backgroundColor": "#F8F8F8",
"backgroundColorTop": "#F4F5F6",
"backgroundColorBottom": "#F4F5F6"
},
2.单页配置
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "主页",
"navigationStyle":"custom", //第一种单页不启用系统导航
"app-plus":{
"titleView":false // 第二种,不启用系统导航,只对App生效
}
}
}
3.自定义顶部导航栏
- App.vue文件不同条件下获取状态高度和计算导航高度
// #ifndef MP
Vue.prototype.StatusBar = e.statusBarHeight;
console.log(e)
if (e.platform == 'android') {
Vue.prototype.CustomBar = e.statusBarHeight + 50;
} else {
Vue.prototype.CustomBar = e.statusBarHeight + 45;
}
;
// #endif
// #ifdef MP-WEIXIN
Vue.prototype.StatusBar = e.statusBarHeight;
let custom = wx.getMenuButtonBoundingClientRect();
Vue.prototype.Custom = custom;
Vue.prototype.CustomBar = custom.bottom + custom.top - e.statusBarHeight;
// #endif
// #ifdef MP-ALIPAY
Vue.prototype.StatusBar = e.statusBarHeight;
Vue.prototype.CustomBar = e.statusBarHeight + e.titleBarHeight;
// #endif
- html:插槽分别可以插入左中右自定义插槽组件
<view class="cu-custom" :style="[{height:CustomBar + 'px',zIndex:zIndex}]">
<view class="cu-bar fixed" :style="style" :class="[bgImage!=''?'none-bg text-white bg-img':'',bgColor]">
<view class="action" @tap="BackPage" v-if="isBack">
<text class="cuIcon-back"></text>
<slot name="backText"></slot>
</view>
<view class="content" :style="[{top:StatusBar + 'px',fontsize:'40upx'}]">
<slot name="content"></slot>
</view>
<view class="action">
<slot name="right"></slot>
</view>
</view>
</view>
- 计算属性计算高度和离顶部状态栏的高度。
computed: {
style() {
var StatusBar= this.StatusBar;
var CustomBar= this.CustomBar;
var bgImage = this.bgImage;
var style = `height:${CustomBar}px;padding-top:${StatusBar}px;`;
if (this.bgImage) {
style = `${style}background-image:url(${bgImage});`;
}
return style
}
},
- 和自定义tabbar一样,把顶部导航栏置于顶部。
.cu-bar.fixed,
.nav.fixed {
position: fixed;
width: 100%;
top: 0;
z-index: 1024;
box-shadow: 0 1upx 6upx rgba(0, 0, 0, 0.1);
}
2.2.3去除顶部状态栏
1.单个页面隐藏
- 页面onLoad() 函数中添加
// #ifdef APP-PLUS
plus.navigator.setFullscreen(true);
// #endif
- 页面onUnload() 函数中添加
// #ifdef APP-PLUS
plus.navigator.setFullscreen(false);
// #endif
2.整个应用隐藏
- App.vue中 onLaunch() 函数中添加
// #ifdef APP-PLUS
plus.navigator.setFullscreen(true);//隐藏状态栏
// #endif
到这里项目的基础外型已经完善。下面我们可以从单页面渐渐完善和优化了!
2.3字体图标引入
1.在iconfont新建一个项目,挑选需要的图标,加入购物车,添加至项目。
2.下载iconfont包
3.解压后如下文件
3.放入项目static目录
4.修改刚刚下载的iconfont.css文件,如下:
5.使用图标
访问文件刚刚下载的demo_index.html文件获得iconfont Symbol码
使用示例如下:
<view class='iconfont icon-jiankong'></view>
监控
</view>
后续请看下文…
原文链接:https://juejin.cn/post/7245184987531214908 作者:柳杉