HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

【分享】苹果App上架App Store注意事项,避免被拒!

上架 iOS打包

iOS APP上架审核比较严格!

这里整理了iOS上架需要注意的事项,上架前尽量避免,争取一次提交审核成功,被拒打回重新修改提交审核会耗费很多时间!

分享Windows申请证书打包iOS app上架详细教程

1、应用内包含检查更新功能iOS 应用的版本更新必须通过 App Store 进行,自身 App 内不能包含提示更新功能。从2015年3月起,所有包含检查更新功能的 App 都会被拒绝上架。

2、使用第三方登录时未做安装检测接入第三方登录要检测是否安装了第三方客户端,未安装时不要显示对应按钮。2015年9月之前,通常可以采用判断未安装则隐藏登录按钮的方式。但目前隐藏按钮的方式也可能被审核拒绝,QQ 和微博提供了 web 登录的方式,如果判断未安装,需要允许用户使用 webview 的登录方式。苹果在条款中有声明不允许 iOS 应用的正常使用需要依赖另外一个 App。

3、采集设备IDFA但应用没有广告功能从2014年2月起,Apple 开始拒绝采集 IDFA (identifier for advertising) 却未集成任何广告服务的应用进入 App Store。如果 App 本身没有广告,ASO100.com 建议可以在审核的时候显示一个 Banner 广告,并且放在比较明显的位置,审核通过后关掉即可。

4、含UGC却未提供用户协议及举报功能如果你的 App 内有发帖等UGC(用户产生内容)功能,必须提供用户协议,并留有内容举报功能,否则就会被审核拒绝。

5、上传时没有使用真实的应用截图应用程序的名称、描述、截图或者预览与应用的内容和功能不相关将会被拒绝。有 App 因为应用截图使用的是自己设计的插画而被审核拒绝。

6、应用必须使用邀请码才能注册使用苹果要求应用不能限制只有部分用户可以使用。

7、应用内出现第三方移动平台的名字或图标一直以来,苹果都不允许iOS开发者在进行软件描述时提到 Android 版本,而自从2015年4月起,在 App 内、截图等任何地方提到安卓、Android 的文字、图标、系统界面都会被拒。曾经有电商 App,因为出现了售卖三星安卓手机而被拒。。。

8、应用内涉及奖励,未声明与苹果无关App 里有实物奖励的话,不能使用苹果产品(例如 iPhone 、iPad 等)作为奖品。另外一定要声明“奖励由本公司提供,与苹果官方无关”。

9、没有提供恢复内购的方法增加一个“恢复购买记录”的按钮即可。

10、未注册时不能使用与账号无关的功能对于资讯等 App,在没有进行与用户信息相关的操作时,却强行让用户登录,甚至不登录就无法看到任何内容,有可能会被拒绝。

11、iPhone 应用在 iPad 上不能正常显示iPhone程序必须不经修改就能以iPhone分辨率和2倍iPhone 3GS的分辨率在iPad上运行。即使你的App 只为 iPhone 用户提供,在 iPad 上也必须能够正常显示,否则审核会被拒绝。

12、侵犯第三方版权对于视频、音乐、图书类的应用很容易因为这一条而被拒。另外 ASO100.com 建议应用内最好不要出现第三方的商标,例如运营商的Logo、影视公司的 Logo 等。13、应用截图、名称、描述等出现不雅词汇在应用截图、名称、描述等任何地方出现例如诸如 牛逼、绿茶婊、无节操、逗比 等词汇,都会被苹果审核拒绝。

14、应用出现 beta版、测试版字样不要过度谦虚地在启动画面或者应用名称上加上”beta”字样,苹果不允许测试版产品上架。

15、注册缺少隐私政策如果应用包含注册功能,注册页面必须提供隐私说明协议按钮或者链接。另外在 iTunes connect 提交新版本的时候,Privacy Policy URL 必须要填写。

16、应用出现崩溃、加载失败等 bug审核期间出现崩溃会导致审核被拒。ASO100.com 建议,在审核期间务必保证服务器稳定,避免审核人员审核时出现内容加载失败的情况,导致被拒。

17、应用描述、截图和应用功能不符如果应用的描述或截图介绍的功能在审核期间没有体现,则会被拒绝,如果介绍文案不够详细也会有一定概率被拒。

18、应用包含应用推荐功能除特殊情况,苹果明令禁止应用内推荐其他APP。

19、应用包含不正确的诊断功能如果你的应用中,包含不真实的系统检测或优化功能,苹果会认为这项功能有误导用户的嫌疑,审核时会被拒绝。

20、应用提交的新版本与上一版差异过大如果你提交的新版本应用与上一版相比,功能上变化过大,比如将游戏升级为工具类应用,或在新版本中完全改掉前一版产品的功能,则会被苹果拒绝。

继续阅读 »

iOS APP上架审核比较严格!

这里整理了iOS上架需要注意的事项,上架前尽量避免,争取一次提交审核成功,被拒打回重新修改提交审核会耗费很多时间!

分享Windows申请证书打包iOS app上架详细教程

1、应用内包含检查更新功能iOS 应用的版本更新必须通过 App Store 进行,自身 App 内不能包含提示更新功能。从2015年3月起,所有包含检查更新功能的 App 都会被拒绝上架。

2、使用第三方登录时未做安装检测接入第三方登录要检测是否安装了第三方客户端,未安装时不要显示对应按钮。2015年9月之前,通常可以采用判断未安装则隐藏登录按钮的方式。但目前隐藏按钮的方式也可能被审核拒绝,QQ 和微博提供了 web 登录的方式,如果判断未安装,需要允许用户使用 webview 的登录方式。苹果在条款中有声明不允许 iOS 应用的正常使用需要依赖另外一个 App。

3、采集设备IDFA但应用没有广告功能从2014年2月起,Apple 开始拒绝采集 IDFA (identifier for advertising) 却未集成任何广告服务的应用进入 App Store。如果 App 本身没有广告,ASO100.com 建议可以在审核的时候显示一个 Banner 广告,并且放在比较明显的位置,审核通过后关掉即可。

4、含UGC却未提供用户协议及举报功能如果你的 App 内有发帖等UGC(用户产生内容)功能,必须提供用户协议,并留有内容举报功能,否则就会被审核拒绝。

5、上传时没有使用真实的应用截图应用程序的名称、描述、截图或者预览与应用的内容和功能不相关将会被拒绝。有 App 因为应用截图使用的是自己设计的插画而被审核拒绝。

6、应用必须使用邀请码才能注册使用苹果要求应用不能限制只有部分用户可以使用。

7、应用内出现第三方移动平台的名字或图标一直以来,苹果都不允许iOS开发者在进行软件描述时提到 Android 版本,而自从2015年4月起,在 App 内、截图等任何地方提到安卓、Android 的文字、图标、系统界面都会被拒。曾经有电商 App,因为出现了售卖三星安卓手机而被拒。。。

8、应用内涉及奖励,未声明与苹果无关App 里有实物奖励的话,不能使用苹果产品(例如 iPhone 、iPad 等)作为奖品。另外一定要声明“奖励由本公司提供,与苹果官方无关”。

9、没有提供恢复内购的方法增加一个“恢复购买记录”的按钮即可。

10、未注册时不能使用与账号无关的功能对于资讯等 App,在没有进行与用户信息相关的操作时,却强行让用户登录,甚至不登录就无法看到任何内容,有可能会被拒绝。

11、iPhone 应用在 iPad 上不能正常显示iPhone程序必须不经修改就能以iPhone分辨率和2倍iPhone 3GS的分辨率在iPad上运行。即使你的App 只为 iPhone 用户提供,在 iPad 上也必须能够正常显示,否则审核会被拒绝。

12、侵犯第三方版权对于视频、音乐、图书类的应用很容易因为这一条而被拒。另外 ASO100.com 建议应用内最好不要出现第三方的商标,例如运营商的Logo、影视公司的 Logo 等。13、应用截图、名称、描述等出现不雅词汇在应用截图、名称、描述等任何地方出现例如诸如 牛逼、绿茶婊、无节操、逗比 等词汇,都会被苹果审核拒绝。

14、应用出现 beta版、测试版字样不要过度谦虚地在启动画面或者应用名称上加上”beta”字样,苹果不允许测试版产品上架。

15、注册缺少隐私政策如果应用包含注册功能,注册页面必须提供隐私说明协议按钮或者链接。另外在 iTunes connect 提交新版本的时候,Privacy Policy URL 必须要填写。

16、应用出现崩溃、加载失败等 bug审核期间出现崩溃会导致审核被拒。ASO100.com 建议,在审核期间务必保证服务器稳定,避免审核人员审核时出现内容加载失败的情况,导致被拒。

17、应用描述、截图和应用功能不符如果应用的描述或截图介绍的功能在审核期间没有体现,则会被拒绝,如果介绍文案不够详细也会有一定概率被拒。

18、应用包含应用推荐功能除特殊情况,苹果明令禁止应用内推荐其他APP。

19、应用包含不正确的诊断功能如果你的应用中,包含不真实的系统检测或优化功能,苹果会认为这项功能有误导用户的嫌疑,审核时会被拒绝。

20、应用提交的新版本与上一版差异过大如果你提交的新版本应用与上一版相比,功能上变化过大,比如将游戏升级为工具类应用,或在新版本中完全改掉前一版产品的功能,则会被苹果拒绝。

收起阅读 »

解决mui.ajax使用FormData方式上传图片无法接收参数的问题

经验分享 图片上传

以前图片上传一直采用的图片压缩后上传base64字符串的方式,没有任何问题,最近的一个项目跟其他端是公用的接口,必须使用input file文件上传图片,结果接口各种接收不到formData append的参数,论坛各种搜都是说放弃file上传方式,最后采用原生XMLHttpRequest上传终于可以了。代码如下:

var xhr = new XMLHttpRequest();  
var formData = new FormData();  
formData.append('file', file);  
formData.append('openId', localStorage.openId);  
formData.append('provider', 'app');  

xhr.open('POST', URL + 'mobileshopapi/Common/PostUploadImage', true);  
xhr.onreadystatechange = function(){  
    if(xhr.readyState == 4 && xhr.status == 200){  
        var res = JSON.parse(xhr.responseText)  
    }  
}  
xhr.send(formData);
继续阅读 »

以前图片上传一直采用的图片压缩后上传base64字符串的方式,没有任何问题,最近的一个项目跟其他端是公用的接口,必须使用input file文件上传图片,结果接口各种接收不到formData append的参数,论坛各种搜都是说放弃file上传方式,最后采用原生XMLHttpRequest上传终于可以了。代码如下:

var xhr = new XMLHttpRequest();  
var formData = new FormData();  
formData.append('file', file);  
formData.append('openId', localStorage.openId);  
formData.append('provider', 'app');  

xhr.open('POST', URL + 'mobileshopapi/Common/PostUploadImage', true);  
xhr.onreadystatechange = function(){  
    if(xhr.readyState == 4 && xhr.status == 200){  
        var res = JSON.parse(xhr.responseText)  
    }  
}  
xhr.send(formData);
收起阅读 »

使用mix-mall为模板的商城Api终于诞生了

先贴代码

https://gitee.com/iotechn/unimall

使用SpringBoot + MyBatis-plus作为基础框架。

支持单机部署、集群部署,不用担心性能扩展了!!

完全面向服务开发,方便以后重构微服务。

在此非常感谢MixR大神!!

继续阅读 »

先贴代码

https://gitee.com/iotechn/unimall

使用SpringBoot + MyBatis-plus作为基础框架。

支持单机部署、集群部署,不用担心性能扩展了!!

完全面向服务开发,方便以后重构微服务。

在此非常感谢MixR大神!!

收起阅读 »

解决 HBuilderX + UniApp + Ts + 父组件Prop 在微信小程序中 无法绑定的 BUG;

uniapp

项目转到 TS 以后,基本就没有使用过 Js 了。。所以下面的所有代码都使用 TS 作为说明; (PS.,我的项目的 ts 和 vue 是分开的)。

父组件 BaseUniComponent.ts 就是定义了一个 父组件中的 prop
import { Component, Emit, Prop, Vue } from "vue-property-decorator";
export default class BaseUniComponent extends Vue{
@Prop({ default: null})
propInParent: null | string;
}
子组件 UserMoneyDetail.ts (继承子父组件,并且定义了一个子组件内的 prop)
import { Component, Emit, Prop, Vue } from "vue-property-decorator";
import BaseUniComponent from './Basic/BaseUniComponent';
@Component({})
export default class UserIncome extends BaseUniComponent {
@Prop({default: null})
propInComponent: null | string;
}
子组件页面: UserMoneyDetail.vue ( 显示传入进来的 prop 的值)
<template>
<view class="content">
<view>propInComponent: {{propInComponent}}</view>
<view>propInParent: {{propInParent}}</view>
</view>
</template>
<script lang="ts" src='./UserMoneyDetail.ts'></script>
入口页面 unientry.ts
import { Component, Emit, Prop, Vue } from "vue-property-decorator";
import UserMoney from './UserMoneyDetail.vue';
@Component({
components: {
UserMoney
}
})
export default class index extends Vue {
title: string = 'Hello';
}
入口页面 unientry.vue (分别绑定了定义在子组件内部的 prop 和 子组件继承自父类的 prop)
<template>
<view>
<UserMoney :propInComponent='title' :propInParent='title'></UserMoney>
</view>
</template>
<script lang="ts" src='./unientry.ts'></script>

在 h5 中这个毫无疑问正常,会显示 2个 Hello,
但是,编译到微信小程序中,却只会显示一个 Hello; ( 我的版本 , HBuilder X 2.2.2.20190816, )

最终发现一个是 HBuilder x 将代码编译成 微信小程序的问题, 也就是 uni-mp-weixin/dist/index.js 编译时,会丢失从父类继承过来的 prop 的定义;
此文件中第 682行定义了如下函数:
function initVueComponent (Vue, vueOptions) {
vueOptions = vueOptions.default || vueOptions;
let VueComponent;
if (isFn(vueOptions)) {
VueComponent = vueOptions;
vueOptions = VueComponent.extendOptions;
} else {
VueComponent = Vue.extend(vueOptions);
}
return [VueComponent, vueOptions]
}
根据 vue.d.ts , 我没有找到 extendOptions 的任何说明,估计是一个未公开的属性吧;
但是 VueComponent.extendOptions 这个属性里面不包含有继承自父类的 Prop,这也就使得,后面在根据返回的 vueOptions 去创建 Vue 的实例时,也丢失了从父类继承而来的 Prop, 进而使得在 unientry.vue 中 :propInParent='title' 无法绑定子组件继承子父组件的 Prop;

问题找到,改正倒是非常简单。 修改 initVueComponent 的函数定义就可以了;
function initVueComponent (Vue, vueOptions) {
let inputVueOptions = vueOptions; //方便调试
vueOptions = vueOptions.default || vueOptions;
let VueComponent;
if (isFn(vueOptions)) {
VueComponent = vueOptions;
vueOptions = VueComponent.extendOptions;

    //#region 往 vueOptions 中补充定义在父组件中但未定义在子组件中的 prop  
let defaultInputVueOptions = inputVueOptions['default'];  
if (defaultInputVueOptions && defaultInputVueOptions.options && defaultInputVueOptions.options.props) {  
    if (!vueOptions.props) vueOptions.props = {};  
    let propsInDefaultInputVueOptions = defaultInputVueOptions.options.props;  
    for (var oneProp in propsInDefaultInputVueOptions) {  
        if (!vueOptions.props[oneProp]) {  
            vueOptions.props[oneProp] = propsInDefaultInputVueOptions[oneProp];  
        }  
    }  
}  
    //#endregion  

} else {
VueComponent = Vue.extend(vueOptions);
}
return [VueComponent, vueOptions]
}
编译到微信小程序中,显示正常( 我的版本 , HBuilder X 2.2.2.20190816, )

顺带做了一个项目模板: https://github.com/hesi726/HBuildX-UniApp-Ts-Template

继续阅读 »

项目转到 TS 以后,基本就没有使用过 Js 了。。所以下面的所有代码都使用 TS 作为说明; (PS.,我的项目的 ts 和 vue 是分开的)。

父组件 BaseUniComponent.ts 就是定义了一个 父组件中的 prop
import { Component, Emit, Prop, Vue } from "vue-property-decorator";
export default class BaseUniComponent extends Vue{
@Prop({ default: null})
propInParent: null | string;
}
子组件 UserMoneyDetail.ts (继承子父组件,并且定义了一个子组件内的 prop)
import { Component, Emit, Prop, Vue } from "vue-property-decorator";
import BaseUniComponent from './Basic/BaseUniComponent';
@Component({})
export default class UserIncome extends BaseUniComponent {
@Prop({default: null})
propInComponent: null | string;
}
子组件页面: UserMoneyDetail.vue ( 显示传入进来的 prop 的值)
<template>
<view class="content">
<view>propInComponent: {{propInComponent}}</view>
<view>propInParent: {{propInParent}}</view>
</view>
</template>
<script lang="ts" src='./UserMoneyDetail.ts'></script>
入口页面 unientry.ts
import { Component, Emit, Prop, Vue } from "vue-property-decorator";
import UserMoney from './UserMoneyDetail.vue';
@Component({
components: {
UserMoney
}
})
export default class index extends Vue {
title: string = 'Hello';
}
入口页面 unientry.vue (分别绑定了定义在子组件内部的 prop 和 子组件继承自父类的 prop)
<template>
<view>
<UserMoney :propInComponent='title' :propInParent='title'></UserMoney>
</view>
</template>
<script lang="ts" src='./unientry.ts'></script>

在 h5 中这个毫无疑问正常,会显示 2个 Hello,
但是,编译到微信小程序中,却只会显示一个 Hello; ( 我的版本 , HBuilder X 2.2.2.20190816, )

最终发现一个是 HBuilder x 将代码编译成 微信小程序的问题, 也就是 uni-mp-weixin/dist/index.js 编译时,会丢失从父类继承过来的 prop 的定义;
此文件中第 682行定义了如下函数:
function initVueComponent (Vue, vueOptions) {
vueOptions = vueOptions.default || vueOptions;
let VueComponent;
if (isFn(vueOptions)) {
VueComponent = vueOptions;
vueOptions = VueComponent.extendOptions;
} else {
VueComponent = Vue.extend(vueOptions);
}
return [VueComponent, vueOptions]
}
根据 vue.d.ts , 我没有找到 extendOptions 的任何说明,估计是一个未公开的属性吧;
但是 VueComponent.extendOptions 这个属性里面不包含有继承自父类的 Prop,这也就使得,后面在根据返回的 vueOptions 去创建 Vue 的实例时,也丢失了从父类继承而来的 Prop, 进而使得在 unientry.vue 中 :propInParent='title' 无法绑定子组件继承子父组件的 Prop;

问题找到,改正倒是非常简单。 修改 initVueComponent 的函数定义就可以了;
function initVueComponent (Vue, vueOptions) {
let inputVueOptions = vueOptions; //方便调试
vueOptions = vueOptions.default || vueOptions;
let VueComponent;
if (isFn(vueOptions)) {
VueComponent = vueOptions;
vueOptions = VueComponent.extendOptions;

    //#region 往 vueOptions 中补充定义在父组件中但未定义在子组件中的 prop  
let defaultInputVueOptions = inputVueOptions['default'];  
if (defaultInputVueOptions && defaultInputVueOptions.options && defaultInputVueOptions.options.props) {  
    if (!vueOptions.props) vueOptions.props = {};  
    let propsInDefaultInputVueOptions = defaultInputVueOptions.options.props;  
    for (var oneProp in propsInDefaultInputVueOptions) {  
        if (!vueOptions.props[oneProp]) {  
            vueOptions.props[oneProp] = propsInDefaultInputVueOptions[oneProp];  
        }  
    }  
}  
    //#endregion  

} else {
VueComponent = Vue.extend(vueOptions);
}
return [VueComponent, vueOptions]
}
编译到微信小程序中,显示正常( 我的版本 , HBuilder X 2.2.2.20190816, )

顺带做了一个项目模板: https://github.com/hesi726/HBuildX-UniApp-Ts-Template

收起阅读 »

MUI-POPOVER中加入mui-scroll无法滚动的问题

scroll popover

MUI-POPOVER中加入mui-scroll无法滚动的问题

最近遇到个需求,需要在mui-popover弹出框中加入列表并且有分页,所以就用了mui的上拉加载和下拉刷新,结果发现mui-scroll在mui-popover中不能滑动,经过查询资料得知,mui.js将popover里的touchmove事件给拦截了,所以内容是不允许滑动(滚动)。

最后在mui.js中注市调如下代码就没问题了
参考文章
修改方法:

    var onPopoverShown = function(e) {  
        this.removeEventListener('webkitTransitionEnd', onPopoverShown);  
        // 发现说是mui.js将popover里的touchmove事件给拦截了,所以内容是不允许滑动(滚动),注释掉下面这段就好了  

        //      this.addEventListener($.EVENT_MOVE, $.preventDefault);  
        $.trigger(this, 'shown', this);  
    }
继续阅读 »

MUI-POPOVER中加入mui-scroll无法滚动的问题

最近遇到个需求,需要在mui-popover弹出框中加入列表并且有分页,所以就用了mui的上拉加载和下拉刷新,结果发现mui-scroll在mui-popover中不能滑动,经过查询资料得知,mui.js将popover里的touchmove事件给拦截了,所以内容是不允许滑动(滚动)。

最后在mui.js中注市调如下代码就没问题了
参考文章
修改方法:

    var onPopoverShown = function(e) {  
        this.removeEventListener('webkitTransitionEnd', onPopoverShown);  
        // 发现说是mui.js将popover里的touchmove事件给拦截了,所以内容是不允许滑动(滚动),注释掉下面这段就好了  

        //      this.addEventListener($.EVENT_MOVE, $.preventDefault);  
        $.trigger(this, 'shown', this);  
    }
收起阅读 »

在 WebStorm 中开发 uni-app

WebStorm

CLI 工程

全局安装 vue-cli 3.x(如已安装请跳过此步骤)

npm install -g @vue/cli

通过 CLI 创建 uni-app 项目

vue create -p dcloudio/uni-preset-vue my-project

此时,会提示选择项目模板,初次体验建议选择 hello uni-app 项目模板,如下所示:

<div>
<img src="http://img.cdn.aliyun.dcloud.net.cn/guide/uniapp/h5-cli-01.png" width="300">
</div>

在 WebStorm 中打开项目

CLI 工程默认带了 uni-app 语法提示和 5+App 语法提示

运行项目

npm run dev:%PLATFORM%

发布项目

npm run build:%PLATFORM%

%PLATFORM% 可取值如下:

平台
h5 H5
mp-alipay 支付宝小程序
mp-baidu 百度小程序
mp-weixin 微信小程序
mp-toutiao 头条小程序
mp-qq qq 小程序

CLI 方式参考文档

HBuilderX 工程

HBuilderX 创建的工程默认不带 types 语法提示,在 WebStorm 中编辑的时候,可以自行安装

初始化npm(如已初始化跳过此步骤)

npm init -y

安装 uni-app 语法提示

npm i @dcloudio/types -D

注意

webstorm不识别rpx等单位

如果想了解HBuilderX为uni-app做了什么更好的优化,参考:https://ask.dcloud.net.cn/article/35451

继续阅读 »

CLI 工程

全局安装 vue-cli 3.x(如已安装请跳过此步骤)

npm install -g @vue/cli

通过 CLI 创建 uni-app 项目

vue create -p dcloudio/uni-preset-vue my-project

此时,会提示选择项目模板,初次体验建议选择 hello uni-app 项目模板,如下所示:

<div>
<img src="http://img.cdn.aliyun.dcloud.net.cn/guide/uniapp/h5-cli-01.png" width="300">
</div>

在 WebStorm 中打开项目

CLI 工程默认带了 uni-app 语法提示和 5+App 语法提示

运行项目

npm run dev:%PLATFORM%

发布项目

npm run build:%PLATFORM%

%PLATFORM% 可取值如下:

平台
h5 H5
mp-alipay 支付宝小程序
mp-baidu 百度小程序
mp-weixin 微信小程序
mp-toutiao 头条小程序
mp-qq qq 小程序

CLI 方式参考文档

HBuilderX 工程

HBuilderX 创建的工程默认不带 types 语法提示,在 WebStorm 中编辑的时候,可以自行安装

初始化npm(如已初始化跳过此步骤)

npm init -y

安装 uni-app 语法提示

npm i @dcloudio/types -D

注意

webstorm不识别rpx等单位

如果想了解HBuilderX为uni-app做了什么更好的优化,参考:https://ask.dcloud.net.cn/article/35451

收起阅读 »

uniapp安卓缓存计算、缓存清理

官方有个未显示的文档http://www.html5plus.org/doc/zh_cn/cache.html用于管理应用缓存
但有些方法在uniapp上报错
感谢二位大佬提供的文章
师大酸梅杨
https://ask.dcloud.net.cn/article/1191
绝地求生
https://ask.dcloud.net.cn/article/13375
通过两位大佬的文章结合做出一个在uniapp安卓系统上可以计算缓存和清理缓存的代码,ios上可以计算但未找到获取缓存路径的方法,希望官方给出方案

计算缓存大小方法

             formatSize() {  
                let that = this;  
                plus.cache.calculate(function(size) {  
                    let sizeCache = parseInt(size);  
                    if (sizeCache == 0) {  
                        that.fileSizeString = "0B";  
                    } else if (sizeCache < 1024) {  
                        that.fileSizeString = sizeCache + "B";  
                    } else if (sizeCache < 1048576) {  
                        that.fileSizeString = (sizeCache / 1024).toFixed(2) + "KB";  
                    } else if (sizeCache < 1073741824) {  
                        that.fileSizeString = (sizeCache / 1048576).toFixed(2) + "MB";  
                    } else {  
                        that.fileSizeString = (sizeCache / 1073741824).toFixed(2) + "GB";  
                    }  
                });  
            }

安卓清理缓存方法

        clearCache() {  
                let that = this;  
                let os = plus.os.name;  
                if (os == 'Android') {  
                    let main = plus.android.runtimeMainActivity();  
                    let sdRoot = main.getCacheDir();  
                    let files = plus.android.invoke(sdRoot, "listFiles");  
                    let len = files.length;  
                    for (let i = 0; i < len; i++) {  
                        let filePath = '' + files[i]; // 没有找到合适的方法获取路径,这样写可以转成文件路径  
                        plus.io.resolveLocalFileSystemURL(filePath, function(entry) {  
                            if (entry.isDirectory) {  
                                entry.removeRecursively(function(entry) { //递归删除其下的所有文件及子目录  
                                    uni.showToast({  
                                        title: '缓存清理完成',  
                                        duration: 2000  
                                    });  
                                    that.formatSize(); // 重新计算缓存  
                                }, function(e) {  
                                    console.log(e.message)  
                                });  
                            } else {  
                                entry.remove();  
                            }  
                        }, function(e) {  
                            console.log('文件路径读取失败')  
                        });  
                    }  
                } else { // ios暂时未找到清理缓存的方法,以下是官方提供的方法,但是无效,会报错  
                    plus.cache.clear(function() {  
                        uni.showToast({  
                            title: '缓存清理完成',  
                            duration: 2000  
                        });  
                        that.formatSize();  
                    });  
                }  
            }
继续阅读 »

官方有个未显示的文档http://www.html5plus.org/doc/zh_cn/cache.html用于管理应用缓存
但有些方法在uniapp上报错
感谢二位大佬提供的文章
师大酸梅杨
https://ask.dcloud.net.cn/article/1191
绝地求生
https://ask.dcloud.net.cn/article/13375
通过两位大佬的文章结合做出一个在uniapp安卓系统上可以计算缓存和清理缓存的代码,ios上可以计算但未找到获取缓存路径的方法,希望官方给出方案

计算缓存大小方法

             formatSize() {  
                let that = this;  
                plus.cache.calculate(function(size) {  
                    let sizeCache = parseInt(size);  
                    if (sizeCache == 0) {  
                        that.fileSizeString = "0B";  
                    } else if (sizeCache < 1024) {  
                        that.fileSizeString = sizeCache + "B";  
                    } else if (sizeCache < 1048576) {  
                        that.fileSizeString = (sizeCache / 1024).toFixed(2) + "KB";  
                    } else if (sizeCache < 1073741824) {  
                        that.fileSizeString = (sizeCache / 1048576).toFixed(2) + "MB";  
                    } else {  
                        that.fileSizeString = (sizeCache / 1073741824).toFixed(2) + "GB";  
                    }  
                });  
            }

安卓清理缓存方法

        clearCache() {  
                let that = this;  
                let os = plus.os.name;  
                if (os == 'Android') {  
                    let main = plus.android.runtimeMainActivity();  
                    let sdRoot = main.getCacheDir();  
                    let files = plus.android.invoke(sdRoot, "listFiles");  
                    let len = files.length;  
                    for (let i = 0; i < len; i++) {  
                        let filePath = '' + files[i]; // 没有找到合适的方法获取路径,这样写可以转成文件路径  
                        plus.io.resolveLocalFileSystemURL(filePath, function(entry) {  
                            if (entry.isDirectory) {  
                                entry.removeRecursively(function(entry) { //递归删除其下的所有文件及子目录  
                                    uni.showToast({  
                                        title: '缓存清理完成',  
                                        duration: 2000  
                                    });  
                                    that.formatSize(); // 重新计算缓存  
                                }, function(e) {  
                                    console.log(e.message)  
                                });  
                            } else {  
                                entry.remove();  
                            }  
                        }, function(e) {  
                            console.log('文件路径读取失败')  
                        });  
                    }  
                } else { // ios暂时未找到清理缓存的方法,以下是官方提供的方法,但是无效,会报错  
                    plus.cache.clear(function() {  
                        uni.showToast({  
                            title: '缓存清理完成',  
                            duration: 2000  
                        });  
                        that.formatSize();  
                    });  
                }  
            }
收起阅读 »

uni 统计自定义事件说明

uni统计 uniapp

自定义事件是为了给开发者提供自定义上报统计数据的功能,如统计登录、注册、分享、点击某个按钮,我们都可以称之为自定义事件。

自定义事件 API

uni.report( eventName , options)

参数说明

参数 类型 描述
eventName String 事件名称,最大长度不超过 255 个字符
options String 、 Object 事件参数

Tips

  • eventName 为 String 类型,并且字符长度必须小于255
  • options 为 String 类型时,字符长度必须小于255
  • options 为 Object 类型时,该对象的值只能为 String 类型
  • 字符串支持特殊字符但不包括(英文逗号 , 英文冒号 : 点 .)
  • eventName 为 title 时为内容标题上报,用户不能自定义。此时数据会展现在uni统计的首页-内容统计及左侧导航的内容统计中。方便查看内容页数据。
  • 用户在使用 uni.login() 会执行登录事件,不携带参数。如果如需上报携带具体参数的数据,需要手动调用 uni.report('login',{...})
  • 用户在使用 uni.share() 或触发 onShareAppMessage 会执行分享事件,不携带参数。如果如需上报携带具体参数的数据,需要手动调用 uni.report('share',{...})
  • 用户在使用 uni.requestPayment() 会执行支付事件,不携带参数。如果如需上报携带具体参数的数据,需要手动调用 uni.report('pay_success',{...})uni.report('pay_fail',{...})

示例

// 内容统计  
// 当 eventName 为 title 时,options 只能为 String 类型  
uni.report('title','首页')  

// 登录  
uni.report('login',{  
  'name':'uni-app',  
  'age':'21',  
  // ...  
})  

// 分享  
uni.report('share','分享')  

// 支付成功  
uni.report('pay_success','支付成功')  
// or  
uni.report('pay_success',{  
  "订单金额":'20元',  
  "订单名称":'鼠标',  
  // ...  
})  

// 支付失败  
uni.report('pay_fail','支付失败')  
// or  
uni.report('pay_fail',{  
  "订单金额":'20元',  
  "订单名称":'鼠标',  
  // ...  
})  

// 注册  
uni.report('register',{  
  'name':'uni-app',  
  'age':'21',  
  // ...  
})  

// 搜索  
uni.report('search','搜索内容')  
// or  
uni.report('search',{  
  '内容':'搜索内容'  
})  

自定义事件上报后,在统计后台的事件和转换栏目中,可以看到上报的事件情况。

继续阅读 »

自定义事件是为了给开发者提供自定义上报统计数据的功能,如统计登录、注册、分享、点击某个按钮,我们都可以称之为自定义事件。

自定义事件 API

uni.report( eventName , options)

参数说明

参数 类型 描述
eventName String 事件名称,最大长度不超过 255 个字符
options String 、 Object 事件参数

Tips

  • eventName 为 String 类型,并且字符长度必须小于255
  • options 为 String 类型时,字符长度必须小于255
  • options 为 Object 类型时,该对象的值只能为 String 类型
  • 字符串支持特殊字符但不包括(英文逗号 , 英文冒号 : 点 .)
  • eventName 为 title 时为内容标题上报,用户不能自定义。此时数据会展现在uni统计的首页-内容统计及左侧导航的内容统计中。方便查看内容页数据。
  • 用户在使用 uni.login() 会执行登录事件,不携带参数。如果如需上报携带具体参数的数据,需要手动调用 uni.report('login',{...})
  • 用户在使用 uni.share() 或触发 onShareAppMessage 会执行分享事件,不携带参数。如果如需上报携带具体参数的数据,需要手动调用 uni.report('share',{...})
  • 用户在使用 uni.requestPayment() 会执行支付事件,不携带参数。如果如需上报携带具体参数的数据,需要手动调用 uni.report('pay_success',{...})uni.report('pay_fail',{...})

示例

// 内容统计  
// 当 eventName 为 title 时,options 只能为 String 类型  
uni.report('title','首页')  

// 登录  
uni.report('login',{  
  'name':'uni-app',  
  'age':'21',  
  // ...  
})  

// 分享  
uni.report('share','分享')  

// 支付成功  
uni.report('pay_success','支付成功')  
// or  
uni.report('pay_success',{  
  "订单金额":'20元',  
  "订单名称":'鼠标',  
  // ...  
})  

// 支付失败  
uni.report('pay_fail','支付失败')  
// or  
uni.report('pay_fail',{  
  "订单金额":'20元',  
  "订单名称":'鼠标',  
  // ...  
})  

// 注册  
uni.report('register',{  
  'name':'uni-app',  
  'age':'21',  
  // ...  
})  

// 搜索  
uni.report('search','搜索内容')  
// or  
uni.report('search',{  
  '内容':'搜索内容'  
})  

自定义事件上报后,在统计后台的事件和转换栏目中,可以看到上报的事件情况。

收起阅读 »

uni统计1.0入门教程

uni统计 uniapp

uni统计2.0已经发布 ,uni统计2.0 是开源、全端、云端一体的统计平台。另行查看:文档

以下是uni统计1.0的文档

  1. 无需在各端接不同的sdk、无需在不同报表看数据。uni统计:一张报表看遍业务全景。
  2. 拉通内容。让你知道用户到底喜欢你提供的什么内容,不管是新闻app里的新闻,还是购物app里的商品,都可以一目了然的看到全景。

web控制台地址:https://tongji.dcloud.net.cn

第一步、配置统计开关

自 uni-app 2.2.3版本后,uni-app项目在发布时会默认启用 uni统计,开发者可在https://tongji.dcloud.net.cn查看数据报表。
但从 uni-app 2.7起,默认值改为了不启用。需要在manifest中手动配置开启。

在HBuilderX中打开manifest,选择 uni统计,如下图:

如果不使用HBuilderX,也可在 manifest.json 的源码视图中手动关闭 uni统计

manifest.json -> uniStatistics 下的 enable 字段设置为 false 来关闭 uni 统计

//...  
"uniStatistics": {  
    "enable": false//全局关闭  
},  
//...

注意:uniStatistics支持分平台设置,比如若需仅关闭微信平台的 uni统计,则在mp-weixin节点下设置uniStatistics ->enable即可,如下:

//...  
"mp-weixin":{  
    "uniStatistics": {  
        "enable": false //微信平台关闭统计  
    }  
}

第二步、小程序端需添加域名访问白名单

由于各家小程序对可访问的域名要配置白名单,否则无法联网,所以需要将tongji.dcloud.io配入服务器域名列表。详细教程可参考https://ask.dcloud.net.cn/article/36298

第三步、使用HBuilderX 2.2.3以上或对应的cli版发行应用

应用在运行、调试时不会上报统计数据,仅在发行后,并启动新版的App、h5、小程序,才会上报数据。

第四步、登陆统计后台看数据

uni统计报表网址:https://tongji.dcloud.net.cn

请使用正确的DCloud账户登陆后台,每个DCloud账户登陆后可看到自己名下创建的应用。如果看不到期待的应用,那说明这个账户不是某个应用的所有者。

如果appid对应的项目的所有者发生变更,请参考如何转让应用

数据报表更新有延时,手机端上报数据后延迟几十分钟可在后台报表看到数据。


发行时为什么提示“当前应用未配置Appid,无法使用uni统计”

uni统计以appid区分不同应用,因此在编译项目时,若发现当前应用未配置appid,则会在控制台显示如下警告提醒:

当前应用未配置Appid,无法使用uni统计

此时,开发者可通过HBuilderX、DCloud开发者中心两个入口创建应用,获取Appid。

方式1. 登录HBluiderX获取

在HBluiderX中先登录,然后在项目根目录打开 manifest.json,在可视化界面点击获取 APPID 获取,无需其他设置,如下图

获取appid

方式2. 登录DCoud开发者中心获取(即将支持)

登录DCloud开发者中心,在线创建应用,然后将新应用的appid填写到manifest.json中

{  
  // ...  
  "appid":"创建的 appid"  
  // ...  
}

Tips

  • 使用 uni 统计必须配置 APPID 才能正常使用
  • 获取以及创建的 APPID 是与您的 DCloud 账号绑定的,请不要随意填写,否则将不能正常获取上报内容
  • 部分开发者不重视Appid,在不同应用中使用相同的appid,请修改这些错误的行为。
  • 附参考文章:DCloud的Appid有什么用,如需转让应用怎么做

注意事项

  • uni统计具备当日实时数据统计功能,但这个实时,仍然要经历一定运算时间,一般在3分钟到1个小时内的不等。
  • 如果开发者连续3日不登录uni统计控制台,则暂停实时统计服务;再次登录后1小时内会开始进行实时统计。这种暂停不影响日报、不影响整体数据准确性。
  • 如果开发者连续1个月不登录uni统计控制台,则暂停数据上报功能。再次登录后点击按钮恢复数据上报。暂停前系统会发送提醒邮件给开发者。暂停期间,数据不再记录,历史数据不受影响。恢复后,暂停期间的数据也无法恢复。

常见问题

  1. 后台数据一直显示 0 ,看不到数据上报

    • 请检查 manifest.json 是否配置 uni 统计为开启
    • 如已经配置请检查 HBuilderX 是否升级到 2.2.3 版本以上,CLI 方式是否升级到最新。
    • 请确认小程序的服务器域名名单中加入了tongji.dcloud.io
    • 请确认带有uni统计的新版本已经发布到手机上并且启动运行
    • 统计数据有几十分钟的延迟,如果是刚配上,请等一会再刷新报表
    • 应用需发布后才有数据,运行期不上报数据
    • 当日实时统计显示逻辑:3天内未登录统计后台的应用不会处理当日实时统计;再次登录后1小时内会开始进行实时统计。
  2. 自定义事件怎么用
    使用 uni.report() API 上报数据,详见自定义事件说明

  3. 内容统计是什么/ 页面规则怎么配置
    内容统计是uni统计的特色功能之一,是内容详情页的访问统计,详见内容统计说明

  4. 不支持导入老数据合并统计。uni统计需要自开通上线后才有数据

  5. 售卖用户数据,或未经用户同意共享数据给第三方,属于违法行为,DCloud严格遵守国家法律要求,uni统计可安心使用。

继续阅读 »

uni统计2.0已经发布 ,uni统计2.0 是开源、全端、云端一体的统计平台。另行查看:文档

以下是uni统计1.0的文档

  1. 无需在各端接不同的sdk、无需在不同报表看数据。uni统计:一张报表看遍业务全景。
  2. 拉通内容。让你知道用户到底喜欢你提供的什么内容,不管是新闻app里的新闻,还是购物app里的商品,都可以一目了然的看到全景。

web控制台地址:https://tongji.dcloud.net.cn

第一步、配置统计开关

自 uni-app 2.2.3版本后,uni-app项目在发布时会默认启用 uni统计,开发者可在https://tongji.dcloud.net.cn查看数据报表。
但从 uni-app 2.7起,默认值改为了不启用。需要在manifest中手动配置开启。

在HBuilderX中打开manifest,选择 uni统计,如下图:

如果不使用HBuilderX,也可在 manifest.json 的源码视图中手动关闭 uni统计

manifest.json -> uniStatistics 下的 enable 字段设置为 false 来关闭 uni 统计

//...  
"uniStatistics": {  
    "enable": false//全局关闭  
},  
//...

注意:uniStatistics支持分平台设置,比如若需仅关闭微信平台的 uni统计,则在mp-weixin节点下设置uniStatistics ->enable即可,如下:

//...  
"mp-weixin":{  
    "uniStatistics": {  
        "enable": false //微信平台关闭统计  
    }  
}

第二步、小程序端需添加域名访问白名单

由于各家小程序对可访问的域名要配置白名单,否则无法联网,所以需要将tongji.dcloud.io配入服务器域名列表。详细教程可参考https://ask.dcloud.net.cn/article/36298

第三步、使用HBuilderX 2.2.3以上或对应的cli版发行应用

应用在运行、调试时不会上报统计数据,仅在发行后,并启动新版的App、h5、小程序,才会上报数据。

第四步、登陆统计后台看数据

uni统计报表网址:https://tongji.dcloud.net.cn

请使用正确的DCloud账户登陆后台,每个DCloud账户登陆后可看到自己名下创建的应用。如果看不到期待的应用,那说明这个账户不是某个应用的所有者。

如果appid对应的项目的所有者发生变更,请参考如何转让应用

数据报表更新有延时,手机端上报数据后延迟几十分钟可在后台报表看到数据。


发行时为什么提示“当前应用未配置Appid,无法使用uni统计”

uni统计以appid区分不同应用,因此在编译项目时,若发现当前应用未配置appid,则会在控制台显示如下警告提醒:

当前应用未配置Appid,无法使用uni统计

此时,开发者可通过HBuilderX、DCloud开发者中心两个入口创建应用,获取Appid。

方式1. 登录HBluiderX获取

在HBluiderX中先登录,然后在项目根目录打开 manifest.json,在可视化界面点击获取 APPID 获取,无需其他设置,如下图

获取appid

方式2. 登录DCoud开发者中心获取(即将支持)

登录DCloud开发者中心,在线创建应用,然后将新应用的appid填写到manifest.json中

{  
  // ...  
  "appid":"创建的 appid"  
  // ...  
}

Tips

  • 使用 uni 统计必须配置 APPID 才能正常使用
  • 获取以及创建的 APPID 是与您的 DCloud 账号绑定的,请不要随意填写,否则将不能正常获取上报内容
  • 部分开发者不重视Appid,在不同应用中使用相同的appid,请修改这些错误的行为。
  • 附参考文章:DCloud的Appid有什么用,如需转让应用怎么做

注意事项

  • uni统计具备当日实时数据统计功能,但这个实时,仍然要经历一定运算时间,一般在3分钟到1个小时内的不等。
  • 如果开发者连续3日不登录uni统计控制台,则暂停实时统计服务;再次登录后1小时内会开始进行实时统计。这种暂停不影响日报、不影响整体数据准确性。
  • 如果开发者连续1个月不登录uni统计控制台,则暂停数据上报功能。再次登录后点击按钮恢复数据上报。暂停前系统会发送提醒邮件给开发者。暂停期间,数据不再记录,历史数据不受影响。恢复后,暂停期间的数据也无法恢复。

常见问题

  1. 后台数据一直显示 0 ,看不到数据上报

    • 请检查 manifest.json 是否配置 uni 统计为开启
    • 如已经配置请检查 HBuilderX 是否升级到 2.2.3 版本以上,CLI 方式是否升级到最新。
    • 请确认小程序的服务器域名名单中加入了tongji.dcloud.io
    • 请确认带有uni统计的新版本已经发布到手机上并且启动运行
    • 统计数据有几十分钟的延迟,如果是刚配上,请等一会再刷新报表
    • 应用需发布后才有数据,运行期不上报数据
    • 当日实时统计显示逻辑:3天内未登录统计后台的应用不会处理当日实时统计;再次登录后1小时内会开始进行实时统计。
  2. 自定义事件怎么用
    使用 uni.report() API 上报数据,详见自定义事件说明

  3. 内容统计是什么/ 页面规则怎么配置
    内容统计是uni统计的特色功能之一,是内容详情页的访问统计,详见内容统计说明

  4. 不支持导入老数据合并统计。uni统计需要自开通上线后才有数据

  5. 售卖用户数据,或未经用户同意共享数据给第三方,属于违法行为,DCloud严格遵守国家法律要求,uni统计可安心使用。

收起阅读 »

页面绑定的数据深层次更新,Dom没有检测到导致页面并没有重新渲染。

数据交互

这是一个上拉加载的回调函数,调用getListDataFromNet函数从服务端获取数据,然后更新到页面数据orderList中,因为orderList是一个二维数组,所以深层的数据更新不会触发Dom的重新渲染,于是在数据更新后添加强制重新渲染 this.$forceUpdate(); 问题解决。

upCallback(mescroll) {  
                //联网加载数据  
                this.getListDataFromNet(mescroll.num, mescroll.size, (curPageData)=>{  
                    //联网成功的回调,隐藏下拉刷新和上拉加载的状态;  
                    mescroll.endSuccess(curPageData.length);  
                    //设置列表数据  

                    if(mescroll.num == 1) this.orderList[this.tabIndex] = []; //如果是第一页需手动制空列表  
                    this.orderList[this.tabIndex]=this.orderList[this.tabIndex].concat(curPageData); //追加新数据  
                    console.log(this.orderList[this.tabIndex])  
                    this.$forceUpdate();  
                }, () => {  
                    //联网失败的回调,隐藏下拉刷新的状态  
                    mescroll.endErr();  
                })    
            },
继续阅读 »

这是一个上拉加载的回调函数,调用getListDataFromNet函数从服务端获取数据,然后更新到页面数据orderList中,因为orderList是一个二维数组,所以深层的数据更新不会触发Dom的重新渲染,于是在数据更新后添加强制重新渲染 this.$forceUpdate(); 问题解决。

upCallback(mescroll) {  
                //联网加载数据  
                this.getListDataFromNet(mescroll.num, mescroll.size, (curPageData)=>{  
                    //联网成功的回调,隐藏下拉刷新和上拉加载的状态;  
                    mescroll.endSuccess(curPageData.length);  
                    //设置列表数据  

                    if(mescroll.num == 1) this.orderList[this.tabIndex] = []; //如果是第一页需手动制空列表  
                    this.orderList[this.tabIndex]=this.orderList[this.tabIndex].concat(curPageData); //追加新数据  
                    console.log(this.orderList[this.tabIndex])  
                    this.$forceUpdate();  
                }, () => {  
                    //联网失败的回调,隐藏下拉刷新的状态  
                    mescroll.endErr();  
                })    
            },
收起阅读 »

QQ小程序qq.getMenuButtonBoundingClientRect()获取为空

uni_app qq小程序

没关系,它不给,我们可以用模拟器+真机调试自己算

先给结论

{width:80,height:30,left:e.windowWidth-12-80,right:e.windowWidth-12,top:e.statusBarHeight+10,bottom:e.statusBarHeight+10+30};

这里的e是用uni.getSystemInfo得到的。可以看到效果如下

继续阅读 »

没关系,它不给,我们可以用模拟器+真机调试自己算

先给结论

{width:80,height:30,left:e.windowWidth-12-80,right:e.windowWidth-12,top:e.statusBarHeight+10,bottom:e.statusBarHeight+10+30};

这里的e是用uni.getSystemInfo得到的。可以看到效果如下

收起阅读 »