HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

iOS 原生工程集成SDK,如果弹窗提示 “HTML5+ Rumtime D”,按如下方式配置工程

提示“HTML5+ Rumtime D” iOS离线打包 弹窗提示 HTML5

如果您遇到弹窗提示 “HTML5+ Rumtime D” 如下图情况,这是因为您调用了原生功能模块但是没有将对应的依赖库添加到工程弹出的提示框,首先需要在原生工程里添加国际化配置,然后即可正常提示您缺少的依赖库名称。

配置国际化方法:

1、打开原生工程如下图所显示的界面,点击“+”号,添加相关语言

2、新建文件命名为:Localizable

3、选择刚才新建的文件,再 XCode 的最右边“Show the file inspector” 栏目中有个 “Localization” 按钮,点击它,会弹出一个提示,选择对应的语言。

4、按下图添加相关的内容,下图中的文字,在离线sdk, HBuilder-Hello工程中有,可以直接拷贝。
"A"="当前环境无法运行启用“自定义组件模式”的uni-app应用!";
"B"="查看详情";
"C"="忽略";
"D"="打包时未添加%@模块,请参考%@";
"E"="本应用使用HBuilderX%@编译,而手机端SDK版本是%@。不匹配的版本可能造成应用异常。";

5、然后重新运行工程,就可以正常显示缺少的依赖库模块了,然后参考 SDK 目录中的 “Feature.xls ”文件,将对应模块的依赖库添加到工程中即可;

继续阅读 »

如果您遇到弹窗提示 “HTML5+ Rumtime D” 如下图情况,这是因为您调用了原生功能模块但是没有将对应的依赖库添加到工程弹出的提示框,首先需要在原生工程里添加国际化配置,然后即可正常提示您缺少的依赖库名称。

配置国际化方法:

1、打开原生工程如下图所显示的界面,点击“+”号,添加相关语言

2、新建文件命名为:Localizable

3、选择刚才新建的文件,再 XCode 的最右边“Show the file inspector” 栏目中有个 “Localization” 按钮,点击它,会弹出一个提示,选择对应的语言。

4、按下图添加相关的内容,下图中的文字,在离线sdk, HBuilder-Hello工程中有,可以直接拷贝。
"A"="当前环境无法运行启用“自定义组件模式”的uni-app应用!";
"B"="查看详情";
"C"="忽略";
"D"="打包时未添加%@模块,请参考%@";
"E"="本应用使用HBuilderX%@编译,而手机端SDK版本是%@。不匹配的版本可能造成应用异常。";

5、然后重新运行工程,就可以正常显示缺少的依赖库模块了,然后参考 SDK 目录中的 “Feature.xls ”文件,将对应模块的依赖库添加到工程中即可;

收起阅读 »

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

公告

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

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

继续阅读 »

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

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

收起阅读 »

关于谷歌商店(Google Play Store)应用因stream.dcloud.net下架的公告

应用下架 GooglePlay

目前有开发者反馈,应用在Google Play上架后被审核小组下架,提示违反个人和敏感信息政策,如下提示:

We’ve identified that your app is using an SDK or library that  
facilitates the collection and transmission of installed packages  
information without meeting the prominent disclosure guidelines.  
If necessary, you can consult your SDK provider(s) for further information.  

Next steps: Submit your app for another review  
Read through the Personal and Sensitive Information policy and make  
the appropriate changes to your app. Your app is using the DCloud  
SDK, which is uploading users Installed Packages information without a  
prominent disclosure to http://stream.dcloud.net. Prior to the  
collection and transmission, it must prominently highlight how the  
user data will be used, describe the type of data being collected and  
have the user provide affirmative consent for such use. Your app must  
handle user data securely, including transmitting it using modern  
cryptography (for example, over HTTPS).  
Make sure your app is compliant with the User Data policy and all  
other Developer Program Policies. Additional enforcement could occur  
if there are further policy violations.  
Sign in to your Play Console and upload the modified, policy compliant  
APK. Make sure to increment the version number of the APK.  
Submit your app.  
If you’ve reviewed the policy and feel this removal may have been in  
error, please reach out to our policy support team. One of my  
colleagues will get back to you within 2 business days.

根据谷歌应用市场反馈的信息,我们排查到应用启动时会发送请求到“http://stream.dcloud.net.cn/device/location”,查询当前设备Webview是否支持需要将标准H5定位API(navigator.geolocation)替换为5+定位API(plus.geolocation),用于解决部分设备在国内无法使用标准H5定位API的问题。

navigator.geolocation这个是H5标准的定位API,但在中国,由于谷歌定位服务被墙,导致很多Android Rom上这个API无法成功定位。

主流浏览器不存在这个问题,它们都已经修改过内核。部分国产Rom也修改了自家webview,可以让navigator.geolocation成功定位。所以这个问题只存在于部分rom的webview中。

自动替换 navigator.geolocation 为 plus.geolocation 是有性能损耗的。所以DCloud官方没有强制全部自动替换。而是在云端维护了一个白名单,根据指定rom来替换。

“http://stream.dcloud.net.cn/device/location”,这个链接请求并没有发送应用安装列表。而是根据rom情况,决定是否替换navigator.geolocation为plus.geolocation。

但谷歌市场仍然认为此请求会提交用户敏感数据,并且使用了http的非加密方式。

当然如果开发者使用了一些其他三方sdk,它们也有可能采集了应用列表信息。

为了尽快帮助开发者恢复上架,已发布新的HBulderX 版本

  • 1.9.11 alpha版,该版本临时去掉自动替换navigator.geolocation为5+定位API(plus.geolocation)的逻辑。已被更新的2.0版本替代。
  • 2.0 版,该版本打包时,必须选择google play store 渠道包。

    在HBuilderX 2.0里,打包选择google play渠道包时,还会自动校验targetSdkVersion。避免提交时才发现targetSdkVersion不符合要求,耽误审核时间。

如果开发者仍需要定位替换功能,将标准H5定位API替换为5+定位API,可以使用以下方法进行配置,这种配置是全部替换,不是根据有问题的rom来替换:

  1. 创建Webview窗口时设置是否需要替换
    var wv = plus.webview.create(url, 'id', {  
    replacewebapi: {  
        geolocation: 'alldevice'  
    }  
    });
  2. 应用首页可在manifest.json的plus->launchwebview中配置是否需要替换
    //...  
    "plus": {  
    "launchwebview": {  
        "replacewebapi": {  
            "geolocation": "alldevice"  
        }  
    },  
    //...  
    }

另不少开发者关注谷歌的新政策:8月1日前,不提供64位版本APK的应用,将无法通过谷歌play store安装在64位的Android手机上。
HBuilderX新版已经提供支持,详见:https://ask.dcloud.net.cn/article/36195

重新提交google play时注意要把alpha、beta里面的旧版全部清掉后再提交。
提交按钮为灰,不是因为64位,检查页面里其他项目是否填全或填对。

继续阅读 »

目前有开发者反馈,应用在Google Play上架后被审核小组下架,提示违反个人和敏感信息政策,如下提示:

We’ve identified that your app is using an SDK or library that  
facilitates the collection and transmission of installed packages  
information without meeting the prominent disclosure guidelines.  
If necessary, you can consult your SDK provider(s) for further information.  

Next steps: Submit your app for another review  
Read through the Personal and Sensitive Information policy and make  
the appropriate changes to your app. Your app is using the DCloud  
SDK, which is uploading users Installed Packages information without a  
prominent disclosure to http://stream.dcloud.net. Prior to the  
collection and transmission, it must prominently highlight how the  
user data will be used, describe the type of data being collected and  
have the user provide affirmative consent for such use. Your app must  
handle user data securely, including transmitting it using modern  
cryptography (for example, over HTTPS).  
Make sure your app is compliant with the User Data policy and all  
other Developer Program Policies. Additional enforcement could occur  
if there are further policy violations.  
Sign in to your Play Console and upload the modified, policy compliant  
APK. Make sure to increment the version number of the APK.  
Submit your app.  
If you’ve reviewed the policy and feel this removal may have been in  
error, please reach out to our policy support team. One of my  
colleagues will get back to you within 2 business days.

根据谷歌应用市场反馈的信息,我们排查到应用启动时会发送请求到“http://stream.dcloud.net.cn/device/location”,查询当前设备Webview是否支持需要将标准H5定位API(navigator.geolocation)替换为5+定位API(plus.geolocation),用于解决部分设备在国内无法使用标准H5定位API的问题。

navigator.geolocation这个是H5标准的定位API,但在中国,由于谷歌定位服务被墙,导致很多Android Rom上这个API无法成功定位。

主流浏览器不存在这个问题,它们都已经修改过内核。部分国产Rom也修改了自家webview,可以让navigator.geolocation成功定位。所以这个问题只存在于部分rom的webview中。

自动替换 navigator.geolocation 为 plus.geolocation 是有性能损耗的。所以DCloud官方没有强制全部自动替换。而是在云端维护了一个白名单,根据指定rom来替换。

“http://stream.dcloud.net.cn/device/location”,这个链接请求并没有发送应用安装列表。而是根据rom情况,决定是否替换navigator.geolocation为plus.geolocation。

但谷歌市场仍然认为此请求会提交用户敏感数据,并且使用了http的非加密方式。

当然如果开发者使用了一些其他三方sdk,它们也有可能采集了应用列表信息。

为了尽快帮助开发者恢复上架,已发布新的HBulderX 版本

  • 1.9.11 alpha版,该版本临时去掉自动替换navigator.geolocation为5+定位API(plus.geolocation)的逻辑。已被更新的2.0版本替代。
  • 2.0 版,该版本打包时,必须选择google play store 渠道包。

    在HBuilderX 2.0里,打包选择google play渠道包时,还会自动校验targetSdkVersion。避免提交时才发现targetSdkVersion不符合要求,耽误审核时间。

如果开发者仍需要定位替换功能,将标准H5定位API替换为5+定位API,可以使用以下方法进行配置,这种配置是全部替换,不是根据有问题的rom来替换:

  1. 创建Webview窗口时设置是否需要替换
    var wv = plus.webview.create(url, 'id', {  
    replacewebapi: {  
        geolocation: 'alldevice'  
    }  
    });
  2. 应用首页可在manifest.json的plus->launchwebview中配置是否需要替换
    //...  
    "plus": {  
    "launchwebview": {  
        "replacewebapi": {  
            "geolocation": "alldevice"  
        }  
    },  
    //...  
    }

另不少开发者关注谷歌的新政策:8月1日前,不提供64位版本APK的应用,将无法通过谷歌play store安装在64位的Android手机上。
HBuilderX新版已经提供支持,详见:https://ask.dcloud.net.cn/article/36195

重新提交google play时注意要把alpha、beta里面的旧版全部清掉后再提交。
提交按钮为灰,不是因为64位,检查页面里其他项目是否填全或填对。

收起阅读 »

mac hbuilderX 无法启动

闪退

运行立马闪退,没有错误信息,大家有碰到吗?系统版本10.14.3

运行立马闪退,没有错误信息,大家有碰到吗?系统版本10.14.3

西安招聘uni-app前端工程师 7K-12K

招聘

岗位要求:

  1. 3年以上前端工作经验,HTML/CSS/Javascript基础扎实,能轻松编写符合W3C标准、语义化、兼容主流浏览器的代码, 熟练编写符合ES6、CSS3标准的代码;
  2. 熟悉前端工程化与组件化开发,并有实践经验(如 Webpack、Vue 等或其他前端工具),熟悉MVC、MVVM等前端开发模型;
  3. 至少了解一门非前端的语言(如 NodeJS/PHP等,了解即可,方便与后端对接);
  4. 熟悉常用UI框架;
  5. 有移动端web开发经验,能够独立设计webApp、技术方案(如国内的Dcloud等),并进行性能优化。
    详情请点击查看
继续阅读 »

岗位要求:

  1. 3年以上前端工作经验,HTML/CSS/Javascript基础扎实,能轻松编写符合W3C标准、语义化、兼容主流浏览器的代码, 熟练编写符合ES6、CSS3标准的代码;
  2. 熟悉前端工程化与组件化开发,并有实践经验(如 Webpack、Vue 等或其他前端工具),熟悉MVC、MVVM等前端开发模型;
  3. 至少了解一门非前端的语言(如 NodeJS/PHP等,了解即可,方便与后端对接);
  4. 熟悉常用UI框架;
  5. 有移动端web开发经验,能够独立设计webApp、技术方案(如国内的Dcloud等),并进行性能优化。
    详情请点击查看
收起阅读 »

突然断电后,在hbuilderx编辑器当前打开的文件会变成空白或乱码问题

问题如下,最近几天比较忙一些,笔记本经常忘记插上电源,以前还有提示,现在电池也不给力了,还没到低电量预警状态就自动断电了,问题就来了,在重启电脑后,断电前编辑器打开的文件变成了空白,内容都没有了


,使用sublime text打开此文件显示全是0000

,不过在编辑器中打开的其他处于非编辑状态的文件正常没有问题,出现此情况的hx版本为最新的20190522版本

,以前版本是否有问题不太清楚因为以前没有遇到,首次出现此问题时正在编辑一个重要文件,因为时间比较紧一直没有提交git保存,不能恢复的话多半天工作就白干了,还好在使用了diskgenius扫描了磁盘,发现了以前的数据,恢复到了断电前最后保存的内容,总算有惊无险,不知道其他同学有没有遇到过类似问题,以及官方对此问题有没有解决方案,仅在此记录一下,方便后面同样有问题的同学参考

继续阅读 »

问题如下,最近几天比较忙一些,笔记本经常忘记插上电源,以前还有提示,现在电池也不给力了,还没到低电量预警状态就自动断电了,问题就来了,在重启电脑后,断电前编辑器打开的文件变成了空白,内容都没有了


,使用sublime text打开此文件显示全是0000

,不过在编辑器中打开的其他处于非编辑状态的文件正常没有问题,出现此情况的hx版本为最新的20190522版本

,以前版本是否有问题不太清楚因为以前没有遇到,首次出现此问题时正在编辑一个重要文件,因为时间比较紧一直没有提交git保存,不能恢复的话多半天工作就白干了,还好在使用了diskgenius扫描了磁盘,发现了以前的数据,恢复到了断电前最后保存的内容,总算有惊无险,不知道其他同学有没有遇到过类似问题,以及官方对此问题有没有解决方案,仅在此记录一下,方便后面同样有问题的同学参考

收起阅读 »

uni-app全局水印

文章废话比较多,主要是想讲一下做这个功能所经历的一些事情,先上代码吧:
由于需要借助canvas生成图片,这里的代码是在应用的首页index.vue执行的,在App.vue无法实现,需要在index.vue中定义
代码写的比较乱,先将就着看,之后再整理

<!-- #ifdef APP-PLUS -->  
        <block v-if="showWatermark">  
            <canvas class="watermarkCans" canvas-id="watermarkCanvas"></canvas>  
        </block>  
        <!-- #endif -->

下面是js


    initWatermark(msg) {  
// #ifdef APP-PLUS  
    let _self = this;  
                let id = '1.23452384164.123412415';  
                if (plus.nativeObj.View.getViewById(id) !== null) {  
                    plus.nativeObj.View.getViewById(id).close();  
                }  
                let canvasInAppPlusContext = uni.createCanvasContext('watermarkCanvas');  
                canvasInAppPlusContext.rotate(-30 * Math.PI / 180);  
                canvasInAppPlusContext.setFontSize(uni.upx2px(28));  
                canvasInAppPlusContext.setFillStyle('rgba(200, 200, 200, 0.50)');  
                canvasInAppPlusContext.setTextAlign('left');  
                canvasInAppPlusContext.setTextBaseline('middle');  
                canvasInAppPlusContext.fillText(msg, -25, uni.upx2px(170));  
                canvasInAppPlusContext.draw(false, function() {  
                    uni.canvasToTempFilePath({  
                        canvasId: "watermarkCanvas",  
                        success: function(res) {  
                            _self.showWatermark = false;  
                            let path = res.tempFilePath;  

                            uni.getSystemInfo({  
                                success: function (res) {  
                                    //水印排列行数  
                                    let row = Math.floor(res.windowHeight / uni.upx2px(250));  
                                    let tarArr = [];  

                                    for(let i = 0; i < row; i++) {  
                                        for(let j = 0; j < 3; j++){  
                                            tarArr.push({  
                                                tag: 'img',  
                                                src: path,  
                                                position: {  
                                                    top: (uni.upx2px(255) * i) + 'px',  
                                                    left: (uni.upx2px(255) * j) + 'px',  
                                                    width: uni.upx2px(255) + 'px',  
                                                    height: uni.upx2px(255) + 'px'  
                                                }  
                                            });  
                                        }  
                                    }  

                                    var watermarkView = new plus.nativeObj.View(id, {  
                                        top:'70px',  
                                        left:'0px',  
                                        right: '0px',  
                                        bottom: '50px'  
                                    }, tarArr);  
                                    //拦截View控件的触屏事件,将事件穿透给下一层view  
                                    watermarkView.interceptTouchEvent(false);   
                                    watermarkView.show();  
                                }  
                            });  
                        }  
                    });  
                });           

// #endif  
// #ifdef H5  
let id = '1.23452384164.123412415';  
    if (document.getElementById(id) !== null) {  
        document.body.removeChild(document.getElementById(id));  
    }  

    let can = document.createElement('canvas');  
    can.width = uni.upx2px(250);  
    can.height = uni.upx2px(250);  

    let cans = can.getContext('2d');  

    cans.rotate(-30 * Math.PI / 180);  
    cans.font = uni.upx2px(28) + 'px';  
    cans.fillStyle = 'rgba(200, 200, 200, 0.50)';  
    cans.textAlign = 'left';  
    cans.textBaseline = 'Middle';  
    cans.fillText(msg, -25, uni.upx2px(170));  

    let div = document.createElement('div');  
    div.id = id;  
    div.style.pointerEvents = 'none';  
    div.style.top = '44px';  
    div.style.left = '-40px';  
    div.style.bottom = '50px';  
    div.style.right = '0px';  
    div.style.position = 'fixed';  
    div.style.zIndex = '100000';  
    // div.style.width = document.documentElement.clientWidth + 'px'  
    // div.style.height = document.documentElement.clientHeight + 'px'  
    div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat';  
    document.body.appendChild(div);  
    return id;  
// #endif  
  }

前两天在研究一个全局水印的功能,需要达到以下的效果:
1、根据给出的文字生成水印
2、水印需要在全局生效,不能跳转页面后消失
3、H5端和APP端都要兼容

根据以上的需求,我研究了以下几种方案:
1、封装水印组件。
做一个漂浮的div,定义z-index层级和pointer-event属性和背景平铺重复,在需要的页面中使用组件。这个实现起来很简单,兼容H5和APP,但是有一个问题需要在每一个页面中去单独引入,不符合全局水印的定义,而且项目要提供给项目组使用,很明显不是一个完美的方案。

2、往页面中插入一个div
实现方式和第一点类似,优点是只能在H5端生效,APP端没有body,这个方案直接被pass了

3、用native.js分别实现安卓和IOS端的效果
但是由于对原生开发不了解,这个方案直接就实现不了了

4、直接丢给原生开发做,再去引入插件
这明显不是个好点子,而且研究了这么久不能半半途而废

尝试了很多方法之后我就思考:有没有这样一个顶层的视图容器的东西,可以让我去插入内容,还不会影响事件的穿透,基于这个想法,我又做了一下尝试
1、应用生命周期
由于对移动开发和vue都不熟,尝试了很多vue的方法,生命周期钩子,createElement,render等等,都失败了。

2、webview
我了解到uni-app在APP端实质上也是一个webview,每一个页面其实是这个webview的子webview,我想在应用的onLaunch里边去获取到顶层的webview,往webview中添加子窗口的方式实现,因为各种原因,实现了一半,但是感觉好像有了苗头

3、plus.nativeObj.View
也就是我最终的实现方式,研究了好久,发现了这个宝藏对象。
plus.nativeObj:可以管理系统原生对象。
plus.nativeObj.View:原生控件对象可用于在屏幕上绘制图片或文本内容,当控件不再使用时需要调用close方法销毁控件。
链接:http://www.html5plus.org/doc/zh_cn/nativeobj.html#plus.nativeObj.View
尝试了之后发现可以在屏幕上绘制内容,并且在整个应用生效,开心到爆炸,但是!!又遇到了一个问题,这些内容会形成类似遮罩层的东西,导致事件无法穿透。研究了一番,找到了这样一个方法:view.interceptTouchEvent(false),它可以拦截View控件的触屏事件。
接下来,就是文字生成水印图片的问题了,我用的canvas绘制了一个水印,转换成图片实现。期间遇到了一个问题,APP端的uni.canvasToTempFilePath事件需要放在cans.draw()的回调里去实现。

继续阅读 »

文章废话比较多,主要是想讲一下做这个功能所经历的一些事情,先上代码吧:
由于需要借助canvas生成图片,这里的代码是在应用的首页index.vue执行的,在App.vue无法实现,需要在index.vue中定义
代码写的比较乱,先将就着看,之后再整理

<!-- #ifdef APP-PLUS -->  
        <block v-if="showWatermark">  
            <canvas class="watermarkCans" canvas-id="watermarkCanvas"></canvas>  
        </block>  
        <!-- #endif -->

下面是js


    initWatermark(msg) {  
// #ifdef APP-PLUS  
    let _self = this;  
                let id = '1.23452384164.123412415';  
                if (plus.nativeObj.View.getViewById(id) !== null) {  
                    plus.nativeObj.View.getViewById(id).close();  
                }  
                let canvasInAppPlusContext = uni.createCanvasContext('watermarkCanvas');  
                canvasInAppPlusContext.rotate(-30 * Math.PI / 180);  
                canvasInAppPlusContext.setFontSize(uni.upx2px(28));  
                canvasInAppPlusContext.setFillStyle('rgba(200, 200, 200, 0.50)');  
                canvasInAppPlusContext.setTextAlign('left');  
                canvasInAppPlusContext.setTextBaseline('middle');  
                canvasInAppPlusContext.fillText(msg, -25, uni.upx2px(170));  
                canvasInAppPlusContext.draw(false, function() {  
                    uni.canvasToTempFilePath({  
                        canvasId: "watermarkCanvas",  
                        success: function(res) {  
                            _self.showWatermark = false;  
                            let path = res.tempFilePath;  

                            uni.getSystemInfo({  
                                success: function (res) {  
                                    //水印排列行数  
                                    let row = Math.floor(res.windowHeight / uni.upx2px(250));  
                                    let tarArr = [];  

                                    for(let i = 0; i < row; i++) {  
                                        for(let j = 0; j < 3; j++){  
                                            tarArr.push({  
                                                tag: 'img',  
                                                src: path,  
                                                position: {  
                                                    top: (uni.upx2px(255) * i) + 'px',  
                                                    left: (uni.upx2px(255) * j) + 'px',  
                                                    width: uni.upx2px(255) + 'px',  
                                                    height: uni.upx2px(255) + 'px'  
                                                }  
                                            });  
                                        }  
                                    }  

                                    var watermarkView = new plus.nativeObj.View(id, {  
                                        top:'70px',  
                                        left:'0px',  
                                        right: '0px',  
                                        bottom: '50px'  
                                    }, tarArr);  
                                    //拦截View控件的触屏事件,将事件穿透给下一层view  
                                    watermarkView.interceptTouchEvent(false);   
                                    watermarkView.show();  
                                }  
                            });  
                        }  
                    });  
                });           

// #endif  
// #ifdef H5  
let id = '1.23452384164.123412415';  
    if (document.getElementById(id) !== null) {  
        document.body.removeChild(document.getElementById(id));  
    }  

    let can = document.createElement('canvas');  
    can.width = uni.upx2px(250);  
    can.height = uni.upx2px(250);  

    let cans = can.getContext('2d');  

    cans.rotate(-30 * Math.PI / 180);  
    cans.font = uni.upx2px(28) + 'px';  
    cans.fillStyle = 'rgba(200, 200, 200, 0.50)';  
    cans.textAlign = 'left';  
    cans.textBaseline = 'Middle';  
    cans.fillText(msg, -25, uni.upx2px(170));  

    let div = document.createElement('div');  
    div.id = id;  
    div.style.pointerEvents = 'none';  
    div.style.top = '44px';  
    div.style.left = '-40px';  
    div.style.bottom = '50px';  
    div.style.right = '0px';  
    div.style.position = 'fixed';  
    div.style.zIndex = '100000';  
    // div.style.width = document.documentElement.clientWidth + 'px'  
    // div.style.height = document.documentElement.clientHeight + 'px'  
    div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat';  
    document.body.appendChild(div);  
    return id;  
// #endif  
  }

前两天在研究一个全局水印的功能,需要达到以下的效果:
1、根据给出的文字生成水印
2、水印需要在全局生效,不能跳转页面后消失
3、H5端和APP端都要兼容

根据以上的需求,我研究了以下几种方案:
1、封装水印组件。
做一个漂浮的div,定义z-index层级和pointer-event属性和背景平铺重复,在需要的页面中使用组件。这个实现起来很简单,兼容H5和APP,但是有一个问题需要在每一个页面中去单独引入,不符合全局水印的定义,而且项目要提供给项目组使用,很明显不是一个完美的方案。

2、往页面中插入一个div
实现方式和第一点类似,优点是只能在H5端生效,APP端没有body,这个方案直接被pass了

3、用native.js分别实现安卓和IOS端的效果
但是由于对原生开发不了解,这个方案直接就实现不了了

4、直接丢给原生开发做,再去引入插件
这明显不是个好点子,而且研究了这么久不能半半途而废

尝试了很多方法之后我就思考:有没有这样一个顶层的视图容器的东西,可以让我去插入内容,还不会影响事件的穿透,基于这个想法,我又做了一下尝试
1、应用生命周期
由于对移动开发和vue都不熟,尝试了很多vue的方法,生命周期钩子,createElement,render等等,都失败了。

2、webview
我了解到uni-app在APP端实质上也是一个webview,每一个页面其实是这个webview的子webview,我想在应用的onLaunch里边去获取到顶层的webview,往webview中添加子窗口的方式实现,因为各种原因,实现了一半,但是感觉好像有了苗头

3、plus.nativeObj.View
也就是我最终的实现方式,研究了好久,发现了这个宝藏对象。
plus.nativeObj:可以管理系统原生对象。
plus.nativeObj.View:原生控件对象可用于在屏幕上绘制图片或文本内容,当控件不再使用时需要调用close方法销毁控件。
链接:http://www.html5plus.org/doc/zh_cn/nativeobj.html#plus.nativeObj.View
尝试了之后发现可以在屏幕上绘制内容,并且在整个应用生效,开心到爆炸,但是!!又遇到了一个问题,这些内容会形成类似遮罩层的东西,导致事件无法穿透。研究了一番,找到了这样一个方法:view.interceptTouchEvent(false),它可以拦截View控件的触屏事件。
接下来,就是文字生成水印图片的问题了,我用的canvas绘制了一个水印,转换成图片实现。期间遇到了一个问题,APP端的uni.canvasToTempFilePath事件需要放在cans.draw()的回调里去实现。

收起阅读 »

uni.canvasToTempFilePath的坑

canvas

昨天做一个将canvas转图片的功能,发现以下问题:
1、在APP端,uni.canvasToTempFilePath方法需要放在convasContext.draw的回调里面,否则会一直报canvas is empty
2、在H5端,需要convasContext.draw与uni.canvasToTempFilePath同步执行,也就是不能放在回调里
3、在APP端uni.canvasToTempFilePath返回的路径是一个临时的图片路径
4、在H5端,生成的是base64路径

继续阅读 »

昨天做一个将canvas转图片的功能,发现以下问题:
1、在APP端,uni.canvasToTempFilePath方法需要放在convasContext.draw的回调里面,否则会一直报canvas is empty
2、在H5端,需要convasContext.draw与uni.canvasToTempFilePath同步执行,也就是不能放在回调里
3、在APP端uni.canvasToTempFilePath返回的路径是一个临时的图片路径
4、在H5端,生成的是base64路径

收起阅读 »

uniapp配置request请求的networktimeout

在uniapp中,默认的networktimeout是6000ms,也就是六秒。虽然我在使用时等了好久才进入到fail方法体内,具体也没去测量,总之就是很影响用户体验。那么怎么更改请

求中的networktimeout属性呢?

在uniapp中,networktimeout是属于配置项里面的内容,所以得在配置项里面对request进行配置。

① 点击项目目录下的manifest.json会进入到配置页面,而默认页面只能更改appid,名称,版本号等少量内容,这时需要点击左下方的源码视图进行配置。

② 点击源码视图进入之后你会发现一堆的配置文件。具体参考https://uniapp.dcloud.io/collocation/manifest

③ 根据官方提供的配置说明https://uniapp.dcloud.io/collocation/manifest?id=networktimeout 对照着源码试图进行查看。我们会发现并没有networktimeout这一配置。那么我们

需要增加这一项配置。

④ 在与name同级的地方新增networkTimeout属性,由于该属性下还具有更多的参数可以指定如(connectSocket,uploadFile,downloadFile),所以采用大括号的形式进行

赋值。如

    "name" : "firstapp",  
"appid" : "__UNI__A0A853F",  
"description": "",  
"versionName": "1.0.0",  
"versionCode": "100",  
"transformPx": false,  
"networkTimeout":{  
    "request":3000  
},  
   ........  

设置其他的请求超时时间也同理。

新手入门,自学中,总结得有错的地方请指正,别骂我,我怂...

继续阅读 »

在uniapp中,默认的networktimeout是6000ms,也就是六秒。虽然我在使用时等了好久才进入到fail方法体内,具体也没去测量,总之就是很影响用户体验。那么怎么更改请

求中的networktimeout属性呢?

在uniapp中,networktimeout是属于配置项里面的内容,所以得在配置项里面对request进行配置。

① 点击项目目录下的manifest.json会进入到配置页面,而默认页面只能更改appid,名称,版本号等少量内容,这时需要点击左下方的源码视图进行配置。

② 点击源码视图进入之后你会发现一堆的配置文件。具体参考https://uniapp.dcloud.io/collocation/manifest

③ 根据官方提供的配置说明https://uniapp.dcloud.io/collocation/manifest?id=networktimeout 对照着源码试图进行查看。我们会发现并没有networktimeout这一配置。那么我们

需要增加这一项配置。

④ 在与name同级的地方新增networkTimeout属性,由于该属性下还具有更多的参数可以指定如(connectSocket,uploadFile,downloadFile),所以采用大括号的形式进行

赋值。如

    "name" : "firstapp",  
"appid" : "__UNI__A0A853F",  
"description": "",  
"versionName": "1.0.0",  
"versionCode": "100",  
"transformPx": false,  
"networkTimeout":{  
    "request":3000  
},  
   ........  

设置其他的请求超时时间也同理。

新手入门,自学中,总结得有错的地方请指正,别骂我,我怂...

收起阅读 »

失踪人口从apicloud正式回归dcloud

dcloud一下简称D公司
我工作中第一个正式用的IDE编辑器是D公司的hbuider。
虽然这之前也用过sublimit和zend和PHP风暴等等,但总体来说hbuider更适合我,
以及目前开发PHP后端仍然再用hbuider。

三年前因为需要开发App,
用了D公司之后发现问题大了去了,
因为我是PHP人员,不会安卓和苹果的第三方SDK打包,
所以就用了apicloud,

时至今日,我发现D公司终于为我等这种人解决了第三方SDK的难题,
而且uni-app的强大,从新让我跪舔。

继续阅读 »

dcloud一下简称D公司
我工作中第一个正式用的IDE编辑器是D公司的hbuider。
虽然这之前也用过sublimit和zend和PHP风暴等等,但总体来说hbuider更适合我,
以及目前开发PHP后端仍然再用hbuider。

三年前因为需要开发App,
用了D公司之后发现问题大了去了,
因为我是PHP人员,不会安卓和苹果的第三方SDK打包,
所以就用了apicloud,

时至今日,我发现D公司终于为我等这种人解决了第三方SDK的难题,
而且uni-app的强大,从新让我跪舔。

收起阅读 »

关于dataset的不同表现方式和解决方式

先看一波简单源代码:

<template>  
    <view @tap="tapFunc" data-param="param">  
        点我  
    </view>  
</template>  
<script>  
    export default {  
        data() {  
            return {  
                param: {  
                    a : 1,  
                    b : 2  
                }  
            }  
        },  
        onLoad() {  

        },  
        methods: {  
            tapFunc(e){  

                //   e.currentTarget.dataset.param = ????;    在H5环境中需要从新赋值即可解决 e.currentTarget.dataset.param = this.param;  

            }  
        }  
    }  
</script>  

<style>  

</style>  

请注意,方法tapFunc里面的e.currentTarget.dataset.param获取到的dataset是根据环境不同的,
H5环境获取到的是字符串[objct],不能进行任何操作,单纯只是完全的字符串[objct],
微信小程序环境中获取到的objct对象,没问题。
所以在H5环境中需要从新赋值即可解决 e.currentTarget.dataset.param = this.param;

继续阅读 »

先看一波简单源代码:

<template>  
    <view @tap="tapFunc" data-param="param">  
        点我  
    </view>  
</template>  
<script>  
    export default {  
        data() {  
            return {  
                param: {  
                    a : 1,  
                    b : 2  
                }  
            }  
        },  
        onLoad() {  

        },  
        methods: {  
            tapFunc(e){  

                //   e.currentTarget.dataset.param = ????;    在H5环境中需要从新赋值即可解决 e.currentTarget.dataset.param = this.param;  

            }  
        }  
    }  
</script>  

<style>  

</style>  

请注意,方法tapFunc里面的e.currentTarget.dataset.param获取到的dataset是根据环境不同的,
H5环境获取到的是字符串[objct],不能进行任何操作,单纯只是完全的字符串[objct],
微信小程序环境中获取到的objct对象,没问题。
所以在H5环境中需要从新赋值即可解决 e.currentTarget.dataset.param = this.param;

收起阅读 »

关于页面栈中getCurrentPages()方法,H5和微信小程序的不同表现

H5没问题。
微信小程序中返回的是微信小程序页面栈,
其里面有一个$vm,才是真实的页面栈。

所以统一页面栈获取方法是

let pages = getCurrentPages();  

        // #ifdef MP-WEIXIN  
        return pages[pages.length - 1].$vm;  
        // #endif  
        return pages[pages.length - 1];
继续阅读 »

H5没问题。
微信小程序中返回的是微信小程序页面栈,
其里面有一个$vm,才是真实的页面栈。

所以统一页面栈获取方法是

let pages = getCurrentPages();  

        // #ifdef MP-WEIXIN  
        return pages[pages.length - 1].$vm;  
        // #endif  
        return pages[pages.length - 1];
收起阅读 »