不得不说,目前这个项目做的真是够久,在开发过程中遇到了一些坑,解决了分享出来给大家。 在各方面综合考虑之下,鄙人抛弃了各大多端开发框架,使用了 原生 的小程序框架进行开发。
前人掘坑、后人遭殃,祝各位早日成为大牛!!👻👻👻
👻自定义动态Tabbar导航栏
在默认的小程序开发中,定义tabbar,需要在app.json中配置如下json:
1"tabBar": { 2 ... 3 "list": [ 4 { 5 "text": "首页", 6 "iconPath": "/public/images/index.png", 7 "selectedIconPath": "/public/images/index-act.png", 8 "pagePath": "pages/job/index" 9 } 10 ... 11 ] 12}
一经配置,无法修改。你可以调用setTabBarItem 设置按钮文字、图片路径;就是无法动态设置跳转地址、tabbar个数。
解决方案
我们需要新建一个中间页面,用来控制所有tabbar,把tabbar要关联的页面,都用组件的方式来写,这样,我们只要在这一个页面里,写个fix在底部的tabbar样式,点击不同tab,显示不同组件。
json文件
1{ 2 "usingComponents": { 3 "home" : "/pages/job/index", // 首页 4 "company" : "/pages/company/company", // 公司 5 "message" : "/pages/chat/index", // 消息 6 "mine" : "/pages/mine/index", // 我的 7 "tabbar" : "/milfun/widget/custom-tab-bar", //自定义tabbar组件 8 } 9}
wxml文件
1<!-- wxml中,把页面设置成组件 --> 2<home wx:if="{{activeTab == 'home'}}">首页</home> 3<company wx:if="{{activeTab == 'company'}}">公司</company> 4<message wx:if="{{activeTab == 'message'}}">消息</message> 5<mine wx:if="{{activeTab == 'mine'}}">我的</mine> 6 7<!-- wxml中,自定义tabbar组件 --> 8<tabbar list="{{tabList}}" bindmytab="tabChange"></tabbar>
js文件
1Page({ 2 data: { 3 activeTab:'home' // company 、message、mine 4 }, 5 onLoad: function (options) { 6 let tmp = 1; // 用来控制显示不同方案的tabbar 7 if( tmp === 1 ){ // 显示第一套tabbar 8 this.setData({ 9 tabList:[ 10 { 11 "name": "...", 12 "text": "...", 13 "iconPath": "...", 14 "selectedIconPath": "...", 15 "pagePath": "..." 16 }, 17 ... 18 ] 19 }) 20 }else{ // 显示第二套tabbar 21 this.setData({ 22 tabList:[{},...] 23 }) 24 } 25 } 26})
上面展示的是中间页面的写法,那正常页面如何改成组件页面呢?
页面改成组件写法
其不同主要是在于js文件里面的写法不同,所以我们只看js部分:
正常写法
1Page({ 2 data: { 3 }, 4 onLoad: function (options) { 5 }, 6 onShow: function (options) { 7 }, 8 func1:function(e){ 9 console.log(e) 10 }, 11 func2:function(e){ 12 console.log(e) 13 }, 14})
组件写法
1Component({ 2 options: { // 为了使用全局css样式 3 addGlobalClass: true, 4 }, 5 data: {}, 6 /* 7 * 组件被创建时调用,等同于上方的 onLoad 8 */ 9 attached: function (options) { 10 }, 11 /* 12 * 组件内部方法,等同于上方的自定义方法 13 */ 14 methods: { 15 func1:function(e){ 16 console.log(e) 17 }, 18 func2:function(e){ 19 console.log(e) 20 }, 21 } 22})
这样,我们就实现了动态tabbar功能,tablist数据我们随时都可修改,怎么跳转,我们自己说了算!
👻输入框弹起页面上滑
遇见上面这个问题,我们的解决方案是:手动设置输入框位置。
js文件
1// 输入框获取焦点 2foucus:function (e) { 3 this.setData({typerHeight: e.detail.height}) 4}, 5// 输入框失去焦点 6blur:function () { 7 this.setData({typerHeight: 0}) 8},
wxml文件
1<view class="tc-board" style="bottom:{{typerHeight}}px" > 2 ...... 3</view>
这样,当输入框获取焦点时,会获取到键盘的高度,然后把输入框这个view的bottom样式,设置成你获取的高度,就完美的贴在输入框上方。当输入框失去焦点时,高度设置成0,输入框view又回到了页面的底部。
👻异步请求回调 + Token验证
为了避免在业务中书写繁杂的if else语句嵌套,或者回调函数
1// 方法一 2onLoad:function (e) { 3 // if嵌套 4 if(){ 5 if(){ 6 if(){ // do something } 7 } 8 } 9 10 // 回调陷阱 11 func1(data,func(){ 12 func2(data,func(){ 13 func3(data,func(){ 14 // do something 15 }) 16 }) 17 }) 18},
我的做法是,为方法添加promise,举个栗子🥗:
公共功能js文件
1/** 2 * 统一post请求接口 3 * @param {*} e “url,data,contentType,noOuth” 4 */ 5function post(e){ 6 // token 保存在缓存中,有需要时调取 7 let header = { 'Content-Type': contentType, 'Authorization':'Bearer ' + getCache('accessToken') } 8 9 // 封装在promise中 10 return new Promise(function (resolve, reject) { 11 wx.request({ 12 url: config.domain + e.url , // domain统一放在config中 13 data:e.data, 14 method: 'POST', 15 header: header, 16 success: res => { 17 // console.log(res) 18 if(res.data.code == 200 ){ 19 resolve(res.data) // 请求成功,返回数据 20 } 21 else{ 22 wx.showToast({ 23 title: res.msg, 24 icon: 'none', 25 duration: 1500, 26 }); 27 reject(res.data.msg) // 请求出错,显示错误 28 } 29 }, 30 fail: res => { // 请求失败 31 wx.showToast({ 32 title: '请求发送失败', 33 icon: 'none', 34 duration: 1500, 35 }); 36 } 37 }) 38 }) 39}
页面js文件
1// 方法一 2onLoad:function (e) { 3 fun.post({ url:'...',data:{...} }) 4 .then( res => console.log(res) ) // 步骤一 5 .then( res => console.log(res) ) // 步骤二 6 .then( res => console.log(res) ) // 步骤三 7 .catch( res => console.log(res) ) // 捕捉异常 8},
这样写起来思路清晰,优雅,感觉棒棒哒!
👻接口统一管理
有了上述的post接口,我们在开发中会有很多的请求接口,如果都写在页面中,难以管理,如有修改,要一个个页面找过去,比较麻烦,我的做法是:
在模块目录下新建一个js,用来保存所有接口信息。为什么在模块下呢?因为考虑到可能有不同的分包、如果都写在一起会太多,分太细又带来管理的不便,具体如何,请根据具体项目来操作。
api接口统一管理文件
1/** 2 * 该模块下所有接口 3 * 接口参数: 4 * url: just url 5 * contentType: default:false( use urlencoded ) or true( use json ) 6 * noOuth: default:false( hase Authorization ) or true( no Authorization ) 7 */ 8const constApi = { 9 // 获取用户信息 10 getUserInfo : { // 定义接口调用的名字 11 url: 'api/v1/userinfo' 12 }, 13 // 获取用户设置 14 getUserSetting: { 15 url: 'api/v1/usersetting', 16 outh:true // 需要鉴权 17 } 18} 19 20/** 21 * 对外接口统一调用 22 * @param {*} name 在api文件中的key 23 * @param {*} data 要post的数据 24 */ 25const http = async function(key,data){ 26 let api = constApi[key]; 27 let response = await fun.post({ 28 url:api.url, 29 data:data, 30 contentType:api.contentType, 31 outh:api.noOuth 32 }) 33 return response 34} 35 36export default http
使用方法
1// 导入api文件 2import Api from './api-index.js' 3 4onLoad:async function (e) { 5 // 用法一 6 Api('getUserInfo ',{ 7 userId:1, 8 userPwd:123456, 9 ... 10 }) 11 .then( res => console.log(res) ) 12 ... 13 14 // 用法二 15 let tmp = await Api('getUserInfo',{...}) 16 this.setData({ list: tmp }) 17},
到时候如果接口修改了,或者地址更换了,就不用满大街去找那些页面用到了接口,一个个修改。只需要在api-index.js中,统一修改和管理了。
这次先分享这些给大家,后续会继续给大家分享有用的开发经验,已经爬过的坑就不要再爬了。
谢谢大家!👻👻👻
本文转自 https://juejin.cn/post/6865920270218035214,如有侵权,请联系删除。
