uni-app开发小程序总结

1,494 阅读8分钟

项目构建

使用npm包 使用npm init -y初始化npm项目,然后使用你喜欢的方式(npm、yarn)安装你需要的npm包;非h5平台的项目不支持使用到dom操作的包。

使用小程序组件

使用小程序组件需要在pages.json中进行配置,在具体的页面中引用:

{  
  "path":"pages/Home/index",  
  "style": {  
    "navigationBarTitleText": "首页",  
    "usingComponents": {  
      "van-search": "/wxcomponents/vant-weapp/search/index"  
    }  
  }  
}

在全局使用:

"globalStyle": {  
  "navigationBarTextStyle": "black",  
  "navigationBarTitleText": "uni-app",  
  "navigationBarBackgroundColor": "#F8F8F8",  
  "backgroundColor": "#F8F8F8",  
  "usingComponents": {  
    "van-button": "/wxcomponents/vant-weapp/button/index",  
    "icon": "/wxcomponents/vant-weapp/icon/index",  
    "van-search": "/wxcomponents/vant-weapp/search/index"  
  }  
},

注意 引用的组件名必须为小写,不然可能会出现无法找到组件的问题

条件编译

官网已经有比较详细的说明了,通过特殊的注释语法来实现代码级别的条件编译,语法是以 #ifdef#ifndef%PLATFORM% 开头,以 #endif结尾。

需要特别说明下的是整体目录条件编译,下项目根目录建立platforms文件夹,然后根据不同的平台建立不同的文件夹(如手机端创建app-plus文件夹),在pages配置path就会根据不同的平台加载不同的页面了。

{  
    "path": "platforms/app-plus/speech/speech",  
    "style": {  
        "navigationBarTitleText": "语音识别"  
    }  
}

上面配置的页面只会在app-plus相关平台加载。

easycom组件模式 hbuilder支持easycom组件模式,一般使用组件我们需要安装、引用、注册三个步骤。easycom组件模式下,你只需将组件下载到components目录下,并符合components/组件名称/组件名称.vue的目录结构,你就可以直接在页面中使用组件,而不用导入,注册;并且没有使用到的组件会在打包时自动剔除。

easycom也支持自定义配置,具体可以查看官方文档

开发项配置

在我们进行开发时,我们可以指定启动页面,启动项目需要在pages.json中配置,可以配置多项,然后运行时进行选择。

"condition" : { //模式配置,仅开发期间生效  
 "current": 0, //当前激活的模式(list 的索引项)  
 "list": [  
   {  
     "name": "Market", //模式名称  
     "path": "pages/Cart/index", //启动页面,必选  
     "query": "" //启动参数,在页面的onLoad函数里面得到  
   }  
 ]

注意:query启动参数并不像官方文档里说的,可以在onLoad函数中获取到,后面我们也会提到这个问题和相应的解决方法。

环境变量

内置环境变量process.env.NODE_ENV,我们可以通过这个之判断当前的运行环境,实现在不同的环境下使用不同的方式。

const isDev = process.env.NODE_ENV === 'development'  
const http = axios.create({  
  baseURL: isDev ? DEV : PRO,  
  timeout: 3000  
})

开发技巧

本地图片

uni-app支持使用本地图片,本地图片可以直接在image标签中引入使用,也可以作为背景图片使用;本地图片会在不支持本地图片的平台(小程序)中,自动转换为base64的格式,但是要求图片必须小于40kb;使用图片的引用路径应该使用~@开头,不然在window中可能出现找不到资源的问题。

通过image标签使用本地图片,图片会以base64的格式存储在打包后的vendor.js文件中,这个文件会在小程序加载时引用,如果使用太多的本地图片会导致小程序首次运行速度变慢;通过背景图片的方式使用,图片会存储在引用文件的样式文件中,会增加包的大小,但是对启动速度的影响不大。

体积较大的图片建议使用网络图片,体积小的图片也应该尽量不要在image标签引用,而是以背景的图片的形式来使用。

小程序分享

小程序分享是通过点击open-type为share的button或者页面的分享按钮来触发的,分享的内容是页面onShareAppMessage的返回值,返回值包含title-分享标题,path-分享路径,imageUrl-分享图片,onShareAppMessage只能定义在页面上,在组件中定义是没有用的。

如果你分享的信息是动态的,你可以通过按钮的data-绑定数据:

<button open-type="share"   
        :data-title="***"   
        :data-imgurl="***"  
        :data-path="***">  
</button>

然后在回调函数中可以获取数据:

onShareAppMessage(data) {  
    let dataset = data.target.dataset  
    return {  
        title: dataset.title,  
        imageUrl: dataset.imgurl,  
        path: dataset.path  
    }  
},

生命周期

在uni-app中,有些时候生命周期的表现会出人意料,让人措手不及:

通过小程序分享时,我们往往会带上路由参数,uni-app的启动选项也是可以配置参数,正常的路由跳转我们可以在onLoad中获取参数,但是在刚才我们说的两种场景中,在onLoad中我们是无法获取参数的,只能在onLauch中获取,如果需要获得路由参数,我们只能在onLauch中获取,然后通过其他方式(vuex或者其他方式)保存,然后在需要的地方获取使用。

tab页面与其他页面的生命周期也不同一样,tab页面切换不会触发onLoad事件,而打开一般的页面会触发onLoad页面。

back返回上一页时,一般是不会触发onLoad,但是会触发onShow。

在选择图片时,打开相册,再回到小程序会触发小程序应用的onShow。

上传图片 uni中可以使用uni.uploadFile接口上传文件:

uni.chooseImage({  
    success: (chooseImageRes) => {  
        const tempFilePaths = chooseImageRes.tempFilePaths;  
        uni.uploadFile({  
            url: 'https://www.example.com/upload', //仅为示例,非真实的接口地址  
            filePath: tempFilePaths[0],  
            name: 'file',  
            formData: {  
                'user': 'test'  
            },  
            success: (uploadFileRes) => {  
                console.log(uploadFileRes.data);  
            }  
        });  
    }  
});

如果你使用了第三方的对象存储OSS你也可以使用uni.uploadFile实现直传:

配置Bucket跨域访问;客户端进行表单直传到OSS时,会从浏览器向OSS发送带有Origin的请求消息。OSS对带有Origin头的请求消息会进行跨域规则(CORS)的验证。因此需要为Bucket设置跨域规则以支持Post方法。在OSS管理控制台,修改相关规则配置。 配置外网域名到小程序的域名白名单;在OSS管理控制台的访问域名区域查看Bucket域名,然后登录小程序平台,配置小程序的上传域名白名单,如果不配置不会影响开发环境的上传,但是发布(包含发布体验版)的小程序会无法上传。 根据平台要求,生成上传需要的信息,使用uni.uploadFile上传

import md5 from 'md5'  

export default ({ dir, host, expire, signature, policy, accessid }) => {  
  return new Promise((resolve, reject) => {  
    uni.chooseImage({  
      count: 1,  
      success: (res) => {  
        const filePath = res.tempFilePaths[0]  

        const ext = filePath.replace(/([\S\s]+)\.(\S+)$/, '$2')  
        const key = `${dir}/${md5(Math.random())}.${ext}` // 文件名MD5重命名  
        uni.uploadFile({  
          url: host,  
          filePath,  
          name: 'file',  
          formData: {  
            policy,  
            OSSAccessKeyId: accessid,  
            signature,  
            expire,  
            key,  
          },  
          success: () => {  
            resolve(`${host}/${key}`) // 返回图片地址  
          },  
          fail (err) {  
            reject(err)  
          }  
        })  
      },  
      fail (err) {  
        reject(err)  
      }  
    })  
  })  
}

如果使用的是阿里云可以参考这份文档-小程序直传实践

小程序顶部适配

在某些场景下,我们需要自定义标题栏,但是标题栏的高度在不同型号的手机中可能是不相同的,这里我们能可以通过微信小程序右上角的胶囊位置来做适配。

我们可以通过uni.getMenuButtonBoundingClientRect()获取到胶囊的相关信息menuButton,menuButton包含胶囊的位置信息top、bottom、left、right,和胶囊尺寸信息width、height;我们通过这些信息就可以计算出合适的标题栏高度。

滚动

页面级别的滚动由pages.json中page的style项进行配置,相关值如下:

属性 类型 默认值 描述 disableScroll Boolean false 设置为 true 则页面整体不能上下滚动(bounce效果),只在页面配置中有效,在globalStyle中设置无效 enablePullDownRefresh Boolean false 是否开启下拉刷新,触发页面的onPullDownRefresh onReachBottomDistance Number 50 页面上拉触底事件触发时距页面底部距离,单位只支持px,会触发页面的onReachBottom 页面生命周期中除了onPullDownRefresh和onReachBottom,还有onPageScroll,用于监听页面滚动,参数是一个对象,包含属性scrollTop,表示页面在垂直方向已滚动的距离(单位px)。

可视化滚动区域需要通过scroll-view来实现,通过css属性overflow设置滚动,在真机上无法滚动。

scroll-view使用竖向滚动的时候需要一个固定高度,这个高度可以是calc高度或者是flex。

scroll-view的滚动条设置,可通过css的-webkit-scrollbar自定义,包括隐藏滚动条。

在ios中如果设置了scroll-view,会出现橡皮筋回弹效果,页面的回弹效果可以通过disableScroll: true取消,但是如果是scroll-view标签,你只能设置scroll-y为false,如果即需要滚动有想要取消回弹效果,可以通过监听scroll-view的相关事件,判断滚动状态,在回弹的情况时,设置scroll-y为false,来阻止回弹。

详情参考:小程序取消橡皮筋回弹效果解决方案及坑总结

uni还提供uni.pageScrollTop方法,将页面滚动到目标位置-说明

其他

开启微信调试工具vConsole,并使用条件编译设置只在小程序中使用:

//#ifdef MP-WEIXIN  
wx.setEnableDebug({  
    enableDebug: false  
})  
//#endif

使用css样式,扩大可点击区域:

position: relative;  
&:before {  
    content: '';  
    position: absolute;  
    top: -10px; bottom: -10px; left: -10px; right: -10px;  
};