HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

最新ios提审通过经验分享

苹果 审核 iOS
  1. ios打包上架
    https://zhuanlan.zhihu.com/p/66575901
  2. 审核流程
    https://blog.csdn.net/pcf1995/article/details/79650345
    应用版本名称和应用版本号对应起来,比如1.0.1对应101
  3. 审核被拒重新提审流程
    https://www.cnblogs.com/appuploader/p/7993011.html

踩坑记录:

  1. 半个月前申请的苹果开发者发布证书,在uniapp云打包的时候报错
    解决:重新生成一个发布证书
  2. ipa包通过application loader上传报错,找不到bound Id
    解决:需要先到苹果开发者-app store管理-我的app里面创建一个该bound id的应用
  3. Application loader上传时报错图片有问题
    解决:提供的app store图标需要是png图片,且必须直角,不透明(即没有alpha,可以使用mac预览里面的导出功能,在导出的时候去掉alpha的勾即可)
  4. 拒审原因:5.1.1,使用手机设备应用时未表明用途
    解决:在manifest里面配置说明文案
继续阅读 »
  1. ios打包上架
    https://zhuanlan.zhihu.com/p/66575901
  2. 审核流程
    https://blog.csdn.net/pcf1995/article/details/79650345
    应用版本名称和应用版本号对应起来,比如1.0.1对应101
  3. 审核被拒重新提审流程
    https://www.cnblogs.com/appuploader/p/7993011.html

踩坑记录:

  1. 半个月前申请的苹果开发者发布证书,在uniapp云打包的时候报错
    解决:重新生成一个发布证书
  2. ipa包通过application loader上传报错,找不到bound Id
    解决:需要先到苹果开发者-app store管理-我的app里面创建一个该bound id的应用
  3. Application loader上传时报错图片有问题
    解决:提供的app store图标需要是png图片,且必须直角,不透明(即没有alpha,可以使用mac预览里面的导出功能,在导出的时候去掉alpha的勾即可)
  4. 拒审原因:5.1.1,使用手机设备应用时未表明用途
    解决:在manifest里面配置说明文案
收起阅读 »

XHbuilder 还不错哈

HBuilderX

本人轻度应用,使用three.js,有语法提示,挺快的。向我一样的可以用用这个

本人轻度应用,使用three.js,有语法提示,挺快的。向我一样的可以用用这个

uniapp 自定义 iOS 端推送提示音

Push 推送提示音 推送

iOS端自定义推送铃声,详情请看 自定义推送铃声

iOS端自定义推送铃声,详情请看 自定义推送铃声

uni-app 2.2 大幅优化H5端性能体验,只开发H5,也要用uni-app

性能 摇树优化 tree_shaking 优化

背景

uni-app发布以来,已经服务了几十万开发者。让我们意外,或者说惊喜的是,有大量开发者用uni-app只编写H5版,并没有多端发布(可参考案例)。

这其实也符合uni-app的初衷,uni-app的定位并不是需要多端发布时才用uni-appuni-app是一个使用vue.js开发所有前端应用的统一框架。对于一个前端工程师来说,uni-app在手,啥需求都不愁。

过去的版本迭代中,uni-app已经成为了更好的小程序开发框架,比使用原生微信开发更有优势。(见评测

uni-app2.2的新版中,我们大幅优化了H5版的性能,让使用uni-app开发的H5,性能体验和直接使用vue.js开发H5拉齐。

可能不少开发者有某种误解:多端框架要适配多端,所以性能肯定不如原生。我们想纠正一下:

  1. 切忌想当然,多看数据评测。还不信就自己动手实验
  2. 请问使用vue.js开发的web性能好,还是使用原生js开发web性能好?答案是:使用vue.js框架。为什么?因为它在底层会自动优化数据同步、虚拟dom,比大多数开发手动写的代码要更高效。同样的,使用uni-app也如此,框架底层的优化处理比大多数开发者手动写setdata或dom操作更高效。
  3. 多端适配很多是在编译时做的,并不影响运行时的性能

优化难点

想优化H5端的性能,并不是一件容易的事。

“功能全面”和“小巧极速”,这是一对最难调和的冤家。

为了保障多端的一致性,uni-app实现了一套小程序的H5版Runtime,支持各种小程序的组件、API、配置。所以uni-app的H5版拥有比其他框架更好的跨端一致性。

但这也造成了老版的uni-app,输出H5端时,包体积过大(框架未压缩前有500k,部署gzip后162k)。

这确实是一个非常大的runtime,包含了几十个内置组件,数百个API。而且这些API仍然在快速增加中。

不能像其他框架一样因为功能少,所以体积小。我们不会用功能换性能,我们需要更好的方案。

优化方法

uni-app包含几十个内置组件、数百个API,是个“大而全”的框架;但开发者在开发具体应用时,未必能使用到所有的组件及API。若能根据项目具体情况,删掉没用到的组件及API,保留对项目有用的组件及API,便可精简框架、减少体积,这即是“摇树优化”的思路。

摇树优化(Tree-Shaking),顾名思义,摇晃树干,将枯死无用的枝条摇掉,仅保留有用的树枝。对应到框架层面理解,就是一个框架的众多组件和API,可以按需使用,把未引用的框架部分裁剪掉。Tree-Shaking 最早由 Rollup 提出,属于死码删除的一种形式。

常见的前端框架摇树,一般是基于明确的import引用关系。比如引用某UI库时,在A页面使用该UI库的search组件,此时需要写js代码import这个search组件,那么摇树分析就很容易。

uni-app和小程序一样,内置组件和API是不需要import的,这提升了开发的易用性,但此时却加大了摇树的难度,依靠简单的import分析无法实现摇树了。

幸好对DCloud团队而言,AST语法分析是看家本事,多年来HBuilder以js和vue语法提示著称。通过AST分析,uni-app新版可以精准判定这个项目使用了哪些组件和API。

不过这还不够,分析工程源码使用了什么组件和API之后,还得考虑框架各组件和API之间可能存在依赖和耦合关系,这需要进一步的计算和关系梳理,具体而言:

  • 组件:通过vue-template-compiler分析出来的AST,映射生成项目中使用到的组件清单,然后再基于Webpack插件将使用到的组件打包构建
  • API:编译器维护一个 api 依赖关系的 json 文件,该 json 文件描述每个 api 可能依赖的文件,然后 babel 查找到对应的 api 后,根据api 的依赖关系自动导入,重新编译

在工程师持续的加班奋战后,uni-app终于推出了全新的2.2版本,解决了这些难题,大幅降低了发行包体积,gzip后的框架体积,从162k降低到92k,仅相当于你在工程中引用了vue.jsvue-router、以及部分es6 polyfill库。(后续有详细比较)

除了大幅降低发行包体积,新版还调整了预载策略,可以进一步加快页面的渲染速度。

优化结果

搭建环境

我们使用vue-cli创建uni-app默认模板

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

项目创建后,编译生成H5端的发行目录

npm run build:h5

或者在HBuilderX的可视化界面新建uni-app项目,选默认模板,然后点菜单发行到h5。

然后配置nginx服务器,指定root目录并启用gzip压缩,示例如下:

server {  
    ...  
    gzip on;  
    gzip_min_length 1k;  
    gzip_buffers 4 16k;  
    gzip_comp_level 4;  
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;  
    ...  
}  

runtime 动态裁剪

然后通过 Chrome DevTools 的 Network 面板,查看优化前的首页网络请求包大小,结果如下:

然后启用H5平台的优化开关,重新查看首页的网络请求包大小,结果如下:

可以看到框架主库(chunk-vendors.js)从162k变为92.8k,体积压缩43%!

实际上,框架主库主要分为三个部分:

  • vue/vue-router基础库
  • es6 polyfill库
  • uni-app runtime(组件&API实现)

如果对这三个部分再拆开对比,我们会看到uni-app组件库优化比例更高:

vue/vue-router es6 polyfill库 uni-app runtime 累计
优化前 38k 43k 81k 162k
优化后 38k 26k 28.8k 92.8k

Tips:

  • uni-app runtime从81k瘦身为28.8k,裁剪比例达到64%
  • 新编译器对es6的使用也做了动态扫描,项目中用到的es6语法(包括uni-app runtime用到的es6语法),才会打包对应的polyfill实现,故es6 polyfill库从43k瘦身为26k

脚本执行时间

然后,我们再通过Chrome DevTools 的 Performance 面板,查看优化前后的性能数据,对比结果如下:

可以看出,最耗时的脚本执行时间,从227ms提升为154ms,时间提升达到32%。

如何使用

虽然内部实现比较复杂,但uni-app对外暴漏了简单的配置,开发者只需在配置文件中打开一个开关即可。具体在 manifest.json 中h5节点配置如下选项:

"h5" : {  
    "optimization":{  
        "treeShaking":{  
            "enable":true //启用摇树优化  
        }  
    }  
}

2.2版的其他优化

uni-app2.2版中,还开放了package.jsonvue-config.js的自定义,开发者可以自由的配置编译策略。

现在可以自定义支持所有小程序平台,包括钉钉小程序、高德小程序、抖音小程序...等。这样除了标准的8大平台(iOS、Android、H5、微信小程序、支付宝小程序、百度小程序、头条小程序、QQ小程序),这些生态的子生态也可以分版本条件编译。

同样,也支持对H5端进行多子端编译,比如微信里的内嵌的H5、App里内嵌的H5...都可以分开条件编译。

如此灵活的条件编译,对于一套工程的多端发布、共享复用、同步升级,有莫大的好处。即便是仅开发H5版,uni-app的多端条件编译也提供了更灵活和强大的工程化能力。

2.2版本还可以设置各种静态资源、js、小程序自定义组件的编译和拷贝策略。如果你之前的h5项目或小程序项目想转换至uni-app下,又不想挪动某些目录结构,那么在vue-config.js里配置策略即可。

使用uni-app开发H5和直接开发H5相比的优势

在与直接开发h5拉齐性能的基础之上,uni-app给开发者提供了更多优势:

  1. 开发效率
    uni-app提供了大量适合手机页面的基础组件(其实就是小程序组件)。还提供了扩展组件uni ui。插件市场更有600多款插件。
    无论开发者想找一个电商的模板,还是找一个图表组件,都可以手到擒来。开发效率更胜以往。
  2. 多端编译
    我们开发H5时,经常需要给浏览器输出一份、给微信等超级App输出一份、给自家的App输出一份。甚至不同地域、不同用户画像,都会输出不同版本。以前,开发者只能对js部分进行条件编译,甚至不得不建多个仓库进行多版维护。

uni-app解决了这些烦恼,它的条件编译非常灵活强大:

  • 不管是组件、js还是css,都可以按平台编译输出
  • 还可以多个平台进行“与和或”的运算编译
  • 除了文件中的代码,整个文件、甚至整个目录,都可以条件编译

例如微信、QQ等在支持x5内核的内置浏览器中,使用x5的视频同层渲染;或者在微信服务号中调用微信卡劵,这段代码只有build到 dist/h5-weixin 这个目录下的版本才会被编译进去,其他平台不会有这段代码

// #ifdef H5-WEIXIN  
wx.openCard({  
    cardList: [{  
        cardId: '',  
        code: ''  
    }]// 需要打开的卡券列表  
});  
// #endif  

相关代码全部托管在 github,欢迎大家 star 或提交 pr!

继续阅读 »

背景

uni-app发布以来,已经服务了几十万开发者。让我们意外,或者说惊喜的是,有大量开发者用uni-app只编写H5版,并没有多端发布(可参考案例)。

这其实也符合uni-app的初衷,uni-app的定位并不是需要多端发布时才用uni-appuni-app是一个使用vue.js开发所有前端应用的统一框架。对于一个前端工程师来说,uni-app在手,啥需求都不愁。

过去的版本迭代中,uni-app已经成为了更好的小程序开发框架,比使用原生微信开发更有优势。(见评测

uni-app2.2的新版中,我们大幅优化了H5版的性能,让使用uni-app开发的H5,性能体验和直接使用vue.js开发H5拉齐。

可能不少开发者有某种误解:多端框架要适配多端,所以性能肯定不如原生。我们想纠正一下:

  1. 切忌想当然,多看数据评测。还不信就自己动手实验
  2. 请问使用vue.js开发的web性能好,还是使用原生js开发web性能好?答案是:使用vue.js框架。为什么?因为它在底层会自动优化数据同步、虚拟dom,比大多数开发手动写的代码要更高效。同样的,使用uni-app也如此,框架底层的优化处理比大多数开发者手动写setdata或dom操作更高效。
  3. 多端适配很多是在编译时做的,并不影响运行时的性能

优化难点

想优化H5端的性能,并不是一件容易的事。

“功能全面”和“小巧极速”,这是一对最难调和的冤家。

为了保障多端的一致性,uni-app实现了一套小程序的H5版Runtime,支持各种小程序的组件、API、配置。所以uni-app的H5版拥有比其他框架更好的跨端一致性。

但这也造成了老版的uni-app,输出H5端时,包体积过大(框架未压缩前有500k,部署gzip后162k)。

这确实是一个非常大的runtime,包含了几十个内置组件,数百个API。而且这些API仍然在快速增加中。

不能像其他框架一样因为功能少,所以体积小。我们不会用功能换性能,我们需要更好的方案。

优化方法

uni-app包含几十个内置组件、数百个API,是个“大而全”的框架;但开发者在开发具体应用时,未必能使用到所有的组件及API。若能根据项目具体情况,删掉没用到的组件及API,保留对项目有用的组件及API,便可精简框架、减少体积,这即是“摇树优化”的思路。

摇树优化(Tree-Shaking),顾名思义,摇晃树干,将枯死无用的枝条摇掉,仅保留有用的树枝。对应到框架层面理解,就是一个框架的众多组件和API,可以按需使用,把未引用的框架部分裁剪掉。Tree-Shaking 最早由 Rollup 提出,属于死码删除的一种形式。

常见的前端框架摇树,一般是基于明确的import引用关系。比如引用某UI库时,在A页面使用该UI库的search组件,此时需要写js代码import这个search组件,那么摇树分析就很容易。

uni-app和小程序一样,内置组件和API是不需要import的,这提升了开发的易用性,但此时却加大了摇树的难度,依靠简单的import分析无法实现摇树了。

幸好对DCloud团队而言,AST语法分析是看家本事,多年来HBuilder以js和vue语法提示著称。通过AST分析,uni-app新版可以精准判定这个项目使用了哪些组件和API。

不过这还不够,分析工程源码使用了什么组件和API之后,还得考虑框架各组件和API之间可能存在依赖和耦合关系,这需要进一步的计算和关系梳理,具体而言:

  • 组件:通过vue-template-compiler分析出来的AST,映射生成项目中使用到的组件清单,然后再基于Webpack插件将使用到的组件打包构建
  • API:编译器维护一个 api 依赖关系的 json 文件,该 json 文件描述每个 api 可能依赖的文件,然后 babel 查找到对应的 api 后,根据api 的依赖关系自动导入,重新编译

在工程师持续的加班奋战后,uni-app终于推出了全新的2.2版本,解决了这些难题,大幅降低了发行包体积,gzip后的框架体积,从162k降低到92k,仅相当于你在工程中引用了vue.jsvue-router、以及部分es6 polyfill库。(后续有详细比较)

除了大幅降低发行包体积,新版还调整了预载策略,可以进一步加快页面的渲染速度。

优化结果

搭建环境

我们使用vue-cli创建uni-app默认模板

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

项目创建后,编译生成H5端的发行目录

npm run build:h5

或者在HBuilderX的可视化界面新建uni-app项目,选默认模板,然后点菜单发行到h5。

然后配置nginx服务器,指定root目录并启用gzip压缩,示例如下:

server {  
    ...  
    gzip on;  
    gzip_min_length 1k;  
    gzip_buffers 4 16k;  
    gzip_comp_level 4;  
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;  
    ...  
}  

runtime 动态裁剪

然后通过 Chrome DevTools 的 Network 面板,查看优化前的首页网络请求包大小,结果如下:

然后启用H5平台的优化开关,重新查看首页的网络请求包大小,结果如下:

可以看到框架主库(chunk-vendors.js)从162k变为92.8k,体积压缩43%!

实际上,框架主库主要分为三个部分:

  • vue/vue-router基础库
  • es6 polyfill库
  • uni-app runtime(组件&API实现)

如果对这三个部分再拆开对比,我们会看到uni-app组件库优化比例更高:

vue/vue-router es6 polyfill库 uni-app runtime 累计
优化前 38k 43k 81k 162k
优化后 38k 26k 28.8k 92.8k

Tips:

  • uni-app runtime从81k瘦身为28.8k,裁剪比例达到64%
  • 新编译器对es6的使用也做了动态扫描,项目中用到的es6语法(包括uni-app runtime用到的es6语法),才会打包对应的polyfill实现,故es6 polyfill库从43k瘦身为26k

脚本执行时间

然后,我们再通过Chrome DevTools 的 Performance 面板,查看优化前后的性能数据,对比结果如下:

可以看出,最耗时的脚本执行时间,从227ms提升为154ms,时间提升达到32%。

如何使用

虽然内部实现比较复杂,但uni-app对外暴漏了简单的配置,开发者只需在配置文件中打开一个开关即可。具体在 manifest.json 中h5节点配置如下选项:

"h5" : {  
    "optimization":{  
        "treeShaking":{  
            "enable":true //启用摇树优化  
        }  
    }  
}

2.2版的其他优化

uni-app2.2版中,还开放了package.jsonvue-config.js的自定义,开发者可以自由的配置编译策略。

现在可以自定义支持所有小程序平台,包括钉钉小程序、高德小程序、抖音小程序...等。这样除了标准的8大平台(iOS、Android、H5、微信小程序、支付宝小程序、百度小程序、头条小程序、QQ小程序),这些生态的子生态也可以分版本条件编译。

同样,也支持对H5端进行多子端编译,比如微信里的内嵌的H5、App里内嵌的H5...都可以分开条件编译。

如此灵活的条件编译,对于一套工程的多端发布、共享复用、同步升级,有莫大的好处。即便是仅开发H5版,uni-app的多端条件编译也提供了更灵活和强大的工程化能力。

2.2版本还可以设置各种静态资源、js、小程序自定义组件的编译和拷贝策略。如果你之前的h5项目或小程序项目想转换至uni-app下,又不想挪动某些目录结构,那么在vue-config.js里配置策略即可。

使用uni-app开发H5和直接开发H5相比的优势

在与直接开发h5拉齐性能的基础之上,uni-app给开发者提供了更多优势:

  1. 开发效率
    uni-app提供了大量适合手机页面的基础组件(其实就是小程序组件)。还提供了扩展组件uni ui。插件市场更有600多款插件。
    无论开发者想找一个电商的模板,还是找一个图表组件,都可以手到擒来。开发效率更胜以往。
  2. 多端编译
    我们开发H5时,经常需要给浏览器输出一份、给微信等超级App输出一份、给自家的App输出一份。甚至不同地域、不同用户画像,都会输出不同版本。以前,开发者只能对js部分进行条件编译,甚至不得不建多个仓库进行多版维护。

uni-app解决了这些烦恼,它的条件编译非常灵活强大:

  • 不管是组件、js还是css,都可以按平台编译输出
  • 还可以多个平台进行“与和或”的运算编译
  • 除了文件中的代码,整个文件、甚至整个目录,都可以条件编译

例如微信、QQ等在支持x5内核的内置浏览器中,使用x5的视频同层渲染;或者在微信服务号中调用微信卡劵,这段代码只有build到 dist/h5-weixin 这个目录下的版本才会被编译进去,其他平台不会有这段代码

// #ifdef H5-WEIXIN  
wx.openCard({  
    cardList: [{  
        cardId: '',  
        code: ''  
    }]// 需要打开的卡券列表  
});  
// #endif  

相关代码全部托管在 github,欢迎大家 star 或提交 pr!

收起阅读 »

uniapp关于使用plus.device.getInfo获取imei的值的经验分享

IMEI

自从新版本的hbuilder x逐渐废弃plus.device.imei的时候,我这边也开始使用plus.device.getInfo,但是使用的过程中发现获取不到imei的值,后面才发现我使用的方法不对,不能像使用 plus.device.imei 的时候直接给变量赋值 然后下文在使用。

不明白的或者看不懂的,直接把我下面的案例代码,拿去执行一下 就就会明白了,imei是怎样获取的

下面直接上一个案例

//开始复制

plus.device.getInfo({
success:function(e){
//这里获取到imei 剩下的逻辑也写在这里面
var imei=e.imei;
//里面写接下来的逻辑
console.log('imei='+imei);//这里是能获取imei的
}
})

//不能在外面再来使用imei 一般是获取不到值的
console.log(imei);//这里的imei是空的 是获取不到的 因为和上面的方法是同时执行的 所以这个时候的imei并没有值

//结束

继续阅读 »

自从新版本的hbuilder x逐渐废弃plus.device.imei的时候,我这边也开始使用plus.device.getInfo,但是使用的过程中发现获取不到imei的值,后面才发现我使用的方法不对,不能像使用 plus.device.imei 的时候直接给变量赋值 然后下文在使用。

不明白的或者看不懂的,直接把我下面的案例代码,拿去执行一下 就就会明白了,imei是怎样获取的

下面直接上一个案例

//开始复制

plus.device.getInfo({
success:function(e){
//这里获取到imei 剩下的逻辑也写在这里面
var imei=e.imei;
//里面写接下来的逻辑
console.log('imei='+imei);//这里是能获取imei的
}
})

//不能在外面再来使用imei 一般是获取不到值的
console.log(imei);//这里的imei是空的 是获取不到的 因为和上面的方法是同时执行的 所以这个时候的imei并没有值

//结束

收起阅读 »

人人商城打包APP说明

插件支持功能
1、支付宝原生支付,微信原生支付
2、分享微信,微博,QQ
3、微信App验证功能,上架苹果市场时必须用到。
4、退出App
5、清理App缓存
6、状态栏颜色随网页内导航条变化

需要准备
1、人人商城网站系统
2、初雪云高级版本App制作网址:https://www.chuxueyun.com/deal/5/cateid-30.html

3、人人电商的插件下载:https://www.lanzous.com/i5ciy5e

4、需先申请微信开放平台权限,支付权限,登录权限,分享权限申请,申请地址:https://open.weixin.qq.com/
5、申请QQ互联权限,申请地址:https://connect.qq.com/index.html
6、申请支付宝支付权限,申请地址:https://b.alipay.com/index2.htm

注意
1:支付配置
安装后端插件:http://t.cn/AiYF6JQX

下载人人商城的插件,解压替换到对应的ewei_shopv2目录内。

注意

请先在人人商城后台配置好支付设置,如下图:

2:微信登录修改

ewei_shopv2\core\model\member.php 文件checkMemberSNS方法里,大概位置在886行

$token = trim($_GPC['token']);

改成

$token = trim($_GPC['access_token']);

$appid和$secret的数值改成自己的微信开放平台的appid和秘钥即可,大概位置在889行

ewei_shopv2\core\mobile\account\index.php文件中sns()方法里将, 大概位置在189行

if ($_W['ispost'] && !empty($sns) && !empty($_GPC['openid']))

改成

if (!empty($sns) && !empty($_GPC['openid'])) {

3.配置平台的UA
设置User Agant

打开App制作平台点击基础配置–>User Agant配置,UA类型选择:自定义 自定义UA填写CK 2.0一定要大写。(中间有个空格)

第三方配置:微信配置填写微信开放平台对应的值,一定要是开放平台,网址https://open.weixin.qq.com

第三方配置:QQ配置填写QQ开放平台对应的值,一定要是开放平台,网址http://open.qq.com QQ安卓登录与分享权限,要求上架应用宝后才可以使用

APP内对应的支付,第三方登录,分享功能全部打开。

高级配置:打开新窗口,请开启

如果被拒,请查看:链接(http://webapp.chuxueyun.com/1174652)

继续阅读 »

插件支持功能
1、支付宝原生支付,微信原生支付
2、分享微信,微博,QQ
3、微信App验证功能,上架苹果市场时必须用到。
4、退出App
5、清理App缓存
6、状态栏颜色随网页内导航条变化

需要准备
1、人人商城网站系统
2、初雪云高级版本App制作网址:https://www.chuxueyun.com/deal/5/cateid-30.html

3、人人电商的插件下载:https://www.lanzous.com/i5ciy5e

4、需先申请微信开放平台权限,支付权限,登录权限,分享权限申请,申请地址:https://open.weixin.qq.com/
5、申请QQ互联权限,申请地址:https://connect.qq.com/index.html
6、申请支付宝支付权限,申请地址:https://b.alipay.com/index2.htm

注意
1:支付配置
安装后端插件:http://t.cn/AiYF6JQX

下载人人商城的插件,解压替换到对应的ewei_shopv2目录内。

注意

请先在人人商城后台配置好支付设置,如下图:

2:微信登录修改

ewei_shopv2\core\model\member.php 文件checkMemberSNS方法里,大概位置在886行

$token = trim($_GPC['token']);

改成

$token = trim($_GPC['access_token']);

$appid和$secret的数值改成自己的微信开放平台的appid和秘钥即可,大概位置在889行

ewei_shopv2\core\mobile\account\index.php文件中sns()方法里将, 大概位置在189行

if ($_W['ispost'] && !empty($sns) && !empty($_GPC['openid']))

改成

if (!empty($sns) && !empty($_GPC['openid'])) {

3.配置平台的UA
设置User Agant

打开App制作平台点击基础配置–>User Agant配置,UA类型选择:自定义 自定义UA填写CK 2.0一定要大写。(中间有个空格)

第三方配置:微信配置填写微信开放平台对应的值,一定要是开放平台,网址https://open.weixin.qq.com

第三方配置:QQ配置填写QQ开放平台对应的值,一定要是开放平台,网址http://open.qq.com QQ安卓登录与分享权限,要求上架应用宝后才可以使用

APP内对应的支付,第三方登录,分享功能全部打开。

高级配置:打开新窗口,请开启

如果被拒,请查看:链接(http://webapp.chuxueyun.com/1174652)

收起阅读 »

vue 动态加载百度地图库(局部)

map.js文件

export default {  
    init: function (){  
            //console.log("初始化百度地图脚本...");  
            const AK = "AK";  
            const BMap_URL = "https://api.map.baidu.com/api?v=2.0&ak="+ AK +"&s=1&callback=onBMapCallback";  
            return new Promise((resolve, reject) => {  
                // 如果已加载直接返回  
                if(typeof BMap !== "undefined") {  
                     resolve(BMap);  
                     return true;  
             }  

             // 百度地图异步加载回调处理  
             window.onBMapCallback = function () {  
                    //   console.log("百度地图脚本初始化成功...");  
                    resolve(BMap);  
             };  

             // 插入script脚本  
             let scriptNode = document.createElement("script");  
             scriptNode.setAttribute("type", "text/javascript");  
             scriptNode.setAttribute("src", BMap_URL);  
             document.body.appendChild(scriptNode);  
      });  
    }  
}

vue文件

import BaiduMap from './map.js';  

BaiduMap.init().then((BMap) => {  
        this.loadScript('http://unpkg.com/inmap/dist/inmap.min.js',()=>{  
               this.init();  
        });  
});
继续阅读 »

map.js文件

export default {  
    init: function (){  
            //console.log("初始化百度地图脚本...");  
            const AK = "AK";  
            const BMap_URL = "https://api.map.baidu.com/api?v=2.0&ak="+ AK +"&s=1&callback=onBMapCallback";  
            return new Promise((resolve, reject) => {  
                // 如果已加载直接返回  
                if(typeof BMap !== "undefined") {  
                     resolve(BMap);  
                     return true;  
             }  

             // 百度地图异步加载回调处理  
             window.onBMapCallback = function () {  
                    //   console.log("百度地图脚本初始化成功...");  
                    resolve(BMap);  
             };  

             // 插入script脚本  
             let scriptNode = document.createElement("script");  
             scriptNode.setAttribute("type", "text/javascript");  
             scriptNode.setAttribute("src", BMap_URL);  
             document.body.appendChild(scriptNode);  
      });  
    }  
}

vue文件

import BaiduMap from './map.js';  

BaiduMap.init().then((BMap) => {  
        this.loadScript('http://unpkg.com/inmap/dist/inmap.min.js',()=>{  
               this.init();  
        });  
});
收起阅读 »

android ios 权限检查与动态申请提示

权限 Native.JS

ios 就这个个性,应用第一次用权限时,比如 相机 权限,检查的话是不存在的!就算打开 应用的权限页面 也没用,因为里面没有 相机 权限...,算了,不多说了,怀疑自己个儿抑郁了....直接发代码了,在逻辑上很可能不完善,还望懂行的道友...


    /**  
     * 获取系统权限  
     * @param {Object} permission       权限标识  
     *      CAMERA: (String 类型 )访问摄像头权限         用于调用摄像头(plus.camera.* plus.barcode.*)  
     *      CONTACTS: (String 类型 )访问系统联系人权限     用于访问(读、写)系统通讯录(plus.gallery.*)  
     *      GALLERY: (String 类型 )访问系统相册权限       用于访问(读、写)系统相册(plus.gallery.*)  
     *      LOCATION: (String 类型 )定位权限              用于获取当前用户位置信息(plus.geolocation.*)  
     *      NOTIFITION: (String 类型 )消息通知权限      用于接收系统消息通知(plus.push.*)  
     *      RECORD: (String 类型 )录音权限                用于进行本地录音操作(plus.audio.AudioRecorder)  
     *      SHORTCUT: (String 类型 )创建桌面快捷方式权限    用于在系统桌面创建快捷方式图标(plus.navigator.createShortcut)  
     *   
     * @param {Object} successCallBack  成功回调  
     * @param {Object} errorCallBack    失败回调  
     */  
function getPermission(permissionIdentity, successCallBack, errorCallBack){  
        //权限标识转换成大写  
        var permissionIdentity = permissionIdentity.toUpperCase();  
        //获取检测权限的状态  
        var checkResult = plus.navigator.checkPermission(permissionIdentity);  
        //权限状态是否正常  
        var permissionStatusOk = false;  
        //权限中文名称  
        var permissionName = '';  
        //对应 andorid 的具体权限  
        var androidPermission = '';  
        //获取权限中文意思与对应 android 系统的权限字符串  
        switch (permissionIdentity) {  
            case 'CAMERA':  
                permissionName = '摄像头';  
                androidPermission = 'android.permission.CAMERA';  
                break;  
            case 'CONTACTS':  
                permissionName = '系统联系人';  
                androidPermission = 'android.permission.READ_CONTACTS'  
                break;  
            case 'GALLERY':  
                permissionName = '系统相册';  
                androidPermission = 'android.permission.READ_EXTERNAL_STORAGE';  
                break;  
            case 'LOCATION':  
                permissionName = '定位';  
                androidPermission = 'android.permission.ACCESS_COARSE_LOCATION';  
                break;  
            case 'NOTIFITION':  
                permissionName = '消息通知';  
                androidPermission = '消息通知';  
                break;  
            case 'RECORD':  
                permissionName = '录音';  
                androidPermission = 'android.permission.RECORD_AUDIO';  
                break;  
            case 'SHORTCUT':  
                permissionName = '创建桌面快捷方式';  
                androidPermission = 'com.android.launcher.permission.INSTALL_SHORTCUT';  
                break;  
            default:  
                permissionName = '未知';  
                androidPermission = '未知';  
                break;  
        }  

        //判断检查权限的结果  
        switch (checkResult) {  
            case 'authorized':  
                //正常的  
                permissionStatusOk = true  
                break;  
            case 'denied':  
                //表示程序已被用户拒绝使用此权限,如果是拒绝的就再次提示用户打开确认提示框  
                //如果有该权限但是没有打开不进行操作还是会去申请或手动打开  
                // console.log('已关闭' + permissionName + '权限')  
                // errorCallBack('已关闭' + permissionName + '权限');  
                // return  
                break;  
            case 'undetermined':  
                // 表示程序未确定是否可使用此权限,此时调用对应的API时系统会弹出提示框让用户确认  
                // this.requestPermissions(androidPermission, permissionName, successCallBack, errorCallBack)  
                // errorCallBack('未确定' + permissionName + '权限');  
                // return  
                break;  
            case 'unknown':  
                errorCallBack('无法查询' + permissionName + '权限');  
                return  
                break;  
            default:  
                errorCallBack('不支持' + permissionName + '权限');  
                return  
                break;  
        }  

        //如果权限是正常的执行成功回调  
        if (permissionStatusOk) {  
            successCallBack()  
        } else {  
            //如果不正常,如果是 andorid 系统,就动态申请权限  
            if (plus.os.name == 'Android') {  
                //动态申请权限  
                plus.android.requestPermissions([androidPermission], function(e) {  
                    if (e.deniedAlways.length > 0) {  
                        //权限被永久拒绝  
                        // 弹出提示框解释为何需要定位权限,引导用户打开设置页面开启  
                        errorCallBack(permissionName + ' 权限被永久拒绝,请到设置权限里找到应用手动开启权限,否则将不能使用此功能。')  
                        // console.log('Always Denied!!! ' + e.deniedAlways.toString());  
                    }  
                    if (e.deniedPresent.length > 0) {  
                        //权限被临时拒绝  
                        // 弹出提示框解释为何需要定位权限,可再次调用plus.android.requestPermissions申请权限  
                        errorCallBack('拒绝开启 ' + permissionName + ' 权限,将不能使用此功能!')  
                        // console.log('Present Denied!!! ' + e.deniedPresent.toString());  
                    }  
                    if (e.granted.length > 0) {  
                        //权限被允许  
                        //调用依赖获取定位权限的代码  
                        successCallBack()  
                        // console.log('Granted!!! ' + e.granted.toString());  
                    }  
                }, function(e) {  
                    errorCallBack('请求 ' + permissionName + ' 权限失败,' + +JSON.stringify(e))  
                    // console.log('Request Permissions error:' + JSON.stringify(e));  
                })  
            } else if (plus.os.name == 'iOS') {  
                //ios ,第一次使用目的权限时,应用的权限列表里是不存在的,所以先默认执行一下成功回调,打开要使用的操作,比如 plus.camera  
                //这时系统会提示是否打开相应的权限,如果拒绝也没关系,因为应用的权限列表里已经存在该权限了,下次再调用相应权限时,就会  
                //走 else 里的流程,会给用户提示,并且跳转到应该的权限页面,让用户手动打开。  
                if (checkResult == 'undetermined') {  
                    //调用依赖获取定位权限的代码  
                    successCallBack(true)  
                } else {  
                    //如果是 ios 系统,ios 没有动态申请操作,所以提示用户去设置页面手动打开  
                    mui.confirm(permissionName + ' 权限没有开启,是否去开启?', '提醒', ['取消', '确认'], function(e) {  
                        //取消  
                        if (e.index == 0) {  
                            errorCallBack('拒绝开启 ' + permissionName + ' 权限,将不能使用此功能!')  
                        } else if (e.index == 1) {  
                            //确认,打开当前应用权限设置页面  
                            var UIApplication = plus.ios.import('UIApplication');  
                            var application2 = UIApplication.sharedApplication();  
                            var NSURL2 = plus.ios.import('NSURL');  
                            // var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");                             
                            var setting2 = NSURL2.URLWithString('app-settings:');  
                            application2.openURL(setting2);  

                            plus.ios.deleteObject(setting2);  
                            plus.ios.deleteObject(NSURL2);  
                            plus.ios.deleteObject(application2)  
                        }  
                    }, 'div')  
                }  
            }  
        }  
}

代码使用示例:
//先动态申请权限
getPermission('CAMERA', function() {
/拍照/
that._takePhoto()
}, function(msg) {
mui.alert(msg, '提醒', '确定', function() {}, 'div')
})
传参传注释里的大写。
涛声依旧吧,先这么着,有问题大家伙讨论。

继续阅读 »

ios 就这个个性,应用第一次用权限时,比如 相机 权限,检查的话是不存在的!就算打开 应用的权限页面 也没用,因为里面没有 相机 权限...,算了,不多说了,怀疑自己个儿抑郁了....直接发代码了,在逻辑上很可能不完善,还望懂行的道友...


    /**  
     * 获取系统权限  
     * @param {Object} permission       权限标识  
     *      CAMERA: (String 类型 )访问摄像头权限         用于调用摄像头(plus.camera.* plus.barcode.*)  
     *      CONTACTS: (String 类型 )访问系统联系人权限     用于访问(读、写)系统通讯录(plus.gallery.*)  
     *      GALLERY: (String 类型 )访问系统相册权限       用于访问(读、写)系统相册(plus.gallery.*)  
     *      LOCATION: (String 类型 )定位权限              用于获取当前用户位置信息(plus.geolocation.*)  
     *      NOTIFITION: (String 类型 )消息通知权限      用于接收系统消息通知(plus.push.*)  
     *      RECORD: (String 类型 )录音权限                用于进行本地录音操作(plus.audio.AudioRecorder)  
     *      SHORTCUT: (String 类型 )创建桌面快捷方式权限    用于在系统桌面创建快捷方式图标(plus.navigator.createShortcut)  
     *   
     * @param {Object} successCallBack  成功回调  
     * @param {Object} errorCallBack    失败回调  
     */  
function getPermission(permissionIdentity, successCallBack, errorCallBack){  
        //权限标识转换成大写  
        var permissionIdentity = permissionIdentity.toUpperCase();  
        //获取检测权限的状态  
        var checkResult = plus.navigator.checkPermission(permissionIdentity);  
        //权限状态是否正常  
        var permissionStatusOk = false;  
        //权限中文名称  
        var permissionName = '';  
        //对应 andorid 的具体权限  
        var androidPermission = '';  
        //获取权限中文意思与对应 android 系统的权限字符串  
        switch (permissionIdentity) {  
            case 'CAMERA':  
                permissionName = '摄像头';  
                androidPermission = 'android.permission.CAMERA';  
                break;  
            case 'CONTACTS':  
                permissionName = '系统联系人';  
                androidPermission = 'android.permission.READ_CONTACTS'  
                break;  
            case 'GALLERY':  
                permissionName = '系统相册';  
                androidPermission = 'android.permission.READ_EXTERNAL_STORAGE';  
                break;  
            case 'LOCATION':  
                permissionName = '定位';  
                androidPermission = 'android.permission.ACCESS_COARSE_LOCATION';  
                break;  
            case 'NOTIFITION':  
                permissionName = '消息通知';  
                androidPermission = '消息通知';  
                break;  
            case 'RECORD':  
                permissionName = '录音';  
                androidPermission = 'android.permission.RECORD_AUDIO';  
                break;  
            case 'SHORTCUT':  
                permissionName = '创建桌面快捷方式';  
                androidPermission = 'com.android.launcher.permission.INSTALL_SHORTCUT';  
                break;  
            default:  
                permissionName = '未知';  
                androidPermission = '未知';  
                break;  
        }  

        //判断检查权限的结果  
        switch (checkResult) {  
            case 'authorized':  
                //正常的  
                permissionStatusOk = true  
                break;  
            case 'denied':  
                //表示程序已被用户拒绝使用此权限,如果是拒绝的就再次提示用户打开确认提示框  
                //如果有该权限但是没有打开不进行操作还是会去申请或手动打开  
                // console.log('已关闭' + permissionName + '权限')  
                // errorCallBack('已关闭' + permissionName + '权限');  
                // return  
                break;  
            case 'undetermined':  
                // 表示程序未确定是否可使用此权限,此时调用对应的API时系统会弹出提示框让用户确认  
                // this.requestPermissions(androidPermission, permissionName, successCallBack, errorCallBack)  
                // errorCallBack('未确定' + permissionName + '权限');  
                // return  
                break;  
            case 'unknown':  
                errorCallBack('无法查询' + permissionName + '权限');  
                return  
                break;  
            default:  
                errorCallBack('不支持' + permissionName + '权限');  
                return  
                break;  
        }  

        //如果权限是正常的执行成功回调  
        if (permissionStatusOk) {  
            successCallBack()  
        } else {  
            //如果不正常,如果是 andorid 系统,就动态申请权限  
            if (plus.os.name == 'Android') {  
                //动态申请权限  
                plus.android.requestPermissions([androidPermission], function(e) {  
                    if (e.deniedAlways.length > 0) {  
                        //权限被永久拒绝  
                        // 弹出提示框解释为何需要定位权限,引导用户打开设置页面开启  
                        errorCallBack(permissionName + ' 权限被永久拒绝,请到设置权限里找到应用手动开启权限,否则将不能使用此功能。')  
                        // console.log('Always Denied!!! ' + e.deniedAlways.toString());  
                    }  
                    if (e.deniedPresent.length > 0) {  
                        //权限被临时拒绝  
                        // 弹出提示框解释为何需要定位权限,可再次调用plus.android.requestPermissions申请权限  
                        errorCallBack('拒绝开启 ' + permissionName + ' 权限,将不能使用此功能!')  
                        // console.log('Present Denied!!! ' + e.deniedPresent.toString());  
                    }  
                    if (e.granted.length > 0) {  
                        //权限被允许  
                        //调用依赖获取定位权限的代码  
                        successCallBack()  
                        // console.log('Granted!!! ' + e.granted.toString());  
                    }  
                }, function(e) {  
                    errorCallBack('请求 ' + permissionName + ' 权限失败,' + +JSON.stringify(e))  
                    // console.log('Request Permissions error:' + JSON.stringify(e));  
                })  
            } else if (plus.os.name == 'iOS') {  
                //ios ,第一次使用目的权限时,应用的权限列表里是不存在的,所以先默认执行一下成功回调,打开要使用的操作,比如 plus.camera  
                //这时系统会提示是否打开相应的权限,如果拒绝也没关系,因为应用的权限列表里已经存在该权限了,下次再调用相应权限时,就会  
                //走 else 里的流程,会给用户提示,并且跳转到应该的权限页面,让用户手动打开。  
                if (checkResult == 'undetermined') {  
                    //调用依赖获取定位权限的代码  
                    successCallBack(true)  
                } else {  
                    //如果是 ios 系统,ios 没有动态申请操作,所以提示用户去设置页面手动打开  
                    mui.confirm(permissionName + ' 权限没有开启,是否去开启?', '提醒', ['取消', '确认'], function(e) {  
                        //取消  
                        if (e.index == 0) {  
                            errorCallBack('拒绝开启 ' + permissionName + ' 权限,将不能使用此功能!')  
                        } else if (e.index == 1) {  
                            //确认,打开当前应用权限设置页面  
                            var UIApplication = plus.ios.import('UIApplication');  
                            var application2 = UIApplication.sharedApplication();  
                            var NSURL2 = plus.ios.import('NSURL');  
                            // var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");                             
                            var setting2 = NSURL2.URLWithString('app-settings:');  
                            application2.openURL(setting2);  

                            plus.ios.deleteObject(setting2);  
                            plus.ios.deleteObject(NSURL2);  
                            plus.ios.deleteObject(application2)  
                        }  
                    }, 'div')  
                }  
            }  
        }  
}

代码使用示例:
//先动态申请权限
getPermission('CAMERA', function() {
/拍照/
that._takePhoto()
}, function(msg) {
mui.alert(msg, '提醒', '确定', function() {}, 'div')
})
传参传注释里的大写。
涛声依旧吧,先这么着,有问题大家伙讨论。

收起阅读 »

nui-app h5微信分享的jweixin demo

微信分享 分享插件

第一步:npm install jweixin-module --save
第二步:在main.js里或者具体的页面这样写

import jswx from 'jweixin-module/out/index.js'  
 let wx_config = “后台返回的config”  

                     jswx.config(  
                     {  
                         debug:false,  
                         appId:wx_config.appId, // 必填,公众号的唯一标识  
                         timestamp:wx_config.timestamp , // 必填,生成签名的时间戳  
                         nonceStr: wx_config.nonceStr, // 必填,生成签名的随机串  
                         signature: wx_config.signature,// 必填,签名  
                         jsApiList:wx_config.jsApiList // 必填,需要使用的JS接口列表          
                     }                                 
                     );  
            jswx.ready(()=>{  
                                          //分享给朋友  
                    jswx.onMenuShareTimeline({  
                        title: 'xxxx', // 分享标题  
                        link: 'https://www.xxx.com', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致  
                        imgUrl: 'https:///www.xxx.com/icon.png', // 分享图标  
                        success: function () {  
                        // 用户点击了分享后执行的回调函数  
                    },  
                     });      
                                         //分享朋友圈  
                     jswx.onMenuShareAppMessage({  
                            title: 'xxxx', // 分享标题  
                            desc: 'xxxx', // 分享描述  
                            link: 'https://www.xxx.com', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致  
                        imgUrl: 'https:///www.xxx.com/icon.png', // 分享图标  
                            success: function () {  
                             uni.showToast({  
                                    title: '分享成功',  
                                    duration: 2000  
                                });  
                            }  
                            });  
                })  

//以上

亲测可用,再有问题就是后台的锅了,怼他们。。。。。还有一个,如果一切正常报:invalid Signature ,那有可能是后台需要获取你前端当前页面的href,否则一直会报这个错,你获取window.location.href给它,如果是tp5的话,应该是

$url = ‘当前链接(前端获取分享那页的链接:window.location.href,传过来这里)’//这步非常重要,官方文档都没有的  
$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";  

    $signature = sha1($string);

生成签名的这个位置

最终效果

继续阅读 »

第一步:npm install jweixin-module --save
第二步:在main.js里或者具体的页面这样写

import jswx from 'jweixin-module/out/index.js'  
 let wx_config = “后台返回的config”  

                     jswx.config(  
                     {  
                         debug:false,  
                         appId:wx_config.appId, // 必填,公众号的唯一标识  
                         timestamp:wx_config.timestamp , // 必填,生成签名的时间戳  
                         nonceStr: wx_config.nonceStr, // 必填,生成签名的随机串  
                         signature: wx_config.signature,// 必填,签名  
                         jsApiList:wx_config.jsApiList // 必填,需要使用的JS接口列表          
                     }                                 
                     );  
            jswx.ready(()=>{  
                                          //分享给朋友  
                    jswx.onMenuShareTimeline({  
                        title: 'xxxx', // 分享标题  
                        link: 'https://www.xxx.com', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致  
                        imgUrl: 'https:///www.xxx.com/icon.png', // 分享图标  
                        success: function () {  
                        // 用户点击了分享后执行的回调函数  
                    },  
                     });      
                                         //分享朋友圈  
                     jswx.onMenuShareAppMessage({  
                            title: 'xxxx', // 分享标题  
                            desc: 'xxxx', // 分享描述  
                            link: 'https://www.xxx.com', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致  
                        imgUrl: 'https:///www.xxx.com/icon.png', // 分享图标  
                            success: function () {  
                             uni.showToast({  
                                    title: '分享成功',  
                                    duration: 2000  
                                });  
                            }  
                            });  
                })  

//以上

亲测可用,再有问题就是后台的锅了,怼他们。。。。。还有一个,如果一切正常报:invalid Signature ,那有可能是后台需要获取你前端当前页面的href,否则一直会报这个错,你获取window.location.href给它,如果是tp5的话,应该是

$url = ‘当前链接(前端获取分享那页的链接:window.location.href,传过来这里)’//这步非常重要,官方文档都没有的  
$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";  

    $signature = sha1($string);

生成签名的这个位置

最终效果

收起阅读 »

公告:uni-app V3版本公测;小米商店/应用宝隐私问题公告;关于Apple发布的App Updates for HTML5 Apps 的说明

公告

关于Apple发布的 App Updates for HTML5 Apps 的说明

详见:https://ask.dcloud.net.cn/article/36654

重磅:uni-app V3版本公测,App端性能、功能大幅提升

更快的启动速度、更多vue语法支持、更方便的开发体验,详见:https://ask.dcloud.net.cn/article/36599

小米应用商店/应用宝隐私管理问题公告

微信小程序2.9.3基础库,input事件失效

微信基础库2.9.3版本在微信开发者工具模拟器端,存在input事件失效的Bug,真机运行没问题。

该Bug影响uni-app在微信开发者工具模拟器端的运行测试(同样真机运行没问题),具体表现有:

  • input事件不触发
  • 表单双向数据绑定失效

该问题目前微信官方已受理(详见微信社区),目前建议开发者临时手动降低基础库版本为2.9.2uni-app今天也会发布紧急更新版,将微信基础库版本策略由默认最新修改为2.9.2,临时解决微信平台的Bug。

阿里小程序IDE官方内嵌uni-app,为开发者提供多端开发服务

详见:https://ask.dcloud.net.cn/article/36485

老版iOS基座过期无法安装的公告

老版HBuilder及HBuilderX 2.3.3.20190923以下的版本,由于iOS企业证书过期,会导致真机运行时默认基座无法安装到iOS设备。需升级新版HBuilderX,详见:https://ask.dcloud.net.cn/article/36523

HBuilderX(alpha)云端打包提交AppStore报WARNING ITMS-90703的公告

详见:https://ask.dcloud.net.cn/article/36588

uni-app 2.3 新版使用注意

uni-app升级,可能会导致老版代码无法正常运行。这并非DCloud所愿,引发这类问题的原因包括:

  1. 三方平台升级,比如iOS13升级导致很多问题,还引发微信等sdk升级的连锁反应
  2. 因为性能问题。为了让应用性能更高,重构了某些实现,废弃了影响性能的写法。比如废弃非自定义组件模式。
    最近新版升级注意详见下:
    • 2.3.4起,tabbar改为纯原生方式实现,无法再通过plus.webview获取tabbar。并且App端高度从之前的56px调整为50px,目前是为了和H5端统一(H5一直是50px)。如需调节回原来的56px,可以在pages.json里配置高度(后期其他端也会支持高度设置,如果不想各端一致,可以使用条件编译)。之前版本iOS上tabbar页面在内存不足时会白屏,也一同解决了
    • 2.3.4起,内置了bindingx,无需再手动import npm库。直接uni.requireNativePlugin('bindingx')即可使用。
    • 2.3.4起,微信的新版分享登录支付SDK升级,要求配置通用链接,否则会打包失败,详见https://ask.dcloud.net.cn/article/36445
    • 5+App或uni-app的web-view组件在iOS上默认改为WKWebview后,会产生跨域导致的联网失败问题、本地跨目录Http请求失败问题、js原生加密失效、拍照等大内存占用操作白屏等问题,详见:https://ask.dcloud.net.cn/article/36348
    • uni-app H5平台 新增 icon 组件,导致 uni-icon 不显示的问题,详见:https://ask.dcloud.net.cn/article/36404
    • 升级后运行到小程序平台,提示 tongji.dcloud.io 不在安全域名名单的问题:这是因为新增了uni统计,一份报表看全端数据,详见 https://tongji.dcloud.io。在小程序端,使用uni统计需在安全域名名单中新增 tongji.dcloud.io 。如不需要uni统计,可在manifest中关闭。开通和关闭详见:https://ask.dcloud.net.cn/article/36303
    • 新版默认为自定义组件模式,而老版如果manifest不指定则是非自定义组件模式。如果新版无法编译老项目大多因为这个原因。详见:https://ask.dcloud.net.cn/article/36385
    • 2.3.4起,Android平台Webview窗口先隐藏(hide)再添加(append)到父窗口后仍然会显示的Bug,导致mui中tabbar-webview显示有问题。2.3.8版本已修复。

iOS13适配

iOS13适配工作已完成,请升级新版2.3.5。

  • 关于iOS13上uni-app页面无法滚动的问题,详见https://ask.dcloud.net.cn/article/36410
  • 微信等三方SDK伴随iOS13都升级了,在HBuilderX 2.3.4中已经升级完毕,iOS平台提交云端打包需要配置通用链接(Universal Link),否则会打包失败,详见https://ask.dcloud.net.cn/article/36445
  • 2.2.5版-2.3.3版,iOS上带tab的页面在手机内存不足时可能出现白屏,在HBuilderX 2.3.4 中已修复。

iOS13引发了Appstore审核的2个政策变化,需注意

uni-app 2.3 重要更新如下:

  • 新增了uni统计,一份报表看全端数据,详见 https://tongji.dcloud.io
    在小程序端,使用uni统计需在安全域名名单中新增 tongji.dcloud.io 。如不需要uni统计,可在manifest中关闭。开通和关闭详见:https://ask.dcloud.net.cn/article/36303
  • 新增 wxs
  • nvue支持vuex
  • App平台 适配 iOS13
  • App平台 优化 页面背景样式生效时机,解决深色背景等特定场景下,页面切换时闪白的问题
  • App平台 优化 Android上使用tab的应用降低内存占用,转场动画和页面滚动更平顺
  • App平台 修复 个推SDK引起的蓝牙权限影响Appstore审核的问题以及隐私政策引发Google Play Store下架问题
  • App平台 支持原生凸起的tabbar
  • App平台 支持打包时原生混淆加密nvue文件
  • App平台 适配 MIUI11,解决toast背景为白色,导致前景色无法看清的问题

关于2019年11月1日起,uni-app不再支持非自定义组件模式的公告:

详见:https://ask.dcloud.net.cn/article/36385

DCloud帮Vue官网提供免费Vue视频教程:

详见:https://ask.dcloud.net.cn/article/36363

vue conf大会上DCloud CTO崔红保的演讲

uni-app的性能为什么高于微信原生开发和其他小程序框架?来看这个视频讲解框架底层的原理:
https://v.qq.com/x/page/r0886mn8v6l.html

继续阅读 »

关于Apple发布的 App Updates for HTML5 Apps 的说明

详见:https://ask.dcloud.net.cn/article/36654

重磅:uni-app V3版本公测,App端性能、功能大幅提升

更快的启动速度、更多vue语法支持、更方便的开发体验,详见:https://ask.dcloud.net.cn/article/36599

小米应用商店/应用宝隐私管理问题公告

微信小程序2.9.3基础库,input事件失效

微信基础库2.9.3版本在微信开发者工具模拟器端,存在input事件失效的Bug,真机运行没问题。

该Bug影响uni-app在微信开发者工具模拟器端的运行测试(同样真机运行没问题),具体表现有:

  • input事件不触发
  • 表单双向数据绑定失效

该问题目前微信官方已受理(详见微信社区),目前建议开发者临时手动降低基础库版本为2.9.2uni-app今天也会发布紧急更新版,将微信基础库版本策略由默认最新修改为2.9.2,临时解决微信平台的Bug。

阿里小程序IDE官方内嵌uni-app,为开发者提供多端开发服务

详见:https://ask.dcloud.net.cn/article/36485

老版iOS基座过期无法安装的公告

老版HBuilder及HBuilderX 2.3.3.20190923以下的版本,由于iOS企业证书过期,会导致真机运行时默认基座无法安装到iOS设备。需升级新版HBuilderX,详见:https://ask.dcloud.net.cn/article/36523

HBuilderX(alpha)云端打包提交AppStore报WARNING ITMS-90703的公告

详见:https://ask.dcloud.net.cn/article/36588

uni-app 2.3 新版使用注意

uni-app升级,可能会导致老版代码无法正常运行。这并非DCloud所愿,引发这类问题的原因包括:

  1. 三方平台升级,比如iOS13升级导致很多问题,还引发微信等sdk升级的连锁反应
  2. 因为性能问题。为了让应用性能更高,重构了某些实现,废弃了影响性能的写法。比如废弃非自定义组件模式。
    最近新版升级注意详见下:
    • 2.3.4起,tabbar改为纯原生方式实现,无法再通过plus.webview获取tabbar。并且App端高度从之前的56px调整为50px,目前是为了和H5端统一(H5一直是50px)。如需调节回原来的56px,可以在pages.json里配置高度(后期其他端也会支持高度设置,如果不想各端一致,可以使用条件编译)。之前版本iOS上tabbar页面在内存不足时会白屏,也一同解决了
    • 2.3.4起,内置了bindingx,无需再手动import npm库。直接uni.requireNativePlugin('bindingx')即可使用。
    • 2.3.4起,微信的新版分享登录支付SDK升级,要求配置通用链接,否则会打包失败,详见https://ask.dcloud.net.cn/article/36445
    • 5+App或uni-app的web-view组件在iOS上默认改为WKWebview后,会产生跨域导致的联网失败问题、本地跨目录Http请求失败问题、js原生加密失效、拍照等大内存占用操作白屏等问题,详见:https://ask.dcloud.net.cn/article/36348
    • uni-app H5平台 新增 icon 组件,导致 uni-icon 不显示的问题,详见:https://ask.dcloud.net.cn/article/36404
    • 升级后运行到小程序平台,提示 tongji.dcloud.io 不在安全域名名单的问题:这是因为新增了uni统计,一份报表看全端数据,详见 https://tongji.dcloud.io。在小程序端,使用uni统计需在安全域名名单中新增 tongji.dcloud.io 。如不需要uni统计,可在manifest中关闭。开通和关闭详见:https://ask.dcloud.net.cn/article/36303
    • 新版默认为自定义组件模式,而老版如果manifest不指定则是非自定义组件模式。如果新版无法编译老项目大多因为这个原因。详见:https://ask.dcloud.net.cn/article/36385
    • 2.3.4起,Android平台Webview窗口先隐藏(hide)再添加(append)到父窗口后仍然会显示的Bug,导致mui中tabbar-webview显示有问题。2.3.8版本已修复。

iOS13适配

iOS13适配工作已完成,请升级新版2.3.5。

  • 关于iOS13上uni-app页面无法滚动的问题,详见https://ask.dcloud.net.cn/article/36410
  • 微信等三方SDK伴随iOS13都升级了,在HBuilderX 2.3.4中已经升级完毕,iOS平台提交云端打包需要配置通用链接(Universal Link),否则会打包失败,详见https://ask.dcloud.net.cn/article/36445
  • 2.2.5版-2.3.3版,iOS上带tab的页面在手机内存不足时可能出现白屏,在HBuilderX 2.3.4 中已修复。

iOS13引发了Appstore审核的2个政策变化,需注意

uni-app 2.3 重要更新如下:

  • 新增了uni统计,一份报表看全端数据,详见 https://tongji.dcloud.io
    在小程序端,使用uni统计需在安全域名名单中新增 tongji.dcloud.io 。如不需要uni统计,可在manifest中关闭。开通和关闭详见:https://ask.dcloud.net.cn/article/36303
  • 新增 wxs
  • nvue支持vuex
  • App平台 适配 iOS13
  • App平台 优化 页面背景样式生效时机,解决深色背景等特定场景下,页面切换时闪白的问题
  • App平台 优化 Android上使用tab的应用降低内存占用,转场动画和页面滚动更平顺
  • App平台 修复 个推SDK引起的蓝牙权限影响Appstore审核的问题以及隐私政策引发Google Play Store下架问题
  • App平台 支持原生凸起的tabbar
  • App平台 支持打包时原生混淆加密nvue文件
  • App平台 适配 MIUI11,解决toast背景为白色,导致前景色无法看清的问题

关于2019年11月1日起,uni-app不再支持非自定义组件模式的公告:

详见:https://ask.dcloud.net.cn/article/36385

DCloud帮Vue官网提供免费Vue视频教程:

详见:https://ask.dcloud.net.cn/article/36363

vue conf大会上DCloud CTO崔红保的演讲

uni-app的性能为什么高于微信原生开发和其他小程序框架?来看这个视频讲解框架底层的原理:
https://v.qq.com/x/page/r0886mn8v6l.html

收起阅读 »

uni-app微信小程序运行

微信小程序 小程序 uniapp 微信开发者工具

uni-app微信小程序运行

github地址,喜欢的可以star下哦

新手可能使用uni-app开发时,想在微信开发者工具预览,经常会遇到各种问题,在此写一个操作步骤

新手可能遇到过这个的问题

操作步骤

运行微信开发者工具前需要一些配置

创建uni-app项目这里步骤忽略了。。。,默认你们已经创建好了uni-app项目了

步骤一

步骤二

步骤三

步骤四

步骤五

这样就代表运行成功了,赶快去试试吧

继续阅读 »

uni-app微信小程序运行

github地址,喜欢的可以star下哦

新手可能使用uni-app开发时,想在微信开发者工具预览,经常会遇到各种问题,在此写一个操作步骤

新手可能遇到过这个的问题

操作步骤

运行微信开发者工具前需要一些配置

创建uni-app项目这里步骤忽略了。。。,默认你们已经创建好了uni-app项目了

步骤一

步骤二

步骤三

步骤四

步骤五

这样就代表运行成功了,赶快去试试吧

收起阅读 »

Windows申请iOS证书p12及描述文件mobileprovision

iOS打包

使用自己证书打包iOS时需要上传两个iOS证书文件p12及描述文件mobileprovision

以申请一份iOS发布证书为例,iOS发布证书用于上架!

一、申请iOS发布证书(p12文件)

Windows申请iOS证书需要用到Appuploader这个软件

如果还没安装Appuploader先安装好

Appuploader下载链接

1.1、登录软件后,点击证书进入,点击右下角+ADD选择,下拉选择发布证书

证书名称:不要中文、随意设置

邮箱:随意

密码:证书的密码、比如设置123这样,不用很复杂,记好、打包时要用、很重要

应用id:这里不用选

点击ok创建。

1.2、创建成功后,找到刚创建的发布证书(iOS Distribution这个类型的就是发布证书,如果之前创建过请看过期时间就知道哪个是新创建的了),点击p12 文件,下载保存.p12证书文件到电脑。

二、创建iOS发布描述文件(.mobileprovision文件)

2.1、返回Appuploader首页,选择描述文件。

2.2、点击+ ADD,对应选择发布版profile

应用id:选择对应的id(又称套装id,appid,BundleID,包名)

证书:选中全部就行

Devices:设备这里不像选开发版profile时会出现,发布版不用选。

输入名称:不要中文,随意,123之类的就行,注意不要跟之前申请过的名称一样),点击ok创建。

2.3、选择刚创建的发布版描述文件(iOS Distribution这个类型的就是发布描述文件,找刚创建的输入的名称),点击Download下载,保存到电脑

得到了p12及描述文件mobileprovision上传打包即可!

AppID:填写申请描述文件时选择的应用id

profile文件,选择上传配置文件.mobileprovision

私钥证书,上传.p12文件

私钥密码,输入创建p12设置的密码。

然后点击打包。

继续阅读 »

使用自己证书打包iOS时需要上传两个iOS证书文件p12及描述文件mobileprovision

以申请一份iOS发布证书为例,iOS发布证书用于上架!

一、申请iOS发布证书(p12文件)

Windows申请iOS证书需要用到Appuploader这个软件

如果还没安装Appuploader先安装好

Appuploader下载链接

1.1、登录软件后,点击证书进入,点击右下角+ADD选择,下拉选择发布证书

证书名称:不要中文、随意设置

邮箱:随意

密码:证书的密码、比如设置123这样,不用很复杂,记好、打包时要用、很重要

应用id:这里不用选

点击ok创建。

1.2、创建成功后,找到刚创建的发布证书(iOS Distribution这个类型的就是发布证书,如果之前创建过请看过期时间就知道哪个是新创建的了),点击p12 文件,下载保存.p12证书文件到电脑。

二、创建iOS发布描述文件(.mobileprovision文件)

2.1、返回Appuploader首页,选择描述文件。

2.2、点击+ ADD,对应选择发布版profile

应用id:选择对应的id(又称套装id,appid,BundleID,包名)

证书:选中全部就行

Devices:设备这里不像选开发版profile时会出现,发布版不用选。

输入名称:不要中文,随意,123之类的就行,注意不要跟之前申请过的名称一样),点击ok创建。

2.3、选择刚创建的发布版描述文件(iOS Distribution这个类型的就是发布描述文件,找刚创建的输入的名称),点击Download下载,保存到电脑

得到了p12及描述文件mobileprovision上传打包即可!

AppID:填写申请描述文件时选择的应用id

profile文件,选择上传配置文件.mobileprovision

私钥证书,上传.p12文件

私钥密码,输入创建p12设置的密码。

然后点击打包。

收起阅读 »