当前位置: 首页>后端>正文

uni-app 踩坑之路

这里主要使用uni-app来把普通h5项目转成app项目。由于头一次使用,踩了很多坑。终于熬到app上线,来这总结下h5转app需要注意的点.方便后续再转项目。
持续更新~~

没有window 和 document对象

感受最大的就是这两点.

1.就是说比如获取元素不能使用document.getElementById

uni-app里这样查找元素

// 通过refs找到元素
<div ref='mydiv'></div>

<script>
   onLoad() {
    let element = this.$refs.mydiv
}
<script>

// 通过uni-api获取
const query = uni.createSelectorQuery().in(this);
query.select('#press').boundingClientRect(data => {
    console.log(data)
    this.pergressWidth = parseInt(data.width)
}).exec();

/* data的值参考如下
    data ===> {
            'height': 21,
            'dataset': {},
            'right': 534.2222290039062,
            'id': 'press',
            'bottom': 246,
            'width': 534.2222290039062,
            'left': 0,
            'top': 225
        }
*/

// 根据类名查找元素
let doms = query.selectAll('.press')
doms.fields({
    rect: true, // 是否返回节点布局信息{top,bottom,right,left}
    size: true, // 返回尺寸信息 width, height
    scrollOffset: true, // 返回节点滚动信息 scrollTop scrollLeft
     },function(res){ // res 包含第一个参数中指定true的相关信息
}).exec(function() {// 节点信息获取成功后的回调
})

2.不能通过window获取设备信息,比如窗口宽高

uni-app API的获取方式

uni.getSystemInfo({
    success(res) {
        // 成功了调用的函数
        console.log(res.appId); 
        console.log(res.appName);
        console.log(res.appVersion);
        console.log(res.appLanguage);
        console.log(res.appVersionCode);
        console.log(res.browserName);
        console.log(res.browserVersion);
        console.log(res.deviceId);
        console.log(res.deviceBrand);
        console.log(res.deviceModel);
        console.log(res.deviceType);
        console.log(res.deviceOrientation);
        console.log(res.devicePixelRatio);
        console.log(res.hostName);
        console.log(res.hostVersion);
        console.log(res.hostLanguage);
        console.log(res.hostTheme);
        console.log(res.hostPackageName);
        console.log(res.hostSDKVersion);
        console.log(res.osName);
        console.log(res.osVersion);
        console.log(res.osLanguage);
        console.log(res.osTheme);
        console.log(res.osAndroidAPILevel);
        console.log(res.romName);
        console.log(res.romVersion);
        console.log(res.uniPlatform);
        console.log(res.uniCompileVersion);
        console.log(res.uniRuntimeVersion);
        console.log(res.ua); // userAgent标识
        console.log(res.screenWidth); // 屏幕宽度
        console.log(res.screenHeight); // 屏幕高度
        console.log(res.windowWidth); // 屏幕可使用宽度
        console.log(res.windowHeight); // 屏幕可使用高度
        console.log(res.windowTop); // 可使用窗口顶部位置
        console.log(res.windowBottom); // 可使用窗口底部位置
        console.log(res.statusBarHeight); // 手机状态栏高度
        console.log(res.safeArea); // 竖屏正方向下的安全区域
        console.log(res.safeAreaInsets); // 竖屏正方向下的安全区域插入位置
    },
    fail (err) { // 失败了调用
        },
    complete () { // 成功失败都会调用
        }
})

// 他还有个【同步方法】
let ref = uni.getSystemInfoSync() // 返回结构同上

类似的方法还有
uni.getWindowInfo()
它返回的参数如下


uni-app 踩坑之路,第1张

app生命周期 && 全局数据

uni-app 踩坑之路,第2张

这些周期对应整个app,即全局的周期控制在App.vue中定义这些函数即可控制。
还有个全局对象globallData, 也是在App.vue中用来定义全局数据的

<script>  
    export default {  
        globalData: {  
            text: 'text'  
        }
    }  
</script>
<script>  
    export default {  
        onLoad(option) {
        //获取这样获取
        console.log(getapp().globalData.text)

    }
    }
</script>

默认不支持 axios

需要做以下配置才行

// 只是app端不支持,需要做以下处理
axios.defaults.adapter = function(config) {
     return new Promise((resolve, reject) => {
            var settle = require('axios/lib/core/settle');
            var buildURL = require('axios/lib/helpers/buildURL');
            var buildFullPath = require('axios/lib/core/buildFullPath');
            let fullurl = buildFullPath(config.baseURL,config.url)
            uni.request({
                method: config.method.toUpperCase(),
                url: buildURL(fullurl, config.params, config.paramsSerializer),
                header: config.headers,
                data: config.data,
                dataType: config.dataType,
                responseType: config.responseType,
                sslVerify: config.sslVerify,
                complete:function complete(response){
                    response = {
                      data: response.data,
                      status: response.statusCode,
                      errMsg: response.errMsg,
                      header: response.header,
                      config: config
                    };
                    
                settle(resolve, reject, response);
                }
            })
        })
}

路由跳转 不支持router 更不支持链接

它的跳转发方式与小程序如出一辙

// 基础的就是
// a标签需要替换成 navigator 标签,href属性换成url属性;animation-type规定跳转动画类型,可选值有slide-in-left,pop-in, zoom-out,zoom-fade-out,none等;animation-duration持续时间
<navigator animation-type='pop-in' animation-duration='300' url='../test/test'>navigator</navigator>

uni.navigateTo({
    url: '/pages/index?a=5&b=7', // 【只有这一个必传参数】,跳转的页面,参数要param形式传递
    // 接收参数要在跳转到的页面的onLoad(option)函数的option里接收:option.a
    animationType: 'fade-in', // 动画
    animationDuration: '300', // 动画时间
    events: {
            // 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
            acceptDataFromOpenedPage: function(data) {
                console.log(data)
            },
            someEvent: function(data) {
                console.log(data)
         }
            ...
    },
    success(res) {
        // 调用成功执行,可以通过res.eventChannel继续像跳入的页面传数据       
    }
})
// 跳入页面可以通过如下操作来给来源页面传数据
onLoad: function(option) {
  // #ifdef APP-NVUE
  const eventChannel = this.$scope.eventChannel; // 兼容APP-NVUE
  // #endif
  // #ifndef APP-NVUE
  const eventChannel = this.getOpenerEventChannel();
  // #endif
  eventChannel.emit('acceptDataFromOpenedPage', {data: 'data from test page'});
  eventChannel.emit('someEvent', {data: 'data from test page for someEvent'});
  // 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据
  eventChannel.on('acceptDataFromOpenerPage', function(data) {
    console.log(data)
  })
}
// 【返回】 可以不传参数,默认返回上一级
uni.navigateBack({
    delta: 1, // 返回几级,级数多于当前已有的级数回到首页
    animationType: 'pop-in',
    animationDuration: '500', 
    success() {},
    fail(){},
    complete(){}
})

// 替换当前链接
uni.redirectTo({
    url: '/pages/mine', // 必传参数,规则同navigateTo
    success(){},
    fail(){},
    complete(){} 
})

没有img标签 使用 <image> 标签代替

uni-app里没有<img 标签,所以转换的时候图片是无法显示的,直接全局替换标签名为<image 即可,其他参数无差别

上传图片或文件逻辑需要更改

选择图片(可选拍照)需要调用uni-app原生的接口: uni.chooseImage({})
上传文件 也需要原生接口: uni.uploadFile({})

// 首先选择图片
uni.chooseImage({
    count: 9, // 可选;的图片数量,默认9
    sizeType: ['original', 'compressed'], // 可选;original 原图,compressed 压缩图,默认都有
    extension: ['.jpg','.png],// 可选;根据拓展名过滤
    sourceType: ['album', 'camera'], // 可选;来源;camera 相机 album相册,默认都有
    crop:{
        quality: 95, // 1-100 的数字,图像质量
        width: 500, // 单位px
        height: 500, 
        resize: true, // 默认true,将width height值作为真实像素值
    },// 可选;设置图像裁剪参数, 如果有sizeType则失效
    success (res) {
        // 获取图片成功回调
        res:{ // 返回值结构
            tempFilePaths: [''], // 所有图片的路径列表
            tempFiles: [file,file]// 所有图片的file列表
        } 
    }
})

// 然后是上传图片
uni.uploadFile({
      url: url, // 上传的链接,完整链接
      header: { // 正常设置的header,不能设置referrer
        token,
        'Content-Type': 'multipart/form-data'
      },
      filePath: data.file, // 要上传的文件路径,就是上边的tempFilePaths中某一项的值
      name:'file', // 服务器接收的key 名字
      onUploadProgress (progress){ // 上传进度回调函数, 可以计算进度
        progress.loaded // 文件已经上传的数量
        progress.total // 文件所有的字节数
    },
      success(res) {
    // 返回的 res的data里才是服务器处理的结果,如果服务器返回的json,需要自己手动转化下
        let data = JSON.parse(res.data)
        
        if (data.code != 200) {
          Message({
            type: 'error',
            message: data.message || '未知错误~'
          })
        }
        if (callback) {callback(data)}
        resolve(data)
      },
      fail (err) {
        if (callback) {callback(err)}
        reject(err)
      },
      complete () {}
    })

https://www.xamrdz.com/backend/3mm1931365.html

相关文章: