HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

终于把人人商城打包好了

1、支付宝原生支付,微信原生支付
2、分享微信,QQ
3、微信登录
4、退出App
5、清理App缓存
6、个推推送(订单推送)
有需要沟通的 M我把 vx 185341954

1、支付宝原生支付,微信原生支付
2、分享微信,QQ
3、微信登录
4、退出App
5、清理App缓存
6、个推推送(订单推送)
有需要沟通的 M我把 vx 185341954

Android平台 storage性能优化说明

Storage

HBuilderX2.6.6+起,Android平台对App本地storage数据存储进行了性能优化,包括plus.storage和uni的storage相关api,主要包括以下改进:

  • 数据存储方式优化
    之前的storage数据存储到Android系统的SharedPreferences中,现在修改为存储到数据库文件中。
    SharedPreferences 是 Android 平台为应用开发者提供的一个轻量级的存储辅助类,不适合存储大量的数据,当数据量过大时会影响性能甚至引发ANR。
    数据库文件存储则可以更好的支持大量数据存储,但需要注意JS与原生通讯时传输数据时也存在性能限制,因此不要一次存储大量的数据,建议每次存储数据不要超过100K。
  • 新增异步操作接口
    原来5+ API中plus.storage只提供同步操作接口,uni-app中的异步接口在App端也是封装同步接口实现的,之前并非真正异步。
    新版本已提供异步接口读取、保存数据,避免同步接口阻塞JS。uni-app中的异步接口也调整为真正的异步操作实现。

通过对比测试,以上优化单次读取速度提升10%,并发300次读取速度提升70%

应用升级向下兼容处理

为了确保应用的新版平滑兼容,当基于新版打包的App升级覆盖老版本App时,会在应用启动时自动将原来存储在SharedPreferences中的数据迁移到数据库文件中,开发者不需要做特殊处理就可以读取到老版本保存的数据。
如果老版App在手机端已经保存了大量数据,覆盖升级新版后,第一次运行新版会因为迁移数据而导致splash界面显示时间稍微变长一些。

注意事项
SharedPreferences方式存储的数据向数据库文件存储的升级,是不可逆的过程。
举个极端例子,开发者已有app版本1.0,并且已经在手机端存储了storage数据,然后开发者使用HBuilderX2.6.6+打包生成2.0的app,新app覆盖安装1.0版后,将storage数据从SharedPreferences迁移到了数据库文件。接着开发者又回退了HBuilderX版本,使用HBuilderX2.6.6-的版本,打包生成了3.0app,那么这个3.0app覆盖安装到手机上后,使用plus.storage和uni的storage相关api将无法读取历史数据,相关api会继续操作SharedPreferences方式存储的数据。

plus.storage新增异步接口的清单如下:

uni的storage操作api无变化,见:https://uniapp.dcloud.io/api/storage/storage?id=setstorage

继续阅读 »

HBuilderX2.6.6+起,Android平台对App本地storage数据存储进行了性能优化,包括plus.storage和uni的storage相关api,主要包括以下改进:

  • 数据存储方式优化
    之前的storage数据存储到Android系统的SharedPreferences中,现在修改为存储到数据库文件中。
    SharedPreferences 是 Android 平台为应用开发者提供的一个轻量级的存储辅助类,不适合存储大量的数据,当数据量过大时会影响性能甚至引发ANR。
    数据库文件存储则可以更好的支持大量数据存储,但需要注意JS与原生通讯时传输数据时也存在性能限制,因此不要一次存储大量的数据,建议每次存储数据不要超过100K。
  • 新增异步操作接口
    原来5+ API中plus.storage只提供同步操作接口,uni-app中的异步接口在App端也是封装同步接口实现的,之前并非真正异步。
    新版本已提供异步接口读取、保存数据,避免同步接口阻塞JS。uni-app中的异步接口也调整为真正的异步操作实现。

通过对比测试,以上优化单次读取速度提升10%,并发300次读取速度提升70%

应用升级向下兼容处理

为了确保应用的新版平滑兼容,当基于新版打包的App升级覆盖老版本App时,会在应用启动时自动将原来存储在SharedPreferences中的数据迁移到数据库文件中,开发者不需要做特殊处理就可以读取到老版本保存的数据。
如果老版App在手机端已经保存了大量数据,覆盖升级新版后,第一次运行新版会因为迁移数据而导致splash界面显示时间稍微变长一些。

注意事项
SharedPreferences方式存储的数据向数据库文件存储的升级,是不可逆的过程。
举个极端例子,开发者已有app版本1.0,并且已经在手机端存储了storage数据,然后开发者使用HBuilderX2.6.6+打包生成2.0的app,新app覆盖安装1.0版后,将storage数据从SharedPreferences迁移到了数据库文件。接着开发者又回退了HBuilderX版本,使用HBuilderX2.6.6-的版本,打包生成了3.0app,那么这个3.0app覆盖安装到手机上后,使用plus.storage和uni的storage相关api将无法读取历史数据,相关api会继续操作SharedPreferences方式存储的数据。

plus.storage新增异步接口的清单如下:

uni的storage操作api无变化,见:https://uniapp.dcloud.io/api/storage/storage?id=setstorage

收起阅读 »

HBuilderX 使用eslint实时校验、自动修复代码错误(适用于HBuilderX 2.6.8+)

eslint一键修复 eslint

HBuilderX 2.6.8+版本起,新增eslint 实时校验、自动修复错误的功能。注意:此文不适用于2.6.8之前的版本

插件下载地址

eslint-js插件下载地址
eslint-vue插件下载地址


1. eslint 文件保存,实时校验、自动修复错误功能说明

  1. 使用此功能,必须安装eslint-jseslint-vue插件。(菜单【工具】【插件安装】)
  2. vue-cli项目,需要安装eslint库,并配置eslint规则.
  3. 若满足上述条件,当编写完代码,保存时,若代码中存在错误,自动修复;

2. 插件设置

2.6.11版本,支持自定义配置:保存时自动修复启用实时校验;见下图

特别说明: 实时校验功能,默认未开启,需要手动开启此功能

3. 特别说明

特别说明: eslint自动修复功能,并不能修复所有的语法错误。
比如定义了某个变量,但未使用,eslint校验保存,自动修复功能并不能修复此类错误。

4. 普通项目:eslint规则配置

点击菜单【工具】【插件配置】【eslint-js】,编辑.eslintrc.js文件

eslint规则:https://eslint.org/docs/rules/

.eslintrc.js配置文件示例

module.exports = {  
    "plugins": [  
        "html"  
    ],  
    "parserOptions": {  
        "ecmaVersion": 2018,  
        "sourceType": "module",  
        "ecmaFeatures": {  
            "jsx": true  
        },  
        "allowImportExportEverywhere": false  
    },  
    rules: {  
        "no-alert": 0,  
        "semi": [2, "always"],  
        "no-multi-spaces": "error",  
       "quotes": ["error", "single"]  
    }  
}

示例:使用eslint, 删除多余的空格

5. vue-cli项目:eslint安装、配置

$ npm install --save eslint eslint-plugin-vue eslint-plugin-html eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-standard

安装完成后,在vue-cli项目根目录,创建.eslintrc.js文件

备注:(注意:项目下eslint规则会覆盖HBuilderX编辑器eslint插件中的规则

eslint-plugin-vue配置文件与规则:eslint-plugin-vue官方教程

.eslintrc.js配置文件示例

module.exports = {  
    extends: [  
        'plugin:vue/recommended'  
    ],  
    rules: {  
        "no-alert": 0,  
        "no-multi-spaces": "error", // 禁止多个空格   
        "semi": [2, "always"] ,// 自动补充分号  
       "quotes": ["error", "single"] // 使用单引号  
    }  
}

示例:使用eslint, 自动补充分号

6. 以uni-app项目为例,配置eslint规则,校验vue文件

特别说明:

  • vue文件,校验规则,需要从eslint-vue插件中配置。
  • 菜单【工具】【插件配置】【eslint-vue】【.eslintrc.js】,编辑.eslintrc.js文件

7. vue-cli 项目demo

附件中的zip包,为vue-cli项目demo。因为node_modules太大,所以未包含node_modules。解压zip后,请执行npm install安装node_modules

继续阅读 »

HBuilderX 2.6.8+版本起,新增eslint 实时校验、自动修复错误的功能。注意:此文不适用于2.6.8之前的版本

插件下载地址

eslint-js插件下载地址
eslint-vue插件下载地址


1. eslint 文件保存,实时校验、自动修复错误功能说明

  1. 使用此功能,必须安装eslint-jseslint-vue插件。(菜单【工具】【插件安装】)
  2. vue-cli项目,需要安装eslint库,并配置eslint规则.
  3. 若满足上述条件,当编写完代码,保存时,若代码中存在错误,自动修复;

2. 插件设置

2.6.11版本,支持自定义配置:保存时自动修复启用实时校验;见下图

特别说明: 实时校验功能,默认未开启,需要手动开启此功能

3. 特别说明

特别说明: eslint自动修复功能,并不能修复所有的语法错误。
比如定义了某个变量,但未使用,eslint校验保存,自动修复功能并不能修复此类错误。

4. 普通项目:eslint规则配置

点击菜单【工具】【插件配置】【eslint-js】,编辑.eslintrc.js文件

eslint规则:https://eslint.org/docs/rules/

.eslintrc.js配置文件示例

module.exports = {  
    "plugins": [  
        "html"  
    ],  
    "parserOptions": {  
        "ecmaVersion": 2018,  
        "sourceType": "module",  
        "ecmaFeatures": {  
            "jsx": true  
        },  
        "allowImportExportEverywhere": false  
    },  
    rules: {  
        "no-alert": 0,  
        "semi": [2, "always"],  
        "no-multi-spaces": "error",  
       "quotes": ["error", "single"]  
    }  
}

示例:使用eslint, 删除多余的空格

5. vue-cli项目:eslint安装、配置

$ npm install --save eslint eslint-plugin-vue eslint-plugin-html eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-standard

安装完成后,在vue-cli项目根目录,创建.eslintrc.js文件

备注:(注意:项目下eslint规则会覆盖HBuilderX编辑器eslint插件中的规则

eslint-plugin-vue配置文件与规则:eslint-plugin-vue官方教程

.eslintrc.js配置文件示例

module.exports = {  
    extends: [  
        'plugin:vue/recommended'  
    ],  
    rules: {  
        "no-alert": 0,  
        "no-multi-spaces": "error", // 禁止多个空格   
        "semi": [2, "always"] ,// 自动补充分号  
       "quotes": ["error", "single"] // 使用单引号  
    }  
}

示例:使用eslint, 自动补充分号

6. 以uni-app项目为例,配置eslint规则,校验vue文件

特别说明:

  • vue文件,校验规则,需要从eslint-vue插件中配置。
  • 菜单【工具】【插件配置】【eslint-vue】【.eslintrc.js】,编辑.eslintrc.js文件

7. vue-cli 项目demo

附件中的zip包,为vue-cli项目demo。因为node_modules太大,所以未包含node_modules。解压zip后,请执行npm install安装node_modules

收起阅读 »

Android原生蓝牙插件(module)相关项目

uniapp原生插件 离线打包 蓝牙

只提供插件,联系:1701119520

只提供插件,联系:1701119520

iOS uni小程序SDK API 参考手册

uni小程序sdk

DCUniMPSDKEngine 类

初始化 SDK 全局环境

/// @param options 初始化参数  
+ (void)initSDKEnvironmentWihtLaunchOptions:(NSDictionary *)options;

初始化 sdk engine,并设置启动参数,建议在 application:didFinishLaunchingWithOptions 方法中添加

示例

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    // Override point for customization after application launch.    

    // 配置参数    
    NSMutableDictionary *options = [NSMutableDictionary dictionaryWithDictionary:launchOptions];    
    // 设置 debug YES 会在控制台输出 js log,默认不输出 log,注:需要引入 liblibLog.a 库    
    [options setObject:[NSNumber numberWithBool:YES] forKey:@"debug"];    
    // 初始化引擎    
    [DCUniMPSDKEngine initSDKEnvironmentWihtLaunchOptions:options];    

    return YES;    
}

App系统生命周期事件方法

App 系统生命周期方法中调用 SDK 相关方法

示例

- (void)applicationDidBecomeActive:(UIApplication *)application {    
    [DCUniMPSDKEngine applicationDidBecomeActive:application];    
}    

- (void)applicationWillResignActive:(UIApplication *)application {    
    [DCUniMPSDKEngine applicationWillResignActive:application];    
}    

- (void)applicationDidEnterBackground:(UIApplication *)application {    
    [DCUniMPSDKEngine applicationDidEnterBackground:application];    
}    

- (void)applicationWillEnterForeground:(UIApplication *)application {    
    [DCUniMPSDKEngine applicationWillEnterForeground:application];    
}    

- (void)applicationWillTerminate:(UIApplication *)application {    
    [DCUniMPSDKEngine destory];    
}

App系统事件回调方法

可根据项目需求,选择实现以下方法

示例

#pragma mark - 如果需要使用 URL Scheme 或 通用链接相关功能,请实现以下方法    
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {    
    // 通过 url scheme 唤起 App    
    [DCUniMPSDKEngine application:app openURL:url options:options];    
    return YES;    
}    

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {    
    // 通过通用链接唤起 App    
    [DCUniMPSDKEngine application:application continueUserActivity:userActivity];    
    return YES;    
}    

#pragma mark - 如需使用远程推送相关功能,请实现以下方法    
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {    
    // 远程通知注册成功,收到 deviceToken 调用sdk方法,传入 deviceToken    
    [DCUniMPSDKEngine application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];    
}    

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {    
    // 远程通知注册失败    
    [DCUniMPSDKEngine application:application didFailToRegisterForRemoteNotificationsWithError:error];    
}    

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {    
    // 收到远程推送消息    
    [DCUniMPSDKEngine application:application didReceiveRemoteNotification:userInfo];    
    completionHandler(UIBackgroundFetchResultNewData);    
}    

#pragma mark - 如需使用本地推送通知功能,请实现以下方法    
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {    
    // 收到本地推送消息    
    [DCUniMPSDKEngine application:application didReceiveLocalNotification:notification];    
}

判断应用资源是否已经部署

+ (BOOL)isExistsApp:(NSString *)appid;

将wgt应用资源包部署到运行路径中

/// @param appid appid  
/// @param wgtPath wgt应用资源包路径  
+ (BOOL)releaseAppResourceToRunPathWithAppid:(NSString *)appid  
                            resourceFilePath:(NSString *)wgtPath;

示例

if (![DCUniMPSDKEngine isExistsApp:k_AppId]) {  
        // 读取导入到工程中的wgt应用资源  
        NSString *appResourcePath = [[NSBundle mainBundle] pathForResource:k_AppId ofType:@"wgt"];  
        if (!appResourcePath) {  
            NSLog(@"资源路径不正确,请检查");  
            return;  
        }  
        // 将应用资源部署到运行路径中  
        if ([DCUniMPSDKEngine releaseAppResourceToRunPathWithAppid:k_AppId resourceFilePath:appResourcePath]) {  
            NSLog(@"应用资源文件部署成功");  
        }  
}

打开小程序应用

/// @param appid appid  
/// @param arguments 启动参数(可以在小程序中通过 plus.runtime.arguments 获取此参数)  
/// @param redirectPath 启动后直接打开的页面路径 例:"pages/component/view/view?a=1&b=2"  
+ (void)openApp:(NSString *)appid  
      arguments:(NSDictionary * _Nullable)arguments  
   redirectPath:(NSString * _Nullable)redirectPath;  

获取应用资源运行路径

+ (NSString *)getAppRunPathWithAppid:(NSString *)appid;

<a id="getUniMPVersionInfo"></a>

获取已经部署的小程序应用资源版本信息

+ (NSDictionary *)getUniMPVersionInfoWithAppid:(NSString *)appid;  

注:返回数据如下对应小程序应用中 manifest.json 配置的信息  
{  
     "name": "1.0.0",     // 应用版本名称  
     "code": 100          // 应用版本号  
}

关闭当前小程序应用

+ (void)closeUniMP;

获取当前运行的小程序appid

+ (NSString *)getActiveUniMPAppid;

<a id="getCurrentPageUrl"></a>

获取当前显示小程序页面的直达链接url

用于打开小程序直达二级页面

+ (NSString *)getCurrentPageUrl;
继续阅读 »

DCUniMPSDKEngine 类

初始化 SDK 全局环境

/// @param options 初始化参数  
+ (void)initSDKEnvironmentWihtLaunchOptions:(NSDictionary *)options;

初始化 sdk engine,并设置启动参数,建议在 application:didFinishLaunchingWithOptions 方法中添加

示例

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    // Override point for customization after application launch.    

    // 配置参数    
    NSMutableDictionary *options = [NSMutableDictionary dictionaryWithDictionary:launchOptions];    
    // 设置 debug YES 会在控制台输出 js log,默认不输出 log,注:需要引入 liblibLog.a 库    
    [options setObject:[NSNumber numberWithBool:YES] forKey:@"debug"];    
    // 初始化引擎    
    [DCUniMPSDKEngine initSDKEnvironmentWihtLaunchOptions:options];    

    return YES;    
}

App系统生命周期事件方法

App 系统生命周期方法中调用 SDK 相关方法

示例

- (void)applicationDidBecomeActive:(UIApplication *)application {    
    [DCUniMPSDKEngine applicationDidBecomeActive:application];    
}    

- (void)applicationWillResignActive:(UIApplication *)application {    
    [DCUniMPSDKEngine applicationWillResignActive:application];    
}    

- (void)applicationDidEnterBackground:(UIApplication *)application {    
    [DCUniMPSDKEngine applicationDidEnterBackground:application];    
}    

- (void)applicationWillEnterForeground:(UIApplication *)application {    
    [DCUniMPSDKEngine applicationWillEnterForeground:application];    
}    

- (void)applicationWillTerminate:(UIApplication *)application {    
    [DCUniMPSDKEngine destory];    
}

App系统事件回调方法

可根据项目需求,选择实现以下方法

示例

#pragma mark - 如果需要使用 URL Scheme 或 通用链接相关功能,请实现以下方法    
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {    
    // 通过 url scheme 唤起 App    
    [DCUniMPSDKEngine application:app openURL:url options:options];    
    return YES;    
}    

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {    
    // 通过通用链接唤起 App    
    [DCUniMPSDKEngine application:application continueUserActivity:userActivity];    
    return YES;    
}    

#pragma mark - 如需使用远程推送相关功能,请实现以下方法    
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {    
    // 远程通知注册成功,收到 deviceToken 调用sdk方法,传入 deviceToken    
    [DCUniMPSDKEngine application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];    
}    

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {    
    // 远程通知注册失败    
    [DCUniMPSDKEngine application:application didFailToRegisterForRemoteNotificationsWithError:error];    
}    

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {    
    // 收到远程推送消息    
    [DCUniMPSDKEngine application:application didReceiveRemoteNotification:userInfo];    
    completionHandler(UIBackgroundFetchResultNewData);    
}    

#pragma mark - 如需使用本地推送通知功能,请实现以下方法    
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {    
    // 收到本地推送消息    
    [DCUniMPSDKEngine application:application didReceiveLocalNotification:notification];    
}

判断应用资源是否已经部署

+ (BOOL)isExistsApp:(NSString *)appid;

将wgt应用资源包部署到运行路径中

/// @param appid appid  
/// @param wgtPath wgt应用资源包路径  
+ (BOOL)releaseAppResourceToRunPathWithAppid:(NSString *)appid  
                            resourceFilePath:(NSString *)wgtPath;

示例

if (![DCUniMPSDKEngine isExistsApp:k_AppId]) {  
        // 读取导入到工程中的wgt应用资源  
        NSString *appResourcePath = [[NSBundle mainBundle] pathForResource:k_AppId ofType:@"wgt"];  
        if (!appResourcePath) {  
            NSLog(@"资源路径不正确,请检查");  
            return;  
        }  
        // 将应用资源部署到运行路径中  
        if ([DCUniMPSDKEngine releaseAppResourceToRunPathWithAppid:k_AppId resourceFilePath:appResourcePath]) {  
            NSLog(@"应用资源文件部署成功");  
        }  
}

打开小程序应用

/// @param appid appid  
/// @param arguments 启动参数(可以在小程序中通过 plus.runtime.arguments 获取此参数)  
/// @param redirectPath 启动后直接打开的页面路径 例:"pages/component/view/view?a=1&b=2"  
+ (void)openApp:(NSString *)appid  
      arguments:(NSDictionary * _Nullable)arguments  
   redirectPath:(NSString * _Nullable)redirectPath;  

获取应用资源运行路径

+ (NSString *)getAppRunPathWithAppid:(NSString *)appid;

<a id="getUniMPVersionInfo"></a>

获取已经部署的小程序应用资源版本信息

+ (NSDictionary *)getUniMPVersionInfoWithAppid:(NSString *)appid;  

注:返回数据如下对应小程序应用中 manifest.json 配置的信息  
{  
     "name": "1.0.0",     // 应用版本名称  
     "code": 100          // 应用版本号  
}

关闭当前小程序应用

+ (void)closeUniMP;

获取当前运行的小程序appid

+ (NSString *)getActiveUniMPAppid;

<a id="getCurrentPageUrl"></a>

获取当前显示小程序页面的直达链接url

用于打开小程序直达二级页面

+ (NSString *)getCurrentPageUrl;
收起阅读 »

2020年11月~2021年7月份毕业学生看过来~~~阿里云春招!!!

投递邮件或添加好友时请注明来自DCloud

投递邮件或添加好友时请注明来自DCloud

文件下载保存, 遇到uni.downloadFile的坑

 uni.downloadFile({  
            //https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top-e3b63a0b1b.png  
             url: 'http://music.163.com/song/media/outer/url?id=65538.mp3',   
             success: (res) => {  
                     if (res.statusCode === 200) {  
                         console.log('下载成功');  
                     }  
                  console.log(res.tempFilePath);  
                  uni.saveFile({  
                       tempFilePath: res.tempFilePath,  
                       complete(res) {  
                         console.log(res)  
                       }  
                     });  
             }  
         });

按官网api通过uni.downloadFile,获得tempFilePath 临时文件路径,再调用uni.saveFiled保存文件。测试发现几个问题:

  1. 下载图片(小文件),下载成功后调saveFiled 是可以保存成功的。但是换成MP3文件(大文件),下载成功后,保存报错提示文件不存在;

    。这个问题不知是BUG,还是说这种方式就不支持大文件。

  2. uni.downloadFile 不支持后台下载,手机黑屏就暂停下载了。

现在解决方案 改用H5+api
不多BB直接看代码:
//查看已下载的文件

         function checkDownload(){  
            plus.io.requestFileSystem( plus.io.PUBLIC_DOWNLOADS, function(fs){  
                    var directoryReader = fs.root.createReader();  
                    directoryReader.readEntries( function( entries ){  
                        var i;  
                        for( i=0; i < entries.length; i++ ) {  
                                    console.log( entries[i].name );  
                                    entries[i].name = i  
                        }   
                    }, function ( e ) {  
                        console.log( "Read entries failed: " + e.message );  
                    });  
                });  
         }    

         // 创建下载任务  
         function createDownload() {  
            var dtask = plus.downloader.createDownload("https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top-e3b63a0b1b.png", {}, function(d, status){  
                // 下载完成 下载的文件会保存在 PUBLIC_DOWNLOADS 目录下,只要不主动删除都会存在  
                if(status == 200){   
                    console.log("Download success: ");  
                    console.log(d);  
                    checkDownload()  
                } else {  
                     console.log("Download failed: " + status);   
                }    
            });  
            ;  
            dtask.start();   
         }  
         createDownload()   


解决了问题1, 下载文件, 查看已下载的文件。
这个方式依然不能后台下载。
还有不知怎么修改下载的文件名

继续阅读 »
 uni.downloadFile({  
            //https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top-e3b63a0b1b.png  
             url: 'http://music.163.com/song/media/outer/url?id=65538.mp3',   
             success: (res) => {  
                     if (res.statusCode === 200) {  
                         console.log('下载成功');  
                     }  
                  console.log(res.tempFilePath);  
                  uni.saveFile({  
                       tempFilePath: res.tempFilePath,  
                       complete(res) {  
                         console.log(res)  
                       }  
                     });  
             }  
         });

按官网api通过uni.downloadFile,获得tempFilePath 临时文件路径,再调用uni.saveFiled保存文件。测试发现几个问题:

  1. 下载图片(小文件),下载成功后调saveFiled 是可以保存成功的。但是换成MP3文件(大文件),下载成功后,保存报错提示文件不存在;

    。这个问题不知是BUG,还是说这种方式就不支持大文件。

  2. uni.downloadFile 不支持后台下载,手机黑屏就暂停下载了。

现在解决方案 改用H5+api
不多BB直接看代码:
//查看已下载的文件

         function checkDownload(){  
            plus.io.requestFileSystem( plus.io.PUBLIC_DOWNLOADS, function(fs){  
                    var directoryReader = fs.root.createReader();  
                    directoryReader.readEntries( function( entries ){  
                        var i;  
                        for( i=0; i < entries.length; i++ ) {  
                                    console.log( entries[i].name );  
                                    entries[i].name = i  
                        }   
                    }, function ( e ) {  
                        console.log( "Read entries failed: " + e.message );  
                    });  
                });  
         }    

         // 创建下载任务  
         function createDownload() {  
            var dtask = plus.downloader.createDownload("https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top-e3b63a0b1b.png", {}, function(d, status){  
                // 下载完成 下载的文件会保存在 PUBLIC_DOWNLOADS 目录下,只要不主动删除都会存在  
                if(status == 200){   
                    console.log("Download success: ");  
                    console.log(d);  
                    checkDownload()  
                } else {  
                     console.log("Download failed: " + status);   
                }    
            });  
            ;  
            dtask.start();   
         }  
         createDownload()   


解决了问题1, 下载文件, 查看已下载的文件。
这个方式依然不能后台下载。
还有不知怎么修改下载的文件名

收起阅读 »

uni-app H5端 “网络不给力” 排查日记

网络不给力

前述

用户访问时莫名奇妙的出现“网络不给力”(连接服务器超时)的提示,可是此时用工具测试网络速度明明很给力。开发人员排查时却无法复现问题,于是开始认为是框架有问题。
作为框架的维护人员经过排查并未发现框架有相关问题,联系多位开发人员协助排查,终于总结出如下结论:

解决办法

太长不看版:使用 CDN、https 。

网络不给力

用户出现问题的时候,开发人员首先怀疑的就是这个内置的“网络不给力”错误页面,开始想办法去掉这个错误提示页面。
首先就要说一下为什么 SPA(单页应用) 都必须有这个页面,普通的 MPA(多页应用)其页面跳转(从一个html跳转到另外一个html)是浏览器负责的,页面加载失败的时候会显示浏览器的失败提示,而 SPA 是使用 ajax 异步加载页面,所以需要自己来判断页面是否加载成功,以及在加载失败的时候显示提示。如果去掉这个提示页面,仅仅是相当于掩耳盗铃,并不能解决问题。

加载超时(情况一)

之前框架默认的加载超时时间是3秒(后续才增大了默认超时时间),是相信运维人员都了解CDN的,一般的商业项目部署 H5 离不开 CDN ,一方面是为了用户体验,一方面是为了运营成本。
经过排查大部分页面加载慢导致超时的用户,都有一个特点,将资源直接部署在了自己服务器供用户访问。
服务端如果采用5兆带宽,同时10个用户访问的情况下,平均每个用户分得0.5兆,其下载速度约为0.06兆每秒,加载0.3兆的文件需要5秒,远超了默认的超时时间,而且这只是理论计算,实际带宽的分配并非均匀,有的用户分得的更小,加载的时间更长。另外服务器机房和网络线路固定,不同地区和网络运营商的用户访问体验不一致。

对此的解决办法有两种:

  1. 配置页面加载超时时间(新版的HBuilderX已经增大了默认超时时间):相关文档,优点:方便快捷,只需修改配置重新发布即可;缺点:并不能真正改善用户体验,使用服务器硬扛流量还可能会给服务器上的其他业务带来影响。
  2. 使用 CDN ,优点:相比增加服务器带宽成本更低,体验更好。

加载出错(情况二)

即使增加了页面的超时时间,仍然有部分用户访问页面时(使用http)出现错误提示,而且并未达到配置的超时时间(有的是切换页面瞬间出现),甚至刷新页面仍然无济于事。开发者调试的时候却始终无法复现。
以下是开发者让用户协助调试提供的截图(开发者未使用CDN为了避免各位访问测试造成压力,对域名进行了打码):

从图中可以看出加载此页面的js文件报错了,此时让用户直接访问这个报错的js文件地址,出现如下内容:

开发者一眼就看出js文件的内容不对,并不是页面真正的js文件,应该是遇到了网络劫持。网上搜索内容中出现的域名,发现中招的人不少:

一般办公使用的商用网络很少有劫持问题,而民用的网络层层转包不免有流氓运营商从中作梗,所以用户会出现问题,而开发者难以复现。

针对此问题,简易便捷解决办法就是升级为 https。

还是加载出错(情况三)

有开发者已经升级到了https,已经解决了网络劫持的问题,但是过了一段时间更新后,仍然有部分用户出现了“网络不给力”的问题。调试发现报错的js文件的文件名和线上的文件名不一致(主要是hash部分不同),是旧版本的文件名。说明html使用了旧版的缓存,请求的页面js文件是旧的,这个问题一般出现在微信内置浏览器中。

百度一下,发现类似的问题很多:百度:微信html缓存

搜到的处理方法基本是修改html的响应头,禁用html的缓存(不必禁用js、css等资源的缓存)。

实际这个问题有两种处理方式:

  1. 禁用html缓存,让用户访问到新版
  2. 每次更新时不删除旧的js、css资源,让使用旧版的用户也能继续访问

已使用CDN的用户一般未发现这个问题,因为CDN缓存了旧版的文件,即使服务器上已经删除了,CDN仍然能访问到。

结语

至此 “网络不给力” 问题排查告一段落,结论就是 CDN 和 https ,感谢一直配合调查测试的开发者,如果还有谁遇到此外的情况,请私信或者留言联系,官方会协助排查。

继续阅读 »

前述

用户访问时莫名奇妙的出现“网络不给力”(连接服务器超时)的提示,可是此时用工具测试网络速度明明很给力。开发人员排查时却无法复现问题,于是开始认为是框架有问题。
作为框架的维护人员经过排查并未发现框架有相关问题,联系多位开发人员协助排查,终于总结出如下结论:

解决办法

太长不看版:使用 CDN、https 。

网络不给力

用户出现问题的时候,开发人员首先怀疑的就是这个内置的“网络不给力”错误页面,开始想办法去掉这个错误提示页面。
首先就要说一下为什么 SPA(单页应用) 都必须有这个页面,普通的 MPA(多页应用)其页面跳转(从一个html跳转到另外一个html)是浏览器负责的,页面加载失败的时候会显示浏览器的失败提示,而 SPA 是使用 ajax 异步加载页面,所以需要自己来判断页面是否加载成功,以及在加载失败的时候显示提示。如果去掉这个提示页面,仅仅是相当于掩耳盗铃,并不能解决问题。

加载超时(情况一)

之前框架默认的加载超时时间是3秒(后续才增大了默认超时时间),是相信运维人员都了解CDN的,一般的商业项目部署 H5 离不开 CDN ,一方面是为了用户体验,一方面是为了运营成本。
经过排查大部分页面加载慢导致超时的用户,都有一个特点,将资源直接部署在了自己服务器供用户访问。
服务端如果采用5兆带宽,同时10个用户访问的情况下,平均每个用户分得0.5兆,其下载速度约为0.06兆每秒,加载0.3兆的文件需要5秒,远超了默认的超时时间,而且这只是理论计算,实际带宽的分配并非均匀,有的用户分得的更小,加载的时间更长。另外服务器机房和网络线路固定,不同地区和网络运营商的用户访问体验不一致。

对此的解决办法有两种:

  1. 配置页面加载超时时间(新版的HBuilderX已经增大了默认超时时间):相关文档,优点:方便快捷,只需修改配置重新发布即可;缺点:并不能真正改善用户体验,使用服务器硬扛流量还可能会给服务器上的其他业务带来影响。
  2. 使用 CDN ,优点:相比增加服务器带宽成本更低,体验更好。

加载出错(情况二)

即使增加了页面的超时时间,仍然有部分用户访问页面时(使用http)出现错误提示,而且并未达到配置的超时时间(有的是切换页面瞬间出现),甚至刷新页面仍然无济于事。开发者调试的时候却始终无法复现。
以下是开发者让用户协助调试提供的截图(开发者未使用CDN为了避免各位访问测试造成压力,对域名进行了打码):

从图中可以看出加载此页面的js文件报错了,此时让用户直接访问这个报错的js文件地址,出现如下内容:

开发者一眼就看出js文件的内容不对,并不是页面真正的js文件,应该是遇到了网络劫持。网上搜索内容中出现的域名,发现中招的人不少:

一般办公使用的商用网络很少有劫持问题,而民用的网络层层转包不免有流氓运营商从中作梗,所以用户会出现问题,而开发者难以复现。

针对此问题,简易便捷解决办法就是升级为 https。

还是加载出错(情况三)

有开发者已经升级到了https,已经解决了网络劫持的问题,但是过了一段时间更新后,仍然有部分用户出现了“网络不给力”的问题。调试发现报错的js文件的文件名和线上的文件名不一致(主要是hash部分不同),是旧版本的文件名。说明html使用了旧版的缓存,请求的页面js文件是旧的,这个问题一般出现在微信内置浏览器中。

百度一下,发现类似的问题很多:百度:微信html缓存

搜到的处理方法基本是修改html的响应头,禁用html的缓存(不必禁用js、css等资源的缓存)。

实际这个问题有两种处理方式:

  1. 禁用html缓存,让用户访问到新版
  2. 每次更新时不删除旧的js、css资源,让使用旧版的用户也能继续访问

已使用CDN的用户一般未发现这个问题,因为CDN缓存了旧版的文件,即使服务器上已经删除了,CDN仍然能访问到。

结语

至此 “网络不给力” 问题排查告一段落,结论就是 CDN 和 https ,感谢一直配合调查测试的开发者,如果还有谁遇到此外的情况,请私信或者留言联系,官方会协助排查。

收起阅读 »

发现一个subNVue的隐藏功能,官方居然没文档介绍

subNVues

发现一个subNVue的隐藏功能,官方居然没文档介绍,那就是subNVue.close() ,不知道参数都哪些,今天实验可用。希望尽快给我们文档介绍。

发现一个subNVue的隐藏功能,官方居然没文档介绍,那就是subNVue.close() ,不知道参数都哪些,今天实验可用。希望尽快给我们文档介绍。

解决uni-app编译后vendor.js文件过大

uni_app uniapp

背景与现象

  • 将一个当前只有简单功能的H5项目(通过vue-cli 3 创建) 迁移为uni-app版本,需要支持输出为QQ小程序、H5,在QQ小程序开发者工具中,发现无法生成预览和真机调试,原因是代码包超过2M,经过分析,发现编译后代码中,最大的是:common/vendor.js,一些处理后仍有2.5M。打包生产版本分析,也是同样的问题。
  • 项目通过vue-cli命令行创建,因此以下涉及示例的,都以此为准,使用HBuilderX开发的,麻烦自行转换操作。

解决方法

  • 开启运行时压缩

这个方法测试了,没看出有什么帮助。

  • 分包优化

这个方法更多地是对于页面过多或static图片资源过多的情况有用。此项目也进行了分包,但这个并未解决打包后vendor过大的问题。

以上2个方法,为uni官方建议的处理vendor过大的方法,见文档-介绍-uni-app 跨端开发注意事项-vendor过大的处理方式

  • Bug:分包资源被打包到主包而导致的vendor过大

这个问题没有遇到,看起来是曾经版本出现过,但新版本已修复,若是这个问题导致的,则可参考:issue #649question #72577

  • 其他的一些处理方式

看到的一篇文章,虽然我的项目中不是这些原因,但这些方法是需要考虑的:小程序包大小优化(uni-app)

  • 开启生产环境gzip,vendor.js从2.5M减少到440k

如何开启,使用compression-webpack-plugin

vue.config.js:

const CompressionWebpackPlugin = require('compression-webpack-plugin')  
const productionGzipExtensions = ['js', 'css']  

configureWebpack: {  
    plugins: [  
          new CompressionWebpackPlugin({  
            filename: '[path].gz[query]',  
            algorithm: 'gzip',  
            test: new RegExp('\\.('   productionGzipExtensions.join('|')   ')$'),//匹配文件名  
            threshold: 10240,//对10K以上的数据进行压缩  
            minRatio: 0.8,  
            deleteOriginalAssets:false,//是否删除源文件  
          })  
        ]}  
}

文件分析

使用 webpackBundleAnalyzer,可以帮助分析文件大小。

vue.config.js:

pluginOptions: {  
    webpackBundleAnalyzer: {  
      openAnalyzer: process.env.NODE_ENV === 'production'  
    }  
  },

编译后,会同时带一份报告,可查看 stat, parsed, gzip 三种状态的文件大小。

继续阅读 »

背景与现象

  • 将一个当前只有简单功能的H5项目(通过vue-cli 3 创建) 迁移为uni-app版本,需要支持输出为QQ小程序、H5,在QQ小程序开发者工具中,发现无法生成预览和真机调试,原因是代码包超过2M,经过分析,发现编译后代码中,最大的是:common/vendor.js,一些处理后仍有2.5M。打包生产版本分析,也是同样的问题。
  • 项目通过vue-cli命令行创建,因此以下涉及示例的,都以此为准,使用HBuilderX开发的,麻烦自行转换操作。

解决方法

  • 开启运行时压缩

这个方法测试了,没看出有什么帮助。

  • 分包优化

这个方法更多地是对于页面过多或static图片资源过多的情况有用。此项目也进行了分包,但这个并未解决打包后vendor过大的问题。

以上2个方法,为uni官方建议的处理vendor过大的方法,见文档-介绍-uni-app 跨端开发注意事项-vendor过大的处理方式

  • Bug:分包资源被打包到主包而导致的vendor过大

这个问题没有遇到,看起来是曾经版本出现过,但新版本已修复,若是这个问题导致的,则可参考:issue #649question #72577

  • 其他的一些处理方式

看到的一篇文章,虽然我的项目中不是这些原因,但这些方法是需要考虑的:小程序包大小优化(uni-app)

  • 开启生产环境gzip,vendor.js从2.5M减少到440k

如何开启,使用compression-webpack-plugin

vue.config.js:

const CompressionWebpackPlugin = require('compression-webpack-plugin')  
const productionGzipExtensions = ['js', 'css']  

configureWebpack: {  
    plugins: [  
          new CompressionWebpackPlugin({  
            filename: '[path].gz[query]',  
            algorithm: 'gzip',  
            test: new RegExp('\\.('   productionGzipExtensions.join('|')   ')$'),//匹配文件名  
            threshold: 10240,//对10K以上的数据进行压缩  
            minRatio: 0.8,  
            deleteOriginalAssets:false,//是否删除源文件  
          })  
        ]}  
}

文件分析

使用 webpackBundleAnalyzer,可以帮助分析文件大小。

vue.config.js:

pluginOptions: {  
    webpackBundleAnalyzer: {  
      openAnalyzer: process.env.NODE_ENV === 'production'  
    }  
  },

编译后,会同时带一份报告,可查看 stat, parsed, gzip 三种状态的文件大小。

收起阅读 »

IOS离线打包微信分享发生多次二次跳转行为

微信分享

如果确认配置都正确,还是发生多次二次跳转,请到微信下载最新的sdk,libWeChatSDK.a这个文件替换原来的,就可以了.

如果确认配置都正确,还是发生多次二次跳转,请到微信下载最新的sdk,libWeChatSDK.a这个文件替换原来的,就可以了.

分享案例,欢迎讨论

下载地址:
安卓(IOS地址) https://www.dfs168.com/market/viewapp.html?id=503
苹果: https://apps.apple.com/cn/app/id1489907205
H5地址:
http://wechat.dfs168.com/
微信小程序
(微信搜索:大丰收农资优选)

继续阅读 »

下载地址:
安卓(IOS地址) https://www.dfs168.com/market/viewapp.html?id=503
苹果: https://apps.apple.com/cn/app/id1489907205
H5地址:
http://wechat.dfs168.com/
微信小程序
(微信搜索:大丰收农资优选)

收起阅读 »