HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

终于学会了制作小程序和app开发教程!!!

终于学会了制作小程序和app开发教程!!!

传说中的复制粘贴大法

原来可以如此简单 学会以后终于不在求人了

B站直达地址

终于学会了制作小程序和app开发教程!!!

传说中的复制粘贴大法

原来可以如此简单 学会以后终于不在求人了

B站直达地址

web2app vue应用 back 回退处理

Vue
if (window.plus) {  
  plusReady();  
} else {  
  document.addEventListener("plusready", plusReady, false);  
}  
// 扩展API准备完成后要执行的操作  
function plusReady() {  
  console.log("plus ready");  

  let click_back_time = Date.now();  
  /** 监听返回键 */  
  plus.key.addEventListener(  
    "backbutton",  
    () => {  

      if (/** 顶层页面 可以自己改成其他的meta参数,自己在router中定义是否为顶层页面 */ router.app.$route.meta.title.hide_back) {  
        /** 2s 内连续两次回退 退出应用 */  
        if (Date.now() - click_back_time > 2 * 1000) {  
          Toast("继续点击返回将退出应用");  
          click_back_time = Date.now();  
        } else {  
          plus.runtime.quit();  
        }  
      } else {  
        router.back();  
      }  
    },  
    false,  
  );  
}
继续阅读 »
if (window.plus) {  
  plusReady();  
} else {  
  document.addEventListener("plusready", plusReady, false);  
}  
// 扩展API准备完成后要执行的操作  
function plusReady() {  
  console.log("plus ready");  

  let click_back_time = Date.now();  
  /** 监听返回键 */  
  plus.key.addEventListener(  
    "backbutton",  
    () => {  

      if (/** 顶层页面 可以自己改成其他的meta参数,自己在router中定义是否为顶层页面 */ router.app.$route.meta.title.hide_back) {  
        /** 2s 内连续两次回退 退出应用 */  
        if (Date.now() - click_back_time > 2 * 1000) {  
          Toast("继续点击返回将退出应用");  
          click_back_time = Date.now();  
        } else {  
          plus.runtime.quit();  
        }  
      } else {  
        router.back();  
      }  
    },  
    false,  
  );  
}
收起阅读 »

uni.createSelectorQuery().in(this).select(".test"); select()里面不支持数字和中文如何解决,

uni.createSelectorQuery().in(this).select(".test");select()里面不支持数字和中文如何解决,DOMException: Failed to execute 'matches' on 'Element': '#2019-09' is not a valid selector. 有没有什么方法,我想获取dom 的top,可以在app ios 兼容的

继续阅读 »

uni.createSelectorQuery().in(this).select(".test");select()里面不支持数字和中文如何解决,DOMException: Failed to execute 'matches' on 'Element': '#2019-09' is not a valid selector. 有没有什么方法,我想获取dom 的top,可以在app ios 兼容的

收起阅读 »

Android uni小程序SDK集成原生功能模块教程

unimpsdk unimp uni小程序sdk uni小程序

Android uni小程序SDK集成 原生功能模块

SDK 提供了丰富的原生能力,您可根据需求自行添加功能模块,各功能模块所需的依赖库及资源文件,在uniMPSDK/Features目录中
目录结构

|-- uniMPSDK/Features  
    |-- Feature 依赖库说明.xls // 功能模块配置表  
    |-- libs                // 各功能模块的依赖库存放位置

请参考 Feature 依赖库说明.xls 配置表,添加模块所需依赖。修改项目相关配置信息;

集成方式

下面以 map 模块为例

首先查看Feature 依赖库说明.xls 表格说明需要添加amap-libs-release.aar,map-amap-release.aar两个库文件 及其AndroidManifest.xml等配置!

将amap-libs-release.aar,map-amap-release.aar两个库文件拷贝到项目中。主Module中的libs下。

地图依赖库文件拷贝完毕后。需要在build.gradle配置导入你引用的两个库文件。

    implementation files('libs/map-amap-release.aar')  
    implementation files('libs/amap-libs-release.aar')

参考Feature 依赖库说明.xls 中Map配置信息修改工程项目:

  • 修改AndroidManifest.xml 增加以下权限及配置
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>  
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>  
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>  
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>  
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
<uses-permission android:name="android.permission.INTERNET"/>  
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  
<uses-permission android:name="android.permission.READ_LOGS"/>  
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>  

<meta-data android:name="com.amap.api.v2.apikey" android:value="%申请高德地图apikey%"/>
  • 修改dcloud_properties.xml配置

在dcloud_properties.xml添加以下信息

features节点  
<feature name="Maps" value="io.dcloud.js.map.amap.JsMapPluginImpl"></feature>  
services节点  
<service name="Maps" value="io.dcloud.js.map.MapInitImpl"/>

以上配置完毕后。运行项目即可体验模块功能了。

功能模块与 API 对应关系

功能模块 5+APP项目 uni-app项目
Audio(音频) plus.audio https://uniapp.dcloud.io/api/media/record-manager https://uniapp.dcloud.io/api/media/audio-context
Audio(MP3格式音频支持库) plus.audio
Barcode(二维码) plus.barcode https://uniapp.dcloud.io/api/system/barcode
Bluetooth(低功耗蓝牙) plus.bluetooth https://uniapp.dcloud.io/api/system/bluetooth
Camera(摄像头) plus.camera
Contacts(通讯录) plus.contacts
Device(设备信息) plus.device https://uniapp.dcloud.io/api/system/info
Downloader(文件下载) plus.downloader https://uniapp.dcloud.io/api/request/network-file?id=downloadfile
Fingerprint(指纹识别) plus.fingerprint https://uniapp.dcloud.io/api/other/authentication
Geolocation(基础定位库) plus.geolocation https://uniapp.dcloud.io/api/location/location
Geolocation(高德定位) plus.geolocation https://uniapp.dcloud.io/api/location/location
Geolocation(系统定位) plus.geolocation https://uniapp.dcloud.io/api/location/location
iBeacon plus.ibeacon https://uniapp.dcloud.io/api/system/ibeacon
IO(文件系统) plus.io https://uniapp.dcloud.io/api/file/file
LivePusher(直播推流) plus.video.LivePusher https://uniapp.dcloud.io/api/media/live-player-context
Maps(高德地图) plus.map https://uniapp.dcloud.io/api/location/map
Messaging(短彩邮件消息) plus.messaging
Navigator(运行环境信息) plus.navigator https://uniapp.dcloud.io/api/system/info
Oauth(登录基础库) plus.oauth https://uniapp.dcloud.io/api/plugins/login
Oauth(小米登录) plus.oauth https://uniapp.dcloud.io/api/plugins/login
Oauth(QQ登录) plus.oauth https://uniapp.dcloud.io/api/plugins/login
Oauth(新浪微博登录) plus.oauth https://uniapp.dcloud.io/api/plugins/login
Oauth(微信登录) plus.oauth https://uniapp.dcloud.io/api/plugins/login
Payment(支付基础库) plus.payment https://uniapp.dcloud.io/api/plugins/payment
Payment(支付宝支付) plus.payment https://uniapp.dcloud.io/api/plugins/payment
Payment(微信支付) plus.payment https://uniapp.dcloud.io/api/plugins/payment
Share(分享基础库) plus.share https://uniapp.dcloud.io/api/plugins/share
Share(QQ分享) plus.share https://uniapp.dcloud.io/api/plugins/share
Share(新浪微博分享) plus.share https://uniapp.dcloud.io/api/plugins/share
Share(微信分享) plus.share https://uniapp.dcloud.io/api/plugins/share
Speech(语音识别基础库) plus.speech https://uniapp.dcloud.io/api/plugins/voice
Speech(百度语音识别) plus.speech https://uniapp.dcloud.io/api/plugins/voice
SQLite(数据库) plus.sqlite
Statistic(友盟统计) plus.statistic
Uploader(文件上传) plus.uploader https://uniapp.dcloud.io/api/request/network-file?id=uploadfile
VideoPlayer(视频播放) plus.video.VideoPlayer https://uniapp.dcloud.io/api/media/video
XHR(网络请求) plus.net https://uniapp.dcloud.io/api/request/request?id=request
nvue原生组件: map(高德地图) 不支持 https://uniapp.dcloud.io/component/map
nvue原生组件: barcode(二维码) 不支持 https://uniapp.dcloud.io/component/barcode
nvue原生组件: live-pusher(直播推流) 不支持 https://uniapp.dcloud.io/component/live-pusher
nvue原生组件: video视频 不支持 https://uniapp.dcloud.io/component/video
nvue原生组件: canvas 不支持 https://github.com/dcloudio/NvueCanvasDemo
继续阅读 »

Android uni小程序SDK集成 原生功能模块

SDK 提供了丰富的原生能力,您可根据需求自行添加功能模块,各功能模块所需的依赖库及资源文件,在uniMPSDK/Features目录中
目录结构

|-- uniMPSDK/Features  
    |-- Feature 依赖库说明.xls // 功能模块配置表  
    |-- libs                // 各功能模块的依赖库存放位置

请参考 Feature 依赖库说明.xls 配置表,添加模块所需依赖。修改项目相关配置信息;

集成方式

下面以 map 模块为例

首先查看Feature 依赖库说明.xls 表格说明需要添加amap-libs-release.aar,map-amap-release.aar两个库文件 及其AndroidManifest.xml等配置!

将amap-libs-release.aar,map-amap-release.aar两个库文件拷贝到项目中。主Module中的libs下。

地图依赖库文件拷贝完毕后。需要在build.gradle配置导入你引用的两个库文件。

    implementation files('libs/map-amap-release.aar')  
    implementation files('libs/amap-libs-release.aar')

参考Feature 依赖库说明.xls 中Map配置信息修改工程项目:

  • 修改AndroidManifest.xml 增加以下权限及配置
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>  
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>  
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>  
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>  
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
<uses-permission android:name="android.permission.INTERNET"/>  
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  
<uses-permission android:name="android.permission.READ_LOGS"/>  
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>  

<meta-data android:name="com.amap.api.v2.apikey" android:value="%申请高德地图apikey%"/>
  • 修改dcloud_properties.xml配置

在dcloud_properties.xml添加以下信息

features节点  
<feature name="Maps" value="io.dcloud.js.map.amap.JsMapPluginImpl"></feature>  
services节点  
<service name="Maps" value="io.dcloud.js.map.MapInitImpl"/>

以上配置完毕后。运行项目即可体验模块功能了。

功能模块与 API 对应关系

功能模块 5+APP项目 uni-app项目
Audio(音频) plus.audio https://uniapp.dcloud.io/api/media/record-manager https://uniapp.dcloud.io/api/media/audio-context
Audio(MP3格式音频支持库) plus.audio
Barcode(二维码) plus.barcode https://uniapp.dcloud.io/api/system/barcode
Bluetooth(低功耗蓝牙) plus.bluetooth https://uniapp.dcloud.io/api/system/bluetooth
Camera(摄像头) plus.camera
Contacts(通讯录) plus.contacts
Device(设备信息) plus.device https://uniapp.dcloud.io/api/system/info
Downloader(文件下载) plus.downloader https://uniapp.dcloud.io/api/request/network-file?id=downloadfile
Fingerprint(指纹识别) plus.fingerprint https://uniapp.dcloud.io/api/other/authentication
Geolocation(基础定位库) plus.geolocation https://uniapp.dcloud.io/api/location/location
Geolocation(高德定位) plus.geolocation https://uniapp.dcloud.io/api/location/location
Geolocation(系统定位) plus.geolocation https://uniapp.dcloud.io/api/location/location
iBeacon plus.ibeacon https://uniapp.dcloud.io/api/system/ibeacon
IO(文件系统) plus.io https://uniapp.dcloud.io/api/file/file
LivePusher(直播推流) plus.video.LivePusher https://uniapp.dcloud.io/api/media/live-player-context
Maps(高德地图) plus.map https://uniapp.dcloud.io/api/location/map
Messaging(短彩邮件消息) plus.messaging
Navigator(运行环境信息) plus.navigator https://uniapp.dcloud.io/api/system/info
Oauth(登录基础库) plus.oauth https://uniapp.dcloud.io/api/plugins/login
Oauth(小米登录) plus.oauth https://uniapp.dcloud.io/api/plugins/login
Oauth(QQ登录) plus.oauth https://uniapp.dcloud.io/api/plugins/login
Oauth(新浪微博登录) plus.oauth https://uniapp.dcloud.io/api/plugins/login
Oauth(微信登录) plus.oauth https://uniapp.dcloud.io/api/plugins/login
Payment(支付基础库) plus.payment https://uniapp.dcloud.io/api/plugins/payment
Payment(支付宝支付) plus.payment https://uniapp.dcloud.io/api/plugins/payment
Payment(微信支付) plus.payment https://uniapp.dcloud.io/api/plugins/payment
Share(分享基础库) plus.share https://uniapp.dcloud.io/api/plugins/share
Share(QQ分享) plus.share https://uniapp.dcloud.io/api/plugins/share
Share(新浪微博分享) plus.share https://uniapp.dcloud.io/api/plugins/share
Share(微信分享) plus.share https://uniapp.dcloud.io/api/plugins/share
Speech(语音识别基础库) plus.speech https://uniapp.dcloud.io/api/plugins/voice
Speech(百度语音识别) plus.speech https://uniapp.dcloud.io/api/plugins/voice
SQLite(数据库) plus.sqlite
Statistic(友盟统计) plus.statistic
Uploader(文件上传) plus.uploader https://uniapp.dcloud.io/api/request/network-file?id=uploadfile
VideoPlayer(视频播放) plus.video.VideoPlayer https://uniapp.dcloud.io/api/media/video
XHR(网络请求) plus.net https://uniapp.dcloud.io/api/request/request?id=request
nvue原生组件: map(高德地图) 不支持 https://uniapp.dcloud.io/component/map
nvue原生组件: barcode(二维码) 不支持 https://uniapp.dcloud.io/component/barcode
nvue原生组件: live-pusher(直播推流) 不支持 https://uniapp.dcloud.io/component/live-pusher
nvue原生组件: video视频 不支持 https://uniapp.dcloud.io/component/video
nvue原生组件: canvas 不支持 https://github.com/dcloudio/NvueCanvasDemo
收起阅读 »

uni-app checkbox组件和switch组件checked属性无效的解决方案

switch checkbox

> 相信许多开发者都有遇到过 uni-app 中的 复选框组件(checkbox)和开关组件(switch)在改变 checked 属性会有无效的问题。本篇文章将分析问题的产生和解决方法。

完整的分析过程和解决方法请查看小编的博客原创文章,字太多。难码!
文章地址:https://blog.csdn.net/u013350495/article/details/104347419

小编有发布过相同示例的插件,完整源码获取方式:

  1. uni-app 插件市场:https://ext.dcloud.net.cn/plugin?id=648
  2. gitee 代码仓库:https://gitee.com/myDarling/uniapp-extend
继续阅读 »

> 相信许多开发者都有遇到过 uni-app 中的 复选框组件(checkbox)和开关组件(switch)在改变 checked 属性会有无效的问题。本篇文章将分析问题的产生和解决方法。

完整的分析过程和解决方法请查看小编的博客原创文章,字太多。难码!
文章地址:https://blog.csdn.net/u013350495/article/details/104347419

小编有发布过相同示例的插件,完整源码获取方式:

  1. uni-app 插件市场:https://ext.dcloud.net.cn/plugin?id=648
  2. gitee 代码仓库:https://gitee.com/myDarling/uniapp-extend
收起阅读 »

多张图片上传(源码分享+实现分析)

图片上传

本篇文章以小程序中的代表【微信小程序】为例,分享一下在微信小程序中实现多图上传的源码实现。
其它小程序和uniapp都可通过该思路实现

代码片段(可导入微信WEB开发者工具体验):https://developers.weixin.qq.com/s/DHrt69mk7af3

两种不同实现方法的优缺点,请查看我的 博客原创文章,在文章中有详细的说明

小程序 多张图片上传 文章地址:https://blog.csdn.net/u013350495/article/details/104326088

JS源码:

Page({  
  data: {  
    // 已选择上传的本地图片地址  
    urlArr:['helang.jpg','1846492969.jpg','web.jpg']  
  },  
  onLoad: function () {  

  },  
  // 多图上传-回调式  
  uploadCallback(){  
    let index = 0;  // 当前位置,标识已上传到第几张图片  
    let newUrls = []; // 上传成功后的图片地址数组  
    // 图片上传方法  
    let upload = ()=>{  
      let nowUrl = this.data.urlArr[index]; //当前待上传的图片地址  
      wx.showLoading({  
        title: '正在上传',  
      });  
      /*   
        无图片上传接口,收setTimeout 模拟延迟状态  
        项目中替换为 wx.uploadFile 即可  
      */  
      // 假设每 1000ms 上传一张图片  
      setTimeout(()=>{  
        // 此处为已上传成功后的回调函数内容  
        let resUrl = `服务器返回上传后的地址 ${nowUrl}`; //假设这是上传成功后返回的地址  
        newUrls.push(resUrl); // 将上传后的地址添加到成功数组中  

        // 判断图片是否已经全部上传完成  
        if (index >= (this.data.urlArr.length-1)){  
          send();  
        }else{  
           //未全部上传完时标识位置+1并再次调用上传方法  
          index++;   
          upload();  
        }  
      },1000);  
    }  
    // 发送方法,用作图片上传完后,得到图片地址提交给其它接口或其它操作  
    let send = () => {  
      // 关闭加载提示  
      wx.hideLoading();  
      wx.showToast({  
        title: '上传成功',  
        icon:'success'  
      })  

      // 输出已经上传完的图片地址,请查看控制台结果  
      console.log(newUrls);  
    }  

    // 调用上传方法  
    upload();  
  },  
  // 多图上传-Promise  
  uploadPromise(){  
    /* Promise 对象数组 */  
    let p_arr = [];  

    /* 新建 Promise 方法,nowUrl参数为当前上传的图片地址 */  
    let new_p = (nowUrl) => {  
      return new Promise((resolve, reject) => {  
        /*   
        无图片上传接口,收setTimeout 模拟延迟状态  
        项目中替换为 wx.uploadFile 即可  
        */  
        // 假设每 1000ms 上传一张图片  
        setTimeout(()=>{  
          // 此处为已上传成功后的回调函数内容  
          let resUrl = `服务器返回上传后的地址 ${nowUrl}`; //假设这是上传成功后返回的地址  
          resolve(resUrl);  
        },1000);  
      })  
    }  

    // 遍历数据,创建相应的 Promise 数组数据  
    this.data.urlArr.forEach((item, index) => {  
      let nowUrl = this.data.urlArr[index]; //当前待上传的图片地址  
      p_arr.push(new_p(nowUrl));  
    });  

    wx.showLoading({  
      title: '正在上传',  
    });  
    /* 所有图片上传完成后调用该方法 */  
    Promise.all(p_arr).then((res) => {  
      // 关闭加载提示  
      wx.hideLoading();  
      wx.showToast({  
        title: '上传成功',  
        icon: 'success'  
      })  
      // 输出已经上传完的图片地址,请查看控制台结果  
      console.log(res);  
    });  
  }  
})

继续阅读 »

本篇文章以小程序中的代表【微信小程序】为例,分享一下在微信小程序中实现多图上传的源码实现。
其它小程序和uniapp都可通过该思路实现

代码片段(可导入微信WEB开发者工具体验):https://developers.weixin.qq.com/s/DHrt69mk7af3

两种不同实现方法的优缺点,请查看我的 博客原创文章,在文章中有详细的说明

小程序 多张图片上传 文章地址:https://blog.csdn.net/u013350495/article/details/104326088

JS源码:

Page({  
  data: {  
    // 已选择上传的本地图片地址  
    urlArr:['helang.jpg','1846492969.jpg','web.jpg']  
  },  
  onLoad: function () {  

  },  
  // 多图上传-回调式  
  uploadCallback(){  
    let index = 0;  // 当前位置,标识已上传到第几张图片  
    let newUrls = []; // 上传成功后的图片地址数组  
    // 图片上传方法  
    let upload = ()=>{  
      let nowUrl = this.data.urlArr[index]; //当前待上传的图片地址  
      wx.showLoading({  
        title: '正在上传',  
      });  
      /*   
        无图片上传接口,收setTimeout 模拟延迟状态  
        项目中替换为 wx.uploadFile 即可  
      */  
      // 假设每 1000ms 上传一张图片  
      setTimeout(()=>{  
        // 此处为已上传成功后的回调函数内容  
        let resUrl = `服务器返回上传后的地址 ${nowUrl}`; //假设这是上传成功后返回的地址  
        newUrls.push(resUrl); // 将上传后的地址添加到成功数组中  

        // 判断图片是否已经全部上传完成  
        if (index >= (this.data.urlArr.length-1)){  
          send();  
        }else{  
           //未全部上传完时标识位置+1并再次调用上传方法  
          index++;   
          upload();  
        }  
      },1000);  
    }  
    // 发送方法,用作图片上传完后,得到图片地址提交给其它接口或其它操作  
    let send = () => {  
      // 关闭加载提示  
      wx.hideLoading();  
      wx.showToast({  
        title: '上传成功',  
        icon:'success'  
      })  

      // 输出已经上传完的图片地址,请查看控制台结果  
      console.log(newUrls);  
    }  

    // 调用上传方法  
    upload();  
  },  
  // 多图上传-Promise  
  uploadPromise(){  
    /* Promise 对象数组 */  
    let p_arr = [];  

    /* 新建 Promise 方法,nowUrl参数为当前上传的图片地址 */  
    let new_p = (nowUrl) => {  
      return new Promise((resolve, reject) => {  
        /*   
        无图片上传接口,收setTimeout 模拟延迟状态  
        项目中替换为 wx.uploadFile 即可  
        */  
        // 假设每 1000ms 上传一张图片  
        setTimeout(()=>{  
          // 此处为已上传成功后的回调函数内容  
          let resUrl = `服务器返回上传后的地址 ${nowUrl}`; //假设这是上传成功后返回的地址  
          resolve(resUrl);  
        },1000);  
      })  
    }  

    // 遍历数据,创建相应的 Promise 数组数据  
    this.data.urlArr.forEach((item, index) => {  
      let nowUrl = this.data.urlArr[index]; //当前待上传的图片地址  
      p_arr.push(new_p(nowUrl));  
    });  

    wx.showLoading({  
      title: '正在上传',  
    });  
    /* 所有图片上传完成后调用该方法 */  
    Promise.all(p_arr).then((res) => {  
      // 关闭加载提示  
      wx.hideLoading();  
      wx.showToast({  
        title: '上传成功',  
        icon: 'success'  
      })  
      // 输出已经上传完的图片地址,请查看控制台结果  
      console.log(res);  
    });  
  }  
})

收起阅读 »

【建议】HBX能否自动识别文档的缩进格式?

由于不同项目文件缩进格式不同,在vscode里能够自动识别,打开的不同文件,每个都会自动按当前文档的缩进格式适配,编辑器下方能够显示该文档的缩进格式,HBX不行,只能统一一个缩进设置,这对于管理多个不同程序员的项目非常不方便,会导致混乱

由于不同项目文件缩进格式不同,在vscode里能够自动识别,打开的不同文件,每个都会自动按当前文档的缩进格式适配,编辑器下方能够显示该文档的缩进格式,HBX不行,只能统一一个缩进设置,这对于管理多个不同程序员的项目非常不方便,会导致混乱

Android原生工程集成uni小程序SDK教程

SDK unimp unimpsdk 小程序SDK uni小程序sdk

请移步 新的文档,此文档已停止更新

请移步 新的文档,此文档已停止更新

【外包项目,已找到合作暂时不需要了】uniapp开发APP,最终要打包成安卓和IOS,IOS要成功上架到苹果商店

uniapp 外包

现外包一个uniapp开发需求,请有能力的朋友私聊。需求如下:
开发要求:用uniapp开发,需打包成安卓和IOS两个版本APP,ios要成功上架到苹果商店
APP使用设备:在ipad上使用,限制横版
页面参考原型:https://1peup3.axshare.com/#id=que1ss&p=%E5%B9%B3%E5%8F%B0%E6%A6%82%E5%86%B5&g=1
说明:已有上线的web网站,现需根据web端开发成app(安卓和IOS),IOS需上架苹果商店。
原型仅供参考,与实际开发完成的网页版页面差不了多少,最终开发需按照web版页面来,即将网页版尺寸缩小为ipad尺寸,内容和功能都不变。
工期:私聊
具体事宜,QQ私聊:339571330

继续阅读 »

现外包一个uniapp开发需求,请有能力的朋友私聊。需求如下:
开发要求:用uniapp开发,需打包成安卓和IOS两个版本APP,ios要成功上架到苹果商店
APP使用设备:在ipad上使用,限制横版
页面参考原型:https://1peup3.axshare.com/#id=que1ss&p=%E5%B9%B3%E5%8F%B0%E6%A6%82%E5%86%B5&g=1
说明:已有上线的web网站,现需根据web端开发成app(安卓和IOS),IOS需上架苹果商店。
原型仅供参考,与实际开发完成的网页版页面差不了多少,最终开发需按照web版页面来,即将网页版尺寸缩小为ipad尺寸,内容和功能都不变。
工期:私聊
具体事宜,QQ私聊:339571330

收起阅读 »

iOS 扩展 uni小程序SDK 原生能力

扩展小程序原生能力 unimpsdk uni小程序sdk

本文档已过期,请查看 新文档

概述

本文档主要介绍如何扩展 uni小程序SDK 原生能力。

什么是扩展原生能力?

扩展原生能力指的是将您原生开发的功能通过一定规范暴露给 uni小程序环境,然后即可在 uni小程序应用中调用您的原生功能。

扩展方式

uni 原生端是基于 WeexSDK 来实现扩展原生能力,扩展原生能力有两种方式:一种是不需要参与页面布局,只需要通过 API 调用原生功能,比如:获取当前定位信息、数据请求等功能,这种情况可通过扩展module的方式来实现;另一种是需要参与页面布局,比如:map、image,这种情况需要通过扩展component即组件的方法来实现;

开发前准备

  • iOS开发环境,请使用 Xcode 11.0 及以上版本;
  • 已有集成 iOS uni小程序SDK 原生工程;集成文档
  • 安装 uni小程序开发工具 HBuilderX (注:版本需与您使用的 uni小程序SDK 版本保持一致)

扩展 module

下面以TestModule为例,源码请查看 uni小程序SDK 包中的示例 demo 工程;

1. 新建TestModule类,继承 NSObject,让该类遵循 WXModuleProtocol 的协议。

#import <Foundation/Foundation.h>  
// 引入 WeexSDK.h 头文件  
#import "WeexSDK.h"  

@interface TestModule : NSObject <WXModuleProtocol>  

@end  

2. 添加实现方法

异步方法实现

/// 异步方法(注:异步方法会在主线程(UI线程)执行)  
/// @param options js 端调用方法时传递的参数  
/// @param callback 回调方法,回传参数给 js 端  
- (void)testAsyncFunc:(NSDictionary *)options callback:(WXModuleKeepAliveCallback)callback {  
    // options 为 js 端调用此方法时传递的参数  
    NSLog(@"%@",options);  

    // 可以在该方法中实现原生能力,然后通过 callback 回调到 js  

    // 回调方法,传递参数给 js 端 注:只支持返回 String 或 NSDictionary (map) 类型  
    if (callback) {  
        // 第一个参数为回传给js端的数据,第二个参数为标识,表示该回调方法是否支持多次调用,如果原生端需要多次回调js端则第二个参数传 YES;  
        callback(@"success",NO);  
    }  
}

通过宏 WX_EXPORT_METHOD 将异步方法暴露给 js 端,只有通过WX_EXPORT_METHOD暴露的原生方法才能被 js 端识别到

// 通过宏 WX_EXPORT_METHOD 将异步方法暴露给 js 端  
WX_EXPORT_METHOD(@selector(testAsyncFunc:callback:))

同步方法实现

/// 同步方法(注:同步方法会在 js 线程执行)  
/// @param options js 端调用方法时传递的参数  
- (NSString *)testSyncFunc:(NSDictionary *)options {  
    // options 为 js 端调用此方法时传递的参数  
    NSLog(@"%@",options);  

    /*  
     可以在该方法中实现原生功能,然后直接通过 return 返回参数给 js  
     */  

    // 同步返回参数给 js 端 注:只支持返回 String 或 NSDictionary (map) 类型  
    return @"success";  
}

通过宏 WX_EXPORT_METHOD_SYNC 将同步方法暴露给 js 端

// 通过宏 WX_EXPORT_METHOD_SYNC 将同步方法暴露给 js 端  
WX_EXPORT_METHOD_SYNC(@selector(testSyncFunc:))

3. 注册 module

在初始化 DCUniMPSDKEngine 方法后,进行 module 的注册

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
    ...  
    // 初始化引擎  
    [DCUniMPSDKEngine initSDKEnvironmentWihtLaunchOptions:options];  

    // 注册 module 注:module的 Name 需要保证唯一, class:为 module 的类名  
    [WXSDKEngine registerModule:@"TestModule" withClass:NSClassFromString(@"TestModule")];  

    return YES;  
}

到此,我们已经完成了一个简单的 module 扩展

4. 在 uni小程序 中调用 module 方法

module 支持在 vue 和 nvue 中使用

<template>  
    <div>  
        <button type="primary" @click="testAsyncFunc">testAsyncFunc</button>  
        <button type="primary" @click="testSyncFunc">testSyncFunc</button>  
    </div>  
</template>  

<script>  
    // 获取 module   
    var testModule = uni.requireNativePlugin("TestModule")  
    export default {  
        methods: {  
            testAsyncFunc() {  
                // 调用异步方法  
                testModule.testAsyncFunc({  
                        'name': 'unimp',  
                        'age': 1  
                    },  
                    (ret) => {  
                        console.log(ret)  
                    })  
            },  
            testSyncFunc() {  
                // 调用同步方法  
                var ret = testModule.testSyncFunc({  
                    'name': 'unimp',  
                    'age': 1  
                })  
            }  
        }  
    }  
</script>  

然后可以导出 uni小程序资源,导入到 App 中查看效果;

扩展组件 component

下面以TestComponent为例,源码请查看 uni小程序SDK 包中的示例 demo 工程;

1. 新建TestComponent类,继承WXComponent类。如果这个类里什么代码也不写,它和默认的的 view 组件能力是一致的

#import "WXComponent.h"  

@interface TestComponent : WXComponent  

@end  

2. 覆写 WXComponent 中的生命周期方法

- loadView 方法

一个组件默认对应于一个原生 view,如果未覆盖loadView提供自定义 view,基类会默认返回一个继承于 UIView 的实例。比如我们要实现一个组件支持地图功能,我们可以返回系统的 MKMapView

- (UIView *)loadView {  
    return [MKMapView new];  
}

- viewDidLoad

对组件 view 需要做一些配置,比如设置 delegate,可以在 viewDidLoad 生命周期做。如果当前 view 没有添加 subview 的话,不要设置 view 的 frame,WeexSDK 会根据 style 进行排版后设置。

- (void)viewDidLoad {  
      ((MKMapView*)self.view).delegate = self;  
}

3. 注册组件

在初始化 DCUniMPSDKEngine 方法后,进行 component 的注册

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
    ...  
    // 初始化引擎  
    [DCUniMPSDKEngine initSDKEnvironmentWihtLaunchOptions:options];  

    // 注册 component 注:component 的 Name 需要保证唯一, class:为 component 的类名  
    [WXSDKEngine registerComponent:@"testmap" withClass:NSClassFromString(@"TestMapComponent")];  

    return YES;  
}

4. 在uni小程序代码中使用组件

注意:扩展的 component 只能在 nvue 文件中使用

<template>  
    <div>  
        <testmap style="width:200px;height:200px"></testmap>  
    </div>  
</template>

自定义事件

1. 对于每个组件默认提供了一些事件能力,如点击等。假如想给我们的地图组件提供 mapLoaded 事件。

在uni小程序代码中,通过 @事件名="方法名" 添加事件,如下添加mapLoaded 事件

<template>  
    <div>  
        <testmap style="width:200px;height:200px" @mapLoaded="onMapLoaded"></testmap>  
    </div>  
</template>  

<script>  
export default {  
    methods: {  
        onMapLoaded:function(e) {  
            console.log("map loaded"+JSON.stringify(e))  
        }  
    }  
}  
</script>
2. 原生端实现:覆盖组件生命周期方法,记录事件是否需要处理

我们需要额外添加一个 BOOL 成员 mapLoadedEvent 用来记录该事件是否生效。

/// 前端注册的事件会调用此方法  
/// @param eventName 事件名称  
- (void)addEvent:(NSString *)eventName {  
    if ([eventName isEqualToString:@"mapLoaded"]) {  
        _mapLoadedEvent = YES;  
    }  
}  

/// 对应的移除事件回调方法  
/// @param eventName 事件名称  
- (void)removeEvent:(NSString *)eventName {  
    if ([eventName isEqualToString:@"mapLoaded"]) {  
        _mapLoadedEvent = NO;  
    }  
}
3. 给前端发送事件
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView {  
    if (_mapLoadedEvent) {  
        // 想前端发送事件 params:传给前端的数据  
        [self fireEvent:@"mapLoaded" params:@{@"customKey":@"customValue"} domChanges:nil];  
    }  
}

自定义属性

给我们的地图组件添加一个新的属性showTraffic。在前端代码里可以控制组件是否显示路况信息

<template>  
    <div>  
        <testmap style="width:200px;height:200px" showTraffic="true"></testmap>  
    </div>  
</template>
原生端实现

1. 覆盖组件初始化方法 initWithRef...
给组件添加一个成员变量记录 showTraffic 属性的值,并在 init 方法中初始化。

- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance {  
    if(self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {  
        if (attributes[@"showsTraffic"]) {  
            _showsTraffic = [WXConvert BOOL: attributes[@"showsTraffic"]];  
        }  
    }  
    return self;  
}

2. 在生命期事件中记得将属性值同步给地图控件

- (void)viewDidLoad {  
  ((MKMapView*)self.view).showsTraffic = _showsTraffic;  
}

3. 当属性更新时,同步给地图控件

/// 前端更新属性回调方法  
/// @param attributes 更新的属性  
- (void)updateAttributes:(NSDictionary *)attributes {  
    // 解析属性  
    if (attributes[@"showsTraffic"]) {  
        _showsTraffic = [WXConvert BOOL: attributes[@"showsTraffic"]];  
        ((MKMapView*)self.view).showsTraffic = _showsTraffic;  
    }  
}

更多的组件生命期方法

组件是由框架管理的,比如创建、布局、渲染、销毁。组件的生命周期方法都是可以重写的,你可以在这些生命周期中去做自己的事情。

方法 描述
initWithRef:type:… 用给定的属性初始化一个component.
layoutDidFinish 在component完成布局时候会调用.
loadView 创建component管理的view.
viewWillLoad 在component的view加载之前会调用.
viewDidLoad 在component的view加载完之后调用.
viewWillUnload 在component的view被释放之前调用.
viewDidUnload 在component的view被释放之后调用.
updateStyles: 在component的style更新时候调用.
updateAttributes: 在component的attribute更新时候调用.
addEvent: 给component添加event的时候调用.
removeEvent: 在event移除的时候调用.

给组件添加方法

1.原生端实现

在组件代码中使用宏 WX_EXPORT_METHOD 暴露原生方法供前端调用

@implementation TestMapComponent  

// 通过 WX_EXPORT_METHOD 将方法暴露给前端  
WX_EXPORT_METHOD(@selector(focus:))  

- (void)focus:(NSDictionary *)options {  
    // options 为前端传递的参数  
    NSLog(@"%@",options);  
}  
@end

2.在uni小程序代码 中调用 focus: 方法。

<template>  
  <testmap ref='mycomponent'></testmap>  
</template>  
<script>  
  module.exports = {  
    created: function() {  
      this.$refs.mycomponent.focus("Hello");  
    }  
  }  
</script>

至此,您已完成组件扩展;

以上示例中的完整uni小程序代码

<template>  
    <div>  
        <button type="primary" @click="testAsyncFunc">testAsyncFunc</button>  
        <button type="primary" @click="testSyncFunc">testSyncFunc</button>  
        <testmap ref='mycomponent' style="width:200px;height:200px" showTraffic="true" @mapLoaded="onMapLoaded"></testmap>  
    </div>  
</template>  

<script>  
    // 获取 module   
    var testModule = uni.requireNativePlugin("TestModule")  
    export default {  
        onLoad() {  
            // 调用组件方法  
            this.$nextTick(()=>{  
                this.$refs.mycomponent.focus("Hello")  
            })  
        },  
        methods: {  
            testAsyncFunc() {  
                // 调用异步方法  
                testModule.testAsyncFunc({  
                        'name': 'unimp',  
                        'age': 1  
                    },  
                    (ret) => {  
                        console.log(ret)  
                    })  
            },  
            testSyncFunc() {  
                // 调用同步方法  
                var ret = testModule.testSyncFunc({  
                    'name': 'unimp',  
                    'age': 1  
                })  
            },  
            onMapLoaded(e) {  
                console.log("map loaded" + JSON.stringify(e))  
            }  
        }  
    }  
</script>
继续阅读 »

本文档已过期,请查看 新文档

概述

本文档主要介绍如何扩展 uni小程序SDK 原生能力。

什么是扩展原生能力?

扩展原生能力指的是将您原生开发的功能通过一定规范暴露给 uni小程序环境,然后即可在 uni小程序应用中调用您的原生功能。

扩展方式

uni 原生端是基于 WeexSDK 来实现扩展原生能力,扩展原生能力有两种方式:一种是不需要参与页面布局,只需要通过 API 调用原生功能,比如:获取当前定位信息、数据请求等功能,这种情况可通过扩展module的方式来实现;另一种是需要参与页面布局,比如:map、image,这种情况需要通过扩展component即组件的方法来实现;

开发前准备

  • iOS开发环境,请使用 Xcode 11.0 及以上版本;
  • 已有集成 iOS uni小程序SDK 原生工程;集成文档
  • 安装 uni小程序开发工具 HBuilderX (注:版本需与您使用的 uni小程序SDK 版本保持一致)

扩展 module

下面以TestModule为例,源码请查看 uni小程序SDK 包中的示例 demo 工程;

1. 新建TestModule类,继承 NSObject,让该类遵循 WXModuleProtocol 的协议。

#import <Foundation/Foundation.h>  
// 引入 WeexSDK.h 头文件  
#import "WeexSDK.h"  

@interface TestModule : NSObject <WXModuleProtocol>  

@end  

2. 添加实现方法

异步方法实现

/// 异步方法(注:异步方法会在主线程(UI线程)执行)  
/// @param options js 端调用方法时传递的参数  
/// @param callback 回调方法,回传参数给 js 端  
- (void)testAsyncFunc:(NSDictionary *)options callback:(WXModuleKeepAliveCallback)callback {  
    // options 为 js 端调用此方法时传递的参数  
    NSLog(@"%@",options);  

    // 可以在该方法中实现原生能力,然后通过 callback 回调到 js  

    // 回调方法,传递参数给 js 端 注:只支持返回 String 或 NSDictionary (map) 类型  
    if (callback) {  
        // 第一个参数为回传给js端的数据,第二个参数为标识,表示该回调方法是否支持多次调用,如果原生端需要多次回调js端则第二个参数传 YES;  
        callback(@"success",NO);  
    }  
}

通过宏 WX_EXPORT_METHOD 将异步方法暴露给 js 端,只有通过WX_EXPORT_METHOD暴露的原生方法才能被 js 端识别到

// 通过宏 WX_EXPORT_METHOD 将异步方法暴露给 js 端  
WX_EXPORT_METHOD(@selector(testAsyncFunc:callback:))

同步方法实现

/// 同步方法(注:同步方法会在 js 线程执行)  
/// @param options js 端调用方法时传递的参数  
- (NSString *)testSyncFunc:(NSDictionary *)options {  
    // options 为 js 端调用此方法时传递的参数  
    NSLog(@"%@",options);  

    /*  
     可以在该方法中实现原生功能,然后直接通过 return 返回参数给 js  
     */  

    // 同步返回参数给 js 端 注:只支持返回 String 或 NSDictionary (map) 类型  
    return @"success";  
}

通过宏 WX_EXPORT_METHOD_SYNC 将同步方法暴露给 js 端

// 通过宏 WX_EXPORT_METHOD_SYNC 将同步方法暴露给 js 端  
WX_EXPORT_METHOD_SYNC(@selector(testSyncFunc:))

3. 注册 module

在初始化 DCUniMPSDKEngine 方法后,进行 module 的注册

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
    ...  
    // 初始化引擎  
    [DCUniMPSDKEngine initSDKEnvironmentWihtLaunchOptions:options];  

    // 注册 module 注:module的 Name 需要保证唯一, class:为 module 的类名  
    [WXSDKEngine registerModule:@"TestModule" withClass:NSClassFromString(@"TestModule")];  

    return YES;  
}

到此,我们已经完成了一个简单的 module 扩展

4. 在 uni小程序 中调用 module 方法

module 支持在 vue 和 nvue 中使用

<template>  
    <div>  
        <button type="primary" @click="testAsyncFunc">testAsyncFunc</button>  
        <button type="primary" @click="testSyncFunc">testSyncFunc</button>  
    </div>  
</template>  

<script>  
    // 获取 module   
    var testModule = uni.requireNativePlugin("TestModule")  
    export default {  
        methods: {  
            testAsyncFunc() {  
                // 调用异步方法  
                testModule.testAsyncFunc({  
                        'name': 'unimp',  
                        'age': 1  
                    },  
                    (ret) => {  
                        console.log(ret)  
                    })  
            },  
            testSyncFunc() {  
                // 调用同步方法  
                var ret = testModule.testSyncFunc({  
                    'name': 'unimp',  
                    'age': 1  
                })  
            }  
        }  
    }  
</script>  

然后可以导出 uni小程序资源,导入到 App 中查看效果;

扩展组件 component

下面以TestComponent为例,源码请查看 uni小程序SDK 包中的示例 demo 工程;

1. 新建TestComponent类,继承WXComponent类。如果这个类里什么代码也不写,它和默认的的 view 组件能力是一致的

#import "WXComponent.h"  

@interface TestComponent : WXComponent  

@end  

2. 覆写 WXComponent 中的生命周期方法

- loadView 方法

一个组件默认对应于一个原生 view,如果未覆盖loadView提供自定义 view,基类会默认返回一个继承于 UIView 的实例。比如我们要实现一个组件支持地图功能,我们可以返回系统的 MKMapView

- (UIView *)loadView {  
    return [MKMapView new];  
}

- viewDidLoad

对组件 view 需要做一些配置,比如设置 delegate,可以在 viewDidLoad 生命周期做。如果当前 view 没有添加 subview 的话,不要设置 view 的 frame,WeexSDK 会根据 style 进行排版后设置。

- (void)viewDidLoad {  
      ((MKMapView*)self.view).delegate = self;  
}

3. 注册组件

在初始化 DCUniMPSDKEngine 方法后,进行 component 的注册

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
    ...  
    // 初始化引擎  
    [DCUniMPSDKEngine initSDKEnvironmentWihtLaunchOptions:options];  

    // 注册 component 注:component 的 Name 需要保证唯一, class:为 component 的类名  
    [WXSDKEngine registerComponent:@"testmap" withClass:NSClassFromString(@"TestMapComponent")];  

    return YES;  
}

4. 在uni小程序代码中使用组件

注意:扩展的 component 只能在 nvue 文件中使用

<template>  
    <div>  
        <testmap style="width:200px;height:200px"></testmap>  
    </div>  
</template>

自定义事件

1. 对于每个组件默认提供了一些事件能力,如点击等。假如想给我们的地图组件提供 mapLoaded 事件。

在uni小程序代码中,通过 @事件名="方法名" 添加事件,如下添加mapLoaded 事件

<template>  
    <div>  
        <testmap style="width:200px;height:200px" @mapLoaded="onMapLoaded"></testmap>  
    </div>  
</template>  

<script>  
export default {  
    methods: {  
        onMapLoaded:function(e) {  
            console.log("map loaded"+JSON.stringify(e))  
        }  
    }  
}  
</script>
2. 原生端实现:覆盖组件生命周期方法,记录事件是否需要处理

我们需要额外添加一个 BOOL 成员 mapLoadedEvent 用来记录该事件是否生效。

/// 前端注册的事件会调用此方法  
/// @param eventName 事件名称  
- (void)addEvent:(NSString *)eventName {  
    if ([eventName isEqualToString:@"mapLoaded"]) {  
        _mapLoadedEvent = YES;  
    }  
}  

/// 对应的移除事件回调方法  
/// @param eventName 事件名称  
- (void)removeEvent:(NSString *)eventName {  
    if ([eventName isEqualToString:@"mapLoaded"]) {  
        _mapLoadedEvent = NO;  
    }  
}
3. 给前端发送事件
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView {  
    if (_mapLoadedEvent) {  
        // 想前端发送事件 params:传给前端的数据  
        [self fireEvent:@"mapLoaded" params:@{@"customKey":@"customValue"} domChanges:nil];  
    }  
}

自定义属性

给我们的地图组件添加一个新的属性showTraffic。在前端代码里可以控制组件是否显示路况信息

<template>  
    <div>  
        <testmap style="width:200px;height:200px" showTraffic="true"></testmap>  
    </div>  
</template>
原生端实现

1. 覆盖组件初始化方法 initWithRef...
给组件添加一个成员变量记录 showTraffic 属性的值,并在 init 方法中初始化。

- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance {  
    if(self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {  
        if (attributes[@"showsTraffic"]) {  
            _showsTraffic = [WXConvert BOOL: attributes[@"showsTraffic"]];  
        }  
    }  
    return self;  
}

2. 在生命期事件中记得将属性值同步给地图控件

- (void)viewDidLoad {  
  ((MKMapView*)self.view).showsTraffic = _showsTraffic;  
}

3. 当属性更新时,同步给地图控件

/// 前端更新属性回调方法  
/// @param attributes 更新的属性  
- (void)updateAttributes:(NSDictionary *)attributes {  
    // 解析属性  
    if (attributes[@"showsTraffic"]) {  
        _showsTraffic = [WXConvert BOOL: attributes[@"showsTraffic"]];  
        ((MKMapView*)self.view).showsTraffic = _showsTraffic;  
    }  
}

更多的组件生命期方法

组件是由框架管理的,比如创建、布局、渲染、销毁。组件的生命周期方法都是可以重写的,你可以在这些生命周期中去做自己的事情。

方法 描述
initWithRef:type:… 用给定的属性初始化一个component.
layoutDidFinish 在component完成布局时候会调用.
loadView 创建component管理的view.
viewWillLoad 在component的view加载之前会调用.
viewDidLoad 在component的view加载完之后调用.
viewWillUnload 在component的view被释放之前调用.
viewDidUnload 在component的view被释放之后调用.
updateStyles: 在component的style更新时候调用.
updateAttributes: 在component的attribute更新时候调用.
addEvent: 给component添加event的时候调用.
removeEvent: 在event移除的时候调用.

给组件添加方法

1.原生端实现

在组件代码中使用宏 WX_EXPORT_METHOD 暴露原生方法供前端调用

@implementation TestMapComponent  

// 通过 WX_EXPORT_METHOD 将方法暴露给前端  
WX_EXPORT_METHOD(@selector(focus:))  

- (void)focus:(NSDictionary *)options {  
    // options 为前端传递的参数  
    NSLog(@"%@",options);  
}  
@end

2.在uni小程序代码 中调用 focus: 方法。

<template>  
  <testmap ref='mycomponent'></testmap>  
</template>  
<script>  
  module.exports = {  
    created: function() {  
      this.$refs.mycomponent.focus("Hello");  
    }  
  }  
</script>

至此,您已完成组件扩展;

以上示例中的完整uni小程序代码

<template>  
    <div>  
        <button type="primary" @click="testAsyncFunc">testAsyncFunc</button>  
        <button type="primary" @click="testSyncFunc">testSyncFunc</button>  
        <testmap ref='mycomponent' style="width:200px;height:200px" showTraffic="true" @mapLoaded="onMapLoaded"></testmap>  
    </div>  
</template>  

<script>  
    // 获取 module   
    var testModule = uni.requireNativePlugin("TestModule")  
    export default {  
        onLoad() {  
            // 调用组件方法  
            this.$nextTick(()=>{  
                this.$refs.mycomponent.focus("Hello")  
            })  
        },  
        methods: {  
            testAsyncFunc() {  
                // 调用异步方法  
                testModule.testAsyncFunc({  
                        'name': 'unimp',  
                        'age': 1  
                    },  
                    (ret) => {  
                        console.log(ret)  
                    })  
            },  
            testSyncFunc() {  
                // 调用同步方法  
                var ret = testModule.testSyncFunc({  
                    'name': 'unimp',  
                    'age': 1  
                })  
            },  
            onMapLoaded(e) {  
                console.log("map loaded" + JSON.stringify(e))  
            }  
        }  
    }  
</script>
收起阅读 »

iOS平台隐私与政策提示框实现注意问题

通知 iOS 隐私 隐私政策

根据工业和信息化部关于开展APP侵害用户权益专项整治要求,App提交到应用市场必须满足以下条件:

  • 应用启动运行时需弹出隐私政策协议,说明应用采集用户数据
    这里将详细介绍如何配置弹出“隐私协议和政策”提示框
  • 应用不能强制要求用户授予权限,即不能“不给权限不让用”

iOS系统因为系统授权管理比较完善,调用访问涉及到个人隐私信息的接口都会弹出系统授权提示框,并且在提示框上描述应用使用此权限的用途。
因此没有提供Android平台这样的提示框配置方法,需要开发者在应用中自己实现隐私政策提示框。

<a id="collect"/>

数据采集说明

为了持续优化应用及提供统计报表功能,应用在运行过程中会采集以下数据:

  • 应用启动时会采集应用启动时间信息用于优化启动速度,不包含个人隐私信息
  • 应用启动后会采集统计数据用于提供uni统计服务,iOS平台如果用户开启了IDFA则采集数据会包含IDFA信息。uni统计配置方法参考uni-app的manifest.json配置项列表
  • 应用异常时会采集错误日志信息,用于优化改进产品

DCloud通过了国家信息安全等级保护三级,证书编号:11010813802-20001,保障相关数据的安全性
DCloud并非大数据公司,采集的数据是为开发者提供统计服务和产品持续优化,不包含个人隐私相关信息

隐私政策提示框实现

iOS平台没有提供隐私政策模板提示框,所以需要开发者在应用中自己实现隐私政策提示框。

  • uni-app项目
    建议使用nvue页面来实现,渲染速度更快,用于体验更好。
  • 5+ APP(WAP2APP)项目
    简单提示框可以使用系统确认对话框plus.nativeUI.confirm,缺点是无法自定义样式,无法使用链接;
    如果希望自定义隐私政策提示框,可以在Webview中使用html渲染,如在首页使用div渲染、或打开独立的Webview窗口。
    用户点击同意隐私政策时推荐调用plus.runtime.agreePrivacy保存状态,应用启动时调用plus.runtime.isAgreePrivacy获取用户是否已经同意。

系统授权提示框处理

如果应用第一次启动时会弹出系统授权提示框,可以参考以下说明处理。

使用无线数据

提交应用启动时间信息等需要用到网络,所以应用第一次启动时可能会弹出“使用无线数据”系统授权框

目前AppStore上大部分应用在显示隐私政策提示框同时会弹出此授权提示款,不会影响上线审核

<a id="push"></a>

发送通知

如果应用使用了uniPush(发送消息通知)功能,在应用启动时会弹出“发送通知”系统授权框

这是因为应用启动时会自动向系统注册要使用消息推送功能引起,如果希望在应用启动时不弹出此授权框,HBuilderX2.6.3+版本可以按以下方法配置配置应用启动时不注册。
在用户接受隐私政策后调用异步获取客户端推送标识信息方法 plus.push.getClientInfoAsync进行注册。

配置方法

打开项目的manifest.json文件,切换到“源码视图”项

  • uni-app项目
    在 "app-plus" -> "distribute" -> "ios" 节点下添加 pushRegisterMode节点
  • 5+ App项目
    在 "plus" -> "distribute" -> "apple" 节点下添加 pushRegisterMode节点

pushRegisterMode字段值设置如下:

        "pushRegisterMode": "manual"

注意plus.push.getClientInfo是同步方法,不会触发向系统注册操作,必须使用异步方法 plus.push.getClientInfoAsync

配置后提交云端打包后生效

本地离线打包参考:https://ask.dcloud.net.cn/article/41#pushRegister

其它授权框

应用启动不会主动调用涉及到系统授权框的功能,但是调用类似定位等功能时也会触发“位置信息”授权框
这时需要修改应用内部业务逻辑,在用户同意隐私政策前不要调用这些API来避免。

继续阅读 »

根据工业和信息化部关于开展APP侵害用户权益专项整治要求,App提交到应用市场必须满足以下条件:

  • 应用启动运行时需弹出隐私政策协议,说明应用采集用户数据
    这里将详细介绍如何配置弹出“隐私协议和政策”提示框
  • 应用不能强制要求用户授予权限,即不能“不给权限不让用”

iOS系统因为系统授权管理比较完善,调用访问涉及到个人隐私信息的接口都会弹出系统授权提示框,并且在提示框上描述应用使用此权限的用途。
因此没有提供Android平台这样的提示框配置方法,需要开发者在应用中自己实现隐私政策提示框。

<a id="collect"/>

数据采集说明

为了持续优化应用及提供统计报表功能,应用在运行过程中会采集以下数据:

  • 应用启动时会采集应用启动时间信息用于优化启动速度,不包含个人隐私信息
  • 应用启动后会采集统计数据用于提供uni统计服务,iOS平台如果用户开启了IDFA则采集数据会包含IDFA信息。uni统计配置方法参考uni-app的manifest.json配置项列表
  • 应用异常时会采集错误日志信息,用于优化改进产品

DCloud通过了国家信息安全等级保护三级,证书编号:11010813802-20001,保障相关数据的安全性
DCloud并非大数据公司,采集的数据是为开发者提供统计服务和产品持续优化,不包含个人隐私相关信息

隐私政策提示框实现

iOS平台没有提供隐私政策模板提示框,所以需要开发者在应用中自己实现隐私政策提示框。

  • uni-app项目
    建议使用nvue页面来实现,渲染速度更快,用于体验更好。
  • 5+ APP(WAP2APP)项目
    简单提示框可以使用系统确认对话框plus.nativeUI.confirm,缺点是无法自定义样式,无法使用链接;
    如果希望自定义隐私政策提示框,可以在Webview中使用html渲染,如在首页使用div渲染、或打开独立的Webview窗口。
    用户点击同意隐私政策时推荐调用plus.runtime.agreePrivacy保存状态,应用启动时调用plus.runtime.isAgreePrivacy获取用户是否已经同意。

系统授权提示框处理

如果应用第一次启动时会弹出系统授权提示框,可以参考以下说明处理。

使用无线数据

提交应用启动时间信息等需要用到网络,所以应用第一次启动时可能会弹出“使用无线数据”系统授权框

目前AppStore上大部分应用在显示隐私政策提示框同时会弹出此授权提示款,不会影响上线审核

<a id="push"></a>

发送通知

如果应用使用了uniPush(发送消息通知)功能,在应用启动时会弹出“发送通知”系统授权框

这是因为应用启动时会自动向系统注册要使用消息推送功能引起,如果希望在应用启动时不弹出此授权框,HBuilderX2.6.3+版本可以按以下方法配置配置应用启动时不注册。
在用户接受隐私政策后调用异步获取客户端推送标识信息方法 plus.push.getClientInfoAsync进行注册。

配置方法

打开项目的manifest.json文件,切换到“源码视图”项

  • uni-app项目
    在 "app-plus" -> "distribute" -> "ios" 节点下添加 pushRegisterMode节点
  • 5+ App项目
    在 "plus" -> "distribute" -> "apple" 节点下添加 pushRegisterMode节点

pushRegisterMode字段值设置如下:

        "pushRegisterMode": "manual"

注意plus.push.getClientInfo是同步方法,不会触发向系统注册操作,必须使用异步方法 plus.push.getClientInfoAsync

配置后提交云端打包后生效

本地离线打包参考:https://ask.dcloud.net.cn/article/41#pushRegister

其它授权框

应用启动不会主动调用涉及到系统授权框的功能,但是调用类似定位等功能时也会触发“位置信息”授权框
这时需要修改应用内部业务逻辑,在用户同意隐私政策前不要调用这些API来避免。

收起阅读 »

三天上线社区防疫人员管理小程序,阿里小程序云联手开发者科技抗疫

uniCloud uniapp

2020年春节伊始,一场新型冠状病毒的疫情突如其来。病毒猖獗,传染性极强。截止北京时间 2月11日,全国确诊新型冠状病毒肺炎的人数已达到了42714例,死亡1017例,疑似患病人数高达21675例!

战疫情,阿里巴巴在行动

面对不断攀升的人数,面对严峻的疫情,阿里巴巴集团义不容辞,承担起了社会责任,第一时间设立了10亿元医疗物资供给专项基金,马云公益基金会捐赠1亿元用于支持新型冠状病毒的疫苗研发。“武汉加油”公益筹款仅8小时就筹集了7140万善款,并通过绿色通道确保物资第一时间送达武汉。

01

战疫情,阿里云小程序云在行动

疫情之下,国家延长了假期,但却有无数的医生、护士、工人、快递员、外卖小哥、网约车司机等成为了最美逆行者,冲到第一线浴血奋战。阿里人作为中国科技互联网人,责无旁贷。虽身不在一线,却始终心系武汉和全国。目前仍是疫情防控的关键时期,即将到来的返程高峰大大增加了疫情防控难度。 现各省市的街道、小区、园区和写字楼等都加强了对流动人员的测温和登记。民政部陈司长发言:“一个有益的公益软件,比捐10个亿还管用!”

鉴于此,阿里云小程序云和DCloud共同发起了安全登记应用的开源项目。开发者们在线出动,仅3天就基于小程序Serverless开发出了一款社区防疫人员管理小程序——人员出入管理工具。满足疫期人员出入管理的需求,帮助企事业单位、医院、卫生委、交通、教育等部门应对即将到来的返程高峰。在后方用科技的力量支援这场没有硝烟的战争。

小程序云

小程序云(Mini Program Cloud)是阿里云面向小程序场景提供的一站式云服务,帮助开发者实现一云多端的业务战略,提供了有服务器和无服务器两种模式。云应用是有服务器模式,提供了包括资源编排、应用托管等服务。小程序Serverless是无服务模式,提供了开发、运营、业务增值等服务。跨端开发工具链为开发者提供了一次开发全网小程序运行的能力,并在一朵云内实现统一的资源管理、统一的数据运营和统一的业务设计。

DCloud

DCloud为开发者提供包括HBuilder、uni-app等开发工具,帮助开发者快速、低成本制作移动互联网多端应用。使用uni-app,可以同时发布为Android App、iOS App、H5网页、以及微信/支付宝/百度/头条/QQ小程序。DCloud旗下产品月活设备规模4.5亿。

战疫情,社区防疫人员出入管理工具问世

研发初衷

由于新型肺炎潜伏期长则14天, 且可通过接触传播,在外来人员登记时如使用纸笔择优交叉感染的可能。因此阿里云开发者们使用小程序云快速开发出通用的出入人员登记应用,无纸化管理,即管理员生成二维码并张贴后,来访人员即可扫码快速填写表单记录体温。降低交叉感染的同时,更便于数据管理。

系统介绍

小程序云人员出入管理工具(链接https://sfsi-wlry.m3w.cn/ )既可减少交叉感染,又具有感染风险预警的功能,同时支持数据管理、跨端支持和弹性扩容,即使人流返程高峰也可安心使用。

1.用户登记界面

扫码即填信息,高效便捷

2.登记人员列表

小程序云人员出入管理工具,联合火遍全网的肺炎确诊患者同行查询工具的开发团队,使用了该工具了数据查询的API。使用人员登记应用时如填写行程信息,系统还会检测是否和已确诊的患者行程有交集,如有重合则会标记预警。例如标红的用户与确诊感染者行程有交集,进一步提升了管理效率。

3.搜索页面

可快速按姓名搜索信息

4.管理员页面

管理员可操作页面,含二维码。

这个项目自2月4日正式发布,天津滨海区的三个工业园区率先使用,利用门卫老大爷的话说,我们的应用减少了他们和来访者的接触,降低了他们感染的风险。

2月5日,看到阿里云官网的疫情专题后,又先后有内蒙古通辽市巴鲁县公安局、甘肃省电力研究所的工作人员联系到我们,表示很想应用我们的登记小程序。宁波市大榭开发区海韵社区的工作人员更是表示他们想把这个工具应用到所辖的所有网格。目前已对接了来自内蒙、甘肃、海南、云南等19个省份,40个社区、企事业单位的出入登记应用需求。

小程序云Serverless为开发者提供了一键构建后端应用运行环境、后端服务部署、运维监控等能力的一站式小程序部署服务。针对此次突发疫情,基于小程序云Serverless,目前已经在短短几天时间内快速上线了5款疫情管理工具,除人员出入管理系统外,还包括学生健康报备管理系统、员工疫情筛查工具、物资管理系统以及消毒检查登记系统。这些项目面向开发者完全开源,开发者可以基于这些项目构建更多的防疫工具。开源项目链接:小程序Serverless防疫小程序最佳实践。

此外,阿里云联合支付宝一起发起了抗疫情的扶持计划和公益开发者联盟。开放生态面向开发者提供七大激励政策,包括为优质开发者提供50万元现金激励,免费试用云资源和小程序模板3个月、免费使用数据可视化产品3个月等,也欢迎广大开发者加入公益开发者联盟。

能力越大,责任越大。经历过非典,正能量的阿里人为战胜疫情不断用代码铸成新的长城,日夜奋战,保卫家国,祈祷疫情早日过去。

武汉加油!中国加油!

继续阅读 »

2020年春节伊始,一场新型冠状病毒的疫情突如其来。病毒猖獗,传染性极强。截止北京时间 2月11日,全国确诊新型冠状病毒肺炎的人数已达到了42714例,死亡1017例,疑似患病人数高达21675例!

战疫情,阿里巴巴在行动

面对不断攀升的人数,面对严峻的疫情,阿里巴巴集团义不容辞,承担起了社会责任,第一时间设立了10亿元医疗物资供给专项基金,马云公益基金会捐赠1亿元用于支持新型冠状病毒的疫苗研发。“武汉加油”公益筹款仅8小时就筹集了7140万善款,并通过绿色通道确保物资第一时间送达武汉。

01

战疫情,阿里云小程序云在行动

疫情之下,国家延长了假期,但却有无数的医生、护士、工人、快递员、外卖小哥、网约车司机等成为了最美逆行者,冲到第一线浴血奋战。阿里人作为中国科技互联网人,责无旁贷。虽身不在一线,却始终心系武汉和全国。目前仍是疫情防控的关键时期,即将到来的返程高峰大大增加了疫情防控难度。 现各省市的街道、小区、园区和写字楼等都加强了对流动人员的测温和登记。民政部陈司长发言:“一个有益的公益软件,比捐10个亿还管用!”

鉴于此,阿里云小程序云和DCloud共同发起了安全登记应用的开源项目。开发者们在线出动,仅3天就基于小程序Serverless开发出了一款社区防疫人员管理小程序——人员出入管理工具。满足疫期人员出入管理的需求,帮助企事业单位、医院、卫生委、交通、教育等部门应对即将到来的返程高峰。在后方用科技的力量支援这场没有硝烟的战争。

小程序云

小程序云(Mini Program Cloud)是阿里云面向小程序场景提供的一站式云服务,帮助开发者实现一云多端的业务战略,提供了有服务器和无服务器两种模式。云应用是有服务器模式,提供了包括资源编排、应用托管等服务。小程序Serverless是无服务模式,提供了开发、运营、业务增值等服务。跨端开发工具链为开发者提供了一次开发全网小程序运行的能力,并在一朵云内实现统一的资源管理、统一的数据运营和统一的业务设计。

DCloud

DCloud为开发者提供包括HBuilder、uni-app等开发工具,帮助开发者快速、低成本制作移动互联网多端应用。使用uni-app,可以同时发布为Android App、iOS App、H5网页、以及微信/支付宝/百度/头条/QQ小程序。DCloud旗下产品月活设备规模4.5亿。

战疫情,社区防疫人员出入管理工具问世

研发初衷

由于新型肺炎潜伏期长则14天, 且可通过接触传播,在外来人员登记时如使用纸笔择优交叉感染的可能。因此阿里云开发者们使用小程序云快速开发出通用的出入人员登记应用,无纸化管理,即管理员生成二维码并张贴后,来访人员即可扫码快速填写表单记录体温。降低交叉感染的同时,更便于数据管理。

系统介绍

小程序云人员出入管理工具(链接https://sfsi-wlry.m3w.cn/ )既可减少交叉感染,又具有感染风险预警的功能,同时支持数据管理、跨端支持和弹性扩容,即使人流返程高峰也可安心使用。

1.用户登记界面

扫码即填信息,高效便捷

2.登记人员列表

小程序云人员出入管理工具,联合火遍全网的肺炎确诊患者同行查询工具的开发团队,使用了该工具了数据查询的API。使用人员登记应用时如填写行程信息,系统还会检测是否和已确诊的患者行程有交集,如有重合则会标记预警。例如标红的用户与确诊感染者行程有交集,进一步提升了管理效率。

3.搜索页面

可快速按姓名搜索信息

4.管理员页面

管理员可操作页面,含二维码。

这个项目自2月4日正式发布,天津滨海区的三个工业园区率先使用,利用门卫老大爷的话说,我们的应用减少了他们和来访者的接触,降低了他们感染的风险。

2月5日,看到阿里云官网的疫情专题后,又先后有内蒙古通辽市巴鲁县公安局、甘肃省电力研究所的工作人员联系到我们,表示很想应用我们的登记小程序。宁波市大榭开发区海韵社区的工作人员更是表示他们想把这个工具应用到所辖的所有网格。目前已对接了来自内蒙、甘肃、海南、云南等19个省份,40个社区、企事业单位的出入登记应用需求。

小程序云Serverless为开发者提供了一键构建后端应用运行环境、后端服务部署、运维监控等能力的一站式小程序部署服务。针对此次突发疫情,基于小程序云Serverless,目前已经在短短几天时间内快速上线了5款疫情管理工具,除人员出入管理系统外,还包括学生健康报备管理系统、员工疫情筛查工具、物资管理系统以及消毒检查登记系统。这些项目面向开发者完全开源,开发者可以基于这些项目构建更多的防疫工具。开源项目链接:小程序Serverless防疫小程序最佳实践。

此外,阿里云联合支付宝一起发起了抗疫情的扶持计划和公益开发者联盟。开放生态面向开发者提供七大激励政策,包括为优质开发者提供50万元现金激励,免费试用云资源和小程序模板3个月、免费使用数据可视化产品3个月等,也欢迎广大开发者加入公益开发者联盟。

能力越大,责任越大。经历过非典,正能量的阿里人为战胜疫情不断用代码铸成新的长城,日夜奋战,保卫家国,祈祷疫情早日过去。

武汉加油!中国加油!

收起阅读 »