使用uni-app进行微信小程序云开发经验分享
因近期在开发一个微信小程序,涉及到微信小程序云开发,搜索社区,并无相关案例。
经过一番折腾,解决方案如下:
第一步:使用微信开发者工具,创建一个云开发的项目,创建云函数并上传(此项目作为开发云函数专用);
第二步:创建uni-app项目,并将上面云函数项目的appid,填入到此项目里,即可关联并直接使用wx云函数。
至此,就可以正常使用HbuilderX愉快的开发啦~
为了方便理解,我将微信小程序云开发DMEO,转换成uni-app版本,大家可以参考一下(见文末:miniprogram_cloud.zip)。
github地址:https://github.com/zhangdaren/miniprogram-cloud
下载后,填入微信小程序appid即可(运行前,需新建或使用原小程序项目,配置云开发环境,不然无法使用云函数,切记~)
与小程序开发异同:
相同之处: 云函数的使用,与小程序里面完全一致。
不同之处: uni-app里没有const app = getApp(),因此我修改为vuex来存储opendid及其他信息
最后,如果有问题,欢迎指正或回帖~~~
因近期在开发一个微信小程序,涉及到微信小程序云开发,搜索社区,并无相关案例。
经过一番折腾,解决方案如下:
第一步:使用微信开发者工具,创建一个云开发的项目,创建云函数并上传(此项目作为开发云函数专用);
第二步:创建uni-app项目,并将上面云函数项目的appid,填入到此项目里,即可关联并直接使用wx云函数。
至此,就可以正常使用HbuilderX愉快的开发啦~
为了方便理解,我将微信小程序云开发DMEO,转换成uni-app版本,大家可以参考一下(见文末:miniprogram_cloud.zip)。
github地址:https://github.com/zhangdaren/miniprogram-cloud
下载后,填入微信小程序appid即可(运行前,需新建或使用原小程序项目,配置云开发环境,不然无法使用云函数,切记~)
与小程序开发异同:
相同之处: 云函数的使用,与小程序里面完全一致。
不同之处: uni-app里没有const app = getApp(),因此我修改为vuex来存储opendid及其他信息
最后,如果有问题,欢迎指正或回帖~~~
收起阅读 »1.9.7.20190516-alpha版本,出现编译或云打包问题的解决方案
更新:HBuilderX 1.9.7的正式版已经发了,请升级到正式版吧
如果您2019-05-16 上午期间,升级alpha版本到1.9.7,可能会遇到HX版本为1.9.7,但是编译器为1.9.6的问题
解决方案1
- 进入【插件管理】,卸载
uniapp编译插件,重装
解决方案2
重新下载1.9.7alpha版本
更新:HBuilderX 1.9.7的正式版已经发了,请升级到正式版吧
如果您2019-05-16 上午期间,升级alpha版本到1.9.7,可能会遇到HX版本为1.9.7,但是编译器为1.9.6的问题
解决方案1
- 进入【插件管理】,卸载
uniapp编译插件,重装
解决方案2
重新下载1.9.7alpha版本
使用yapi 的ajax配置文件
https://github.com/scandalYang/Yapi-ts-Ajax.ts 需要的拿走
https://github.com/scandalYang/Yapi-ts-Ajax.ts 需要的拿走
Android平台设置UrlSchemes过程中遇到的几个坑
官方代码
document.addEventListener('plusready',function(){
checkArguments();
},false);
// 判断启动方式
function checkArguments(){
console.log("plus.runtime.launcher: "+plus.runtime.launcher);
var args= plus.runtime.arguments;
if(args){
// 处理args参数,如打开新页面等
}
}
// 处理从后台恢复
document.addEventListener('newintent',function(){
console.log("addEventListener: newintent");
checkArguments();
},false);
官方代码没解释太多东西。
第一个坑:
<a herf="test://index.html">点击打开app</a>
app打开之后提示 test://index.html 这个页面打不开
解决方法:
传递参数不要用html后缀之类的形式。建议还是按照官方标准,使用json字符串形式,接收到之后解析url并且跳转。
<a herf="test://{'url':'index.html'}">点击打开app</a>
第二个坑:
app后台运行发起没有任何问题,app如果后台关闭,通过链接唤醒之后,跳转到参数页面,然后无限刷新,根本停止不下来
根据html5+手册介绍 plus.runtime.arguments 这个参数是只读的,设置为空,并且判断也没用
解决方法:
这个放在入口html文件,app关闭情况下,加载会先加载这个页面,这里判断并且执行跳转。
这个plus.runtime.arguments参数清理不掉,但是其他文件不执行,解决了无限跳转的问题!
document.addEventListener('plusready',function(){
checkArguments();
},false);
下面这个放在全局,app不关闭,后台切换到前台的唤醒,自己就执行一次,我也不知道为什么!
// 判断启动方式
function checkArguments(){
console.log("plus.runtime.launcher: "+plus.runtime.launcher);
var args= plus.runtime.arguments;
if(args){
// 处理args参数,如打开新页面等
}
}
// 处理从后台恢复
document.addEventListener('newintent',function(){
console.log("addEventListener: newintent");
checkArguments();
},false);
官方代码
document.addEventListener('plusready',function(){
checkArguments();
},false);
// 判断启动方式
function checkArguments(){
console.log("plus.runtime.launcher: "+plus.runtime.launcher);
var args= plus.runtime.arguments;
if(args){
// 处理args参数,如打开新页面等
}
}
// 处理从后台恢复
document.addEventListener('newintent',function(){
console.log("addEventListener: newintent");
checkArguments();
},false);
官方代码没解释太多东西。
第一个坑:
<a herf="test://index.html">点击打开app</a>
app打开之后提示 test://index.html 这个页面打不开
解决方法:
传递参数不要用html后缀之类的形式。建议还是按照官方标准,使用json字符串形式,接收到之后解析url并且跳转。
<a herf="test://{'url':'index.html'}">点击打开app</a>
第二个坑:
app后台运行发起没有任何问题,app如果后台关闭,通过链接唤醒之后,跳转到参数页面,然后无限刷新,根本停止不下来
根据html5+手册介绍 plus.runtime.arguments 这个参数是只读的,设置为空,并且判断也没用
解决方法:
这个放在入口html文件,app关闭情况下,加载会先加载这个页面,这里判断并且执行跳转。
这个plus.runtime.arguments参数清理不掉,但是其他文件不执行,解决了无限跳转的问题!
document.addEventListener('plusready',function(){
checkArguments();
},false);
下面这个放在全局,app不关闭,后台切换到前台的唤醒,自己就执行一次,我也不知道为什么!
// 判断启动方式
function checkArguments(){
console.log("plus.runtime.launcher: "+plus.runtime.launcher);
var args= plus.runtime.arguments;
if(args){
// 处理args参数,如打开新页面等
}
}
// 处理从后台恢复
document.addEventListener('newintent',function(){
console.log("addEventListener: newintent");
checkArguments();
},false);
收起阅读 »
mui开发H5+app——原生选择系统相册图片上传七牛云
```要完成用MUI 拍照和从系统相册选择图片上传的功能,可以理解成有三个功能
1 调用手机相机的功能(可以查看官方API http://www.html5plus.org/doc/zh_cn/camera.html)
2 调用系统相册的功能(可以查看官方API http://www.html5plus.org/doc/zh_cn/gallery.html)
3 照片资源上传到服务(可以查看官方API http://www.html5plus.org/doc/zh_cn/uploader.html)
完整实例
流程:获取七牛云token => 选择图片 => 上传图片 =>返回key。
代码如图:
```javascript
upImg: function() {
this.getToken(); //获取token
var _this = this;
console.log(_this.token);
// 从相册获取图片
plus.gallery.pick(function(ret) {
// 获取图片名称
var path = ret;
var file = ret.substr(ret.lastIndexOf("/") + 1);
var token = _this.token; // 填写你的七牛上传令牌
// 上传图片
var url = "http://upload-z2.qiniup.com";
document.getElementById('img').src = path;
this.ajaxUp(token, file, url, path);
});
}
一、获取七牛云token
此项目因使用七牛云,所以后端选择PHP的TP5框架。
1.将七牛云的第三方SDK放至tp5框架中,参考https://developer.qiniu.com/kodo/sdk/1241/php
2.配置AK和SK,写好后端接口
代码如图:
<?php
namespace app\index\controller;
下载sdk包解压并改名为qiniuyun,放在vendor目录下,引入qiniuyun目录下的autoload.php文件
require_once VENDOR_PATH . 'qiniuyun/autoload.php';
use think\Controller;
use \Qiniu\Auth;
/**
- 直接通过前端上传文件到七牛云储存空间(文件小于4MB)
- 上传token应先生成,并填写到上传表单的隐藏域,表单提交地址目前固定为:http://up-z2.qiniup.com
- <form method="post" action="http://up-z2.qiniup.com" enctype="multipart/form-data">
- <input name="token" type="hidden" value="上传token">
- <input name="file" type="file" />
- <input type="submit" value="上传"/>
- </form>
-
上传成功后会返回包含key的json数据,可根据该key生成文件的获取地址(地址存数据库)
*/
class Qiniuyun extends Controller
{
private $accessKey = '你的AK'; # accessKey
private $secretKey = '你的SK'; # secretKey
private $bucket = '你的空间'; # 存储空间名称
private $domain = '空间对应域名'; # 域名(与上面存储空间对应)
public $auth; # auth对象public function _initialize()
{
if (!$this->auth) {
$this->auth = new Auth($this->accessKey, $this->secretKey);
}
return $this->auth;
}/**
- 获取上传token
- @return string
*/
public function getToken()
{
return $this->auth->uploadToken($this->bucket);
}
/**
- 获取文件访问地址
- @param string $key 文件上传成功后返回的key
- @return string
*/
public function getUrl($key)
{
$baseUrl = 'http://' . $this->domain . '/' . $key;
return $this->auth->privateDownloadUrl($baseUrl);
}
}
前端请求后端接口获取token(请求开发者服务器)
代码如图:
/获取token凭证,上传前无凭证无法上传/
getToken: function() {
var _this = this;
mui.ajax('https://XXXXX/index/upload/getToken', {
data: {},
dataType: 'jsonp',
type: 'post',
timeout: '10000',
success: function(res) {
//此步骤打印出返回的token 观察是否存在双引号
_this.token = res.replace(/\"/g,"");//去双引号 (无双引号可省略)
console.log(res);
},
error: function(xhr, type, errorThrown) {
plus.nativeUI.toast('网络请求错误');
console.log(errorThrown);
}
});
}
3.请求七牛云服务器,上传图片
代码如图:
/**
- 上传图片
- @param token(str) 上传token 由七牛返回
- @param file(str) 文件名
- @param url(str) 请求路径
-
@param path(file) 文件对象
**/
ajaxUp: function(token, file, url, path) {
var _this = this;
var uploader = plus.uploader.createUpload(url, {
method: "POST"
}, function(up, state) {var res = JSON.parse(up.responseText); if(state == 200){ document.getElementById('imgUrl').value = _this.imgUrl+res.key; console.log("上传成功"+ res.key); } else{ console.log("上传失败 - " + state); } }); /** * * 上传参数addData * * 上传文件addFile * * 请勿将二者弄混 addFile上传的是文字对象 addData上传为字符串 * */ uploader.addData("key", file); uploader.addData("token", token); //添加上传参数 token必填 uploader.addFile(path, { "key": "file" }); // 固定值,千万不要修改 uploader.start(); }html部分
<!--这个是表单提交的方法-->
<!--<form method="post" action="http://up-z2.qiniup.com" enctype="multipart/form-data">
<input name="token" type="text" :value="token">
<input name="file" type="file" accept="image/*" @click="getToken()"/>
<input type="submit" value="上传"/>
</form>-->
<!--这个是调用原生接口的方法-->
<img class="my_img_class" width="100px" height="100px" @click="upImg" id="img" src=""/>
<p>
此input只做演示,实际应用时 input应为隐藏
<input type="text" name="imgUrl" id="imgUrl" value="" />
</p>
最后
通过七牛云上传图片后,将返回的key保存,然后获取对应的图片路径。
注意事项:
1.七牛云空间所在地区。七牛云空间所处地区不同,请求的URL也不一样,本人是华南的空间,因此路径为http://upload-z2.qiniup.com(是客户端路径不是服务器端路径)
2.H5+手机原生上传组件 addData与addFile的使用。上传的图片是对象,因此图片应使用addFile,但七牛云需要我们上传字段,所以上传的字段我们使用addData
3.返回的token。调试时请打印返回的token,观察token是否带有“”,有则去掉。否则接口会报401错误
结尾
本文为手机H5+APP开发中图片上传解决思路,并非最好的方法,仅列出常见问题,因系统差异问题,ios与安卓所遇问题不一定相同。
原文链接https://my.oschina.net/incess/blog/1818787
```要完成用MUI 拍照和从系统相册选择图片上传的功能,可以理解成有三个功能
1 调用手机相机的功能(可以查看官方API http://www.html5plus.org/doc/zh_cn/camera.html)
2 调用系统相册的功能(可以查看官方API http://www.html5plus.org/doc/zh_cn/gallery.html)
3 照片资源上传到服务(可以查看官方API http://www.html5plus.org/doc/zh_cn/uploader.html)
完整实例
流程:获取七牛云token => 选择图片 => 上传图片 =>返回key。
代码如图:
```javascript
upImg: function() {
this.getToken(); //获取token
var _this = this;
console.log(_this.token);
// 从相册获取图片
plus.gallery.pick(function(ret) {
// 获取图片名称
var path = ret;
var file = ret.substr(ret.lastIndexOf("/") + 1);
var token = _this.token; // 填写你的七牛上传令牌
// 上传图片
var url = "http://upload-z2.qiniup.com";
document.getElementById('img').src = path;
this.ajaxUp(token, file, url, path);
});
}
一、获取七牛云token
此项目因使用七牛云,所以后端选择PHP的TP5框架。
1.将七牛云的第三方SDK放至tp5框架中,参考https://developer.qiniu.com/kodo/sdk/1241/php
2.配置AK和SK,写好后端接口
代码如图:
<?php
namespace app\index\controller;
下载sdk包解压并改名为qiniuyun,放在vendor目录下,引入qiniuyun目录下的autoload.php文件
require_once VENDOR_PATH . 'qiniuyun/autoload.php';
use think\Controller;
use \Qiniu\Auth;
/**
- 直接通过前端上传文件到七牛云储存空间(文件小于4MB)
- 上传token应先生成,并填写到上传表单的隐藏域,表单提交地址目前固定为:http://up-z2.qiniup.com
- <form method="post" action="http://up-z2.qiniup.com" enctype="multipart/form-data">
- <input name="token" type="hidden" value="上传token">
- <input name="file" type="file" />
- <input type="submit" value="上传"/>
- </form>
-
上传成功后会返回包含key的json数据,可根据该key生成文件的获取地址(地址存数据库)
*/
class Qiniuyun extends Controller
{
private $accessKey = '你的AK'; # accessKey
private $secretKey = '你的SK'; # secretKey
private $bucket = '你的空间'; # 存储空间名称
private $domain = '空间对应域名'; # 域名(与上面存储空间对应)
public $auth; # auth对象public function _initialize()
{
if (!$this->auth) {
$this->auth = new Auth($this->accessKey, $this->secretKey);
}
return $this->auth;
}/**
- 获取上传token
- @return string
*/
public function getToken()
{
return $this->auth->uploadToken($this->bucket);
}
/**
- 获取文件访问地址
- @param string $key 文件上传成功后返回的key
- @return string
*/
public function getUrl($key)
{
$baseUrl = 'http://' . $this->domain . '/' . $key;
return $this->auth->privateDownloadUrl($baseUrl);
}
}
前端请求后端接口获取token(请求开发者服务器)
代码如图:
/获取token凭证,上传前无凭证无法上传/
getToken: function() {
var _this = this;
mui.ajax('https://XXXXX/index/upload/getToken', {
data: {},
dataType: 'jsonp',
type: 'post',
timeout: '10000',
success: function(res) {
//此步骤打印出返回的token 观察是否存在双引号
_this.token = res.replace(/\"/g,"");//去双引号 (无双引号可省略)
console.log(res);
},
error: function(xhr, type, errorThrown) {
plus.nativeUI.toast('网络请求错误');
console.log(errorThrown);
}
});
}
3.请求七牛云服务器,上传图片
代码如图:
/**
- 上传图片
- @param token(str) 上传token 由七牛返回
- @param file(str) 文件名
- @param url(str) 请求路径
-
@param path(file) 文件对象
**/
ajaxUp: function(token, file, url, path) {
var _this = this;
var uploader = plus.uploader.createUpload(url, {
method: "POST"
}, function(up, state) {var res = JSON.parse(up.responseText); if(state == 200){ document.getElementById('imgUrl').value = _this.imgUrl+res.key; console.log("上传成功"+ res.key); } else{ console.log("上传失败 - " + state); } }); /** * * 上传参数addData * * 上传文件addFile * * 请勿将二者弄混 addFile上传的是文字对象 addData上传为字符串 * */ uploader.addData("key", file); uploader.addData("token", token); //添加上传参数 token必填 uploader.addFile(path, { "key": "file" }); // 固定值,千万不要修改 uploader.start(); }html部分
<!--这个是表单提交的方法-->
<!--<form method="post" action="http://up-z2.qiniup.com" enctype="multipart/form-data">
<input name="token" type="text" :value="token">
<input name="file" type="file" accept="image/*" @click="getToken()"/>
<input type="submit" value="上传"/>
</form>-->
<!--这个是调用原生接口的方法-->
<img class="my_img_class" width="100px" height="100px" @click="upImg" id="img" src=""/>
<p>
此input只做演示,实际应用时 input应为隐藏
<input type="text" name="imgUrl" id="imgUrl" value="" />
</p>
最后
通过七牛云上传图片后,将返回的key保存,然后获取对应的图片路径。
注意事项:
1.七牛云空间所在地区。七牛云空间所处地区不同,请求的URL也不一样,本人是华南的空间,因此路径为http://upload-z2.qiniup.com(是客户端路径不是服务器端路径)
2.H5+手机原生上传组件 addData与addFile的使用。上传的图片是对象,因此图片应使用addFile,但七牛云需要我们上传字段,所以上传的字段我们使用addData
3.返回的token。调试时请打印返回的token,观察token是否带有“”,有则去掉。否则接口会报401错误
结尾
本文为手机H5+APP开发中图片上传解决思路,并非最好的方法,仅列出常见问题,因系统差异问题,ios与安卓所遇问题不一定相同。
原文链接https://my.oschina.net/incess/blog/1818787
请教大佬们一个问题,你们在布局的时候是怎么适配手机的刘海屏的啊
就是布局里面,有些是需要把一个元素贴在顶部显示的,或者需要距离顶部一些距离,
在小程序端我想到了一个方法就是获取小程序胶囊按钮的位置,然后通过胶囊按钮的top属性来适配,( wx.getMenuButtonBoundingClientRect() )这个属性
哪在app端或者h5端哪?这个有什么好的方法来适配的,大佬们,有没有好的方法分享一下
就是布局里面,有些是需要把一个元素贴在顶部显示的,或者需要距离顶部一些距离,
在小程序端我想到了一个方法就是获取小程序胶囊按钮的位置,然后通过胶囊按钮的top属性来适配,( wx.getMenuButtonBoundingClientRect() )这个属性
哪在app端或者h5端哪?这个有什么好的方法来适配的,大佬们,有没有好的方法分享一下
收起阅读 »如果在正式版1.9.4里面无法使用自定义组价编译模式或者在安卓机上面卡顿的 可以使用Alpha版 v1.9.7 亲测有效
如果在正式版1.9.4里面无法使用自定义组价编译模式或者在安卓机上面卡顿的 可以使用Alpha版 v1.9.7 亲测有效
如果在正式版1.9.4里面无法使用自定义组价编译模式或者在安卓机上面卡顿的 可以使用Alpha版 v1.9.7 亲测有效
真机运行总是卡在43%,其中一个可能
大概只有我遇到过吧,总是卡在43%,安装失败,找不到原因,后来发现它莫名其妙安装在了手机分身里,导致安装失败
大概只有我遇到过吧,总是卡在43%,安装失败,找不到原因,后来发现它莫名其妙安装在了手机分身里,导致安装失败
hubilder的代码块,官方文档实在看不懂。
hubilder的代码块,官方文档实在看不懂。百度出来的也是以前旧的代码块设置方法或者就是拷贝的现在的文档。
hubilder的代码块,官方文档实在看不懂。百度出来的也是以前旧的代码块设置方法或者就是拷贝的现在的文档。
HBuilderX:代码块说明及自定义代码块教程
本帖文档已集成到: hx产品文档
代码块是快速开发的利器。简单的敲几个字母,回车,就能生成大段代码。
比如我们经常会敲if...else结构,在HBuilderX中,只需敲ife回车,就能直接生成相应的代码结构。
- 敲ife
- 回车后生成if结构体
HBuilderX已经内置了大量常用的代码块,熟悉这些代码块,对于提高编程效率有重要帮助。
查看内建的代码块,点菜单-工具-代码块设置,选择你要查看的语言的代码块。
打开的界面中,左侧即是预置的代码块,右侧是开发者可以自己扩展代码块的地方。
常用代码块列表
通用js代码块
- iff :简单if
- forr :for循环结构体
- fori :for循环结构体并包含i
- funn:函数
- funa:匿名函数
- clog:打印日志
- clogvar:打印变量命名和值
dom代码块
- dg :document.getElementById
- dl :$("")
vue代码块
敲v,即可拉出各种vue代码块
uni-app代码块
敲u,即可拉出各种uni-app代码块
还有ifios、ifandroid,这2个平台判断代码块(HBuilderX 1.9.10+)
模板示例
自定义代码块都是配置json文件中的,直接来一个js例子吧,上述ife代码块的配置如下:
{
"if ... else": {
"body": [
"if ($1) {",
"\t$0",
"} else{",
"\t",
"}"
],
"prefix": "ife",
"scope": "source.js"
}
}
代码块配置格式说明
HBuilderX使用json定义代码块的格式,兼容vscode的代码块格式,也就是你可以把vscode里已经配置的自定义代码块方便的挪到HBuilderX中使用。
每个配置项的说明如下:
key
"key" :代码块显示名称,显示在代码助手列表中的名字。key是不能重复的。
上面例子中"if ... else"就是一个key。
prefix
"prefix" :代码块的触发字符,就是敲什么字母可以激活这个代码块。
body
"body" :代码块的内容。内容中有如下特殊格式
$1 表示代码块输入后光标的所在位置。如需要多光标,就在多个地方配置$1;如该位置有预置数据且需要选中,则写法是${1:selectedtext};这里还支持下拉候选菜单,多选项即下拉候选列表使用${1:foo1/foo2/foo3}
$2 表示代码块输入后再次按tab后光标的切换位置tabstops(代码块展开后按tab可以跳到下一个tabstop,在HBuilderX中看到类似绿色光标的不闪的竖线,就可以按tab或回车跳转光标过去)
$0代表代码块输入后最终光标的所在位置(也可以按回车直接跳过去)。
双引号使用\"转义
换行使用多个数组表示,每个行一个数组,用双引号包围,并用逗号分隔
缩进需要用\t表示,不能直接输入缩进或空格!
triggerAssist
"triggerAssist" :为true表示该代码块输入到文档后立即在第一个tabstop上触发代码提示,拉出代码助手,默认为false。
project
project: 将代码块控制在指定项目类型下生效。可取值有:uni-app、Web、App、Wap2App
比如:"project": "uni-app",代表这个代码块仅在uni-app项目下生效
如果不设置,则该代码块在所有项目类型下均生效。
Web指普通项目,App指5+App项目。
如需设置多种项目类型,用逗号分隔。比如:"project": "uni-app,App"
注意事项
- 每个代码块以
key为主键,多个代码块需要逗号分隔。 - 如果json语法不合法,编辑器状态栏会弹出错误信息,json中会画出红波浪线,请注意修正。
本帖文档已集成到: hx产品文档
代码块是快速开发的利器。简单的敲几个字母,回车,就能生成大段代码。
比如我们经常会敲if...else结构,在HBuilderX中,只需敲ife回车,就能直接生成相应的代码结构。
- 敲ife
- 回车后生成if结构体
HBuilderX已经内置了大量常用的代码块,熟悉这些代码块,对于提高编程效率有重要帮助。
查看内建的代码块,点菜单-工具-代码块设置,选择你要查看的语言的代码块。
打开的界面中,左侧即是预置的代码块,右侧是开发者可以自己扩展代码块的地方。
常用代码块列表
通用js代码块
- iff :简单if
- forr :for循环结构体
- fori :for循环结构体并包含i
- funn:函数
- funa:匿名函数
- clog:打印日志
- clogvar:打印变量命名和值
dom代码块
- dg :document.getElementById
- dl :$("")
vue代码块
敲v,即可拉出各种vue代码块
uni-app代码块
敲u,即可拉出各种uni-app代码块
还有ifios、ifandroid,这2个平台判断代码块(HBuilderX 1.9.10+)
模板示例
自定义代码块都是配置json文件中的,直接来一个js例子吧,上述ife代码块的配置如下:
{
"if ... else": {
"body": [
"if ($1) {",
"\t$0",
"} else{",
"\t",
"}"
],
"prefix": "ife",
"scope": "source.js"
}
}
代码块配置格式说明
HBuilderX使用json定义代码块的格式,兼容vscode的代码块格式,也就是你可以把vscode里已经配置的自定义代码块方便的挪到HBuilderX中使用。
每个配置项的说明如下:
key
"key" :代码块显示名称,显示在代码助手列表中的名字。key是不能重复的。
上面例子中"if ... else"就是一个key。
prefix
"prefix" :代码块的触发字符,就是敲什么字母可以激活这个代码块。
body
"body" :代码块的内容。内容中有如下特殊格式
$1 表示代码块输入后光标的所在位置。如需要多光标,就在多个地方配置$1;如该位置有预置数据且需要选中,则写法是${1:selectedtext};这里还支持下拉候选菜单,多选项即下拉候选列表使用${1:foo1/foo2/foo3}
$2 表示代码块输入后再次按tab后光标的切换位置tabstops(代码块展开后按tab可以跳到下一个tabstop,在HBuilderX中看到类似绿色光标的不闪的竖线,就可以按tab或回车跳转光标过去)
$0代表代码块输入后最终光标的所在位置(也可以按回车直接跳过去)。
双引号使用\"转义
换行使用多个数组表示,每个行一个数组,用双引号包围,并用逗号分隔
缩进需要用\t表示,不能直接输入缩进或空格!
triggerAssist
"triggerAssist" :为true表示该代码块输入到文档后立即在第一个tabstop上触发代码提示,拉出代码助手,默认为false。
project
project: 将代码块控制在指定项目类型下生效。可取值有:uni-app、Web、App、Wap2App
比如:"project": "uni-app",代表这个代码块仅在uni-app项目下生效
如果不设置,则该代码块在所有项目类型下均生效。
Web指普通项目,App指5+App项目。
如需设置多种项目类型,用逗号分隔。比如:"project": "uni-app,App"
注意事项
- 每个代码块以
key为主键,多个代码块需要逗号分隔。 - 如果json语法不合法,编辑器状态栏会弹出错误信息,json中会画出红波浪线,请注意修正。
分享一个Andorid手机插入一个日程事件
实现功能:
- 建立自己的账户,每次插入日历都使用自己的账户,区分第三方日历账户与系统日历账户
- 实现建立的日历删除
- 实现2次闹钟提醒,(addcalendar中的参数 fr, tr的值必须为分钟数字,比如:你的闹钟设置是1个小时提醒,输入的参数必须是60)
mui.plusReady(function() {
if(mui.os.ios) {
} else {
var calanderURL = 'content://com.android.calendar/calendars',
eventsURL = 'content://com.android.calendar/events',
ContentValues = plus.android.importClass("android.content.ContentValues"),
Uri = plus.android.importClass('android.net.Uri'),
ContentUris = plus.android.importClass('android.content.ContentUris'),
Calendar = plus.android.importClass('java.util.Calendar'),
main = plus.android.runtimeMainActivity(),
userCursor = plus.android.invoke(main.getContentResolver(), 'query', Uri.parse(calanderURL), null, null, null, null),
userCursor_count = plus.android.invoke(userCursor, 'getCount'),
TimeZone = plus.android.importClass('java.util.TimeZone'),
TimeZone_str = plus.android.invoke(TimeZone.getDefault(), 'getID');
}
//Nid参数为数据库中的一个id,可以不用,我用这个Nid实现与手机系统的日历事件id进行关联
addcalendar = function(Nid, title, description, date_str, etime, fr, tr) {
if(userCursor_count <= 0) { //如果没有日历账户
addcalendaraccount();
userCursor = plus.android.invoke(main.getContentResolver(), 'query', Uri.parse(calanderURL), null, null, null, null);
userCursor_count++;
}
plus.android.invoke(userCursor, 'moveToFirst');//第一个
//plus.android.invoke(userCursor, 'moveToLast');//最后一个
//plus.android.invoke(userCursor, 'moveToNext');//下一个
for(var i = 0; i < userCursor_count; i++) {
var calName = plus.android.invoke(userCursor, 'getString', plus.android.invoke(userCursor, 'getColumnIndex', 'calendar_displayName'));
//获得日历的描述名称
if(calName == "OA日历") {
break;
}
if(i == (userCursor_count - 1)) {
addcalendaraccount();
userCursor = plus.android.invoke(main.getContentResolver(), 'query', Uri.parse(calanderURL), null, null, null, null);
userCursor_count++;
}
plus.android.invoke(userCursor, 'moveToNext');
}
try {
var calId = plus.android.invoke(userCursor, 'getString', plus.android.invoke(userCursor, 'getColumnIndex', '_id')),
events = new ContentValues(),
mCalendar = Calendar.getInstance(),
date = date_str.split(/\s{1}|:|-/g);
plus.android.invoke(mCalendar, 'set', Calendar.YEAR, ~~date[0]);
plus.android.invoke(mCalendar, 'set', Calendar.MONTH, ((~~date[1]) - 1));
plus.android.invoke(mCalendar, 'set', Calendar.DATE, ~~date[2]);
plus.android.invoke(mCalendar, 'set', Calendar.HOUR_OF_DAY, ~~date[3]);
plus.android.invoke(mCalendar, 'set', Calendar.MINUTE, ~~date[4]);
var start = plus.android.invoke(plus.android.invoke(mCalendar, 'getTime'), 'getTime');
//设置日历事件
var etimestamp = new Date(etime.replace(/-/g, "\/")).getTime();//时间可以用传入参数的模式
events.put('title', title);
events.put('description', description);
events.put('calendar_id', calId);
events.put('dtstart', start);
events.put('dtend', etimestamp);
//events.put('ALL_DAY', 0); //值为 1 表示此事件占用一整天(按照本地时区的定义)。 值为 0 表示它是常规事件,可在一天内的任何时间开始和结束。
//events.put('RRULE')
events.put('hasAlarm', 1);
events.put('eventTimezone', TimeZone_str);
var newEvent = plus.android.invoke(main.getContentResolver(), 'insert', Uri.parse('content://com.android.calendar/events'), events);
var id = plus.android.invoke(newEvent, 'getLastPathSegment');
if(fr.length > 0) {
var values = new ContentValues();
values.put('event_id', id);
values.put('minutes', fr);
values.put('method', '1');
plus.android.invoke(main.getContentResolver(), 'insert', Uri.parse('content://com.android.calendar/reminders'), values);
}
if(tr.length > 0) {
var values2 = new ContentValues();
values2.put('event_id', id);
values2.put('minutes', tr);
values2.put('method', '1');
plus.android.invoke(main.getContentResolver(), 'insert', Uri.parse('content://com.android.calendar/reminders'), values2);
}
//SaveCalendID(id, Nid, callSetProRmData); 把插入日历的id保存起来,便于删除调用
//也可以用于更新(先删后插入);
} catch(e) {
mui.alert("您没有允许APP访问日历的权限");
}
}
deletecalendar = function(eventID) {
if(userCursor_count <= 0) { //如果没有日历账户
addcalendaraccount();
}
var id = Number(eventID);
//alert(id);
var deleteUri = ContentUris.withAppendedId(Uri.parse(eventsURL), id);
var rows = plus.android.invoke(main.getContentResolver(), "delete", deleteUri, null, null);
if(rows == -1) {
return;
}
}
addcalendaraccount = function() {
var account = new ContentValues(),
buildUpon = plus.android.invoke(Uri.parse(calanderURL), 'buildUpon'),
CalendarContract = plus.android.importClass('android.provider.CalendarContract');
plus.android.invoke(buildUpon, 'appendQueryParameter', CalendarContract.CALLER_IS_SYNCADAPTER, 'true');
plus.android.invoke(buildUpon, 'appendQueryParameter', 'account_name', 'OA@xxx.com.com');
plus.android.invoke(buildUpon, 'appendQueryParameter', 'account_type', 'com.android.exchange');
//设置账户信息
account.put('name', 'OAAppAdmin');
account.put('account_name', 'OA@xxx.com.com');
account.put('account_type', 'com.android.exchange');
account.put('calendar_displayName', 'OA日历');
account.put('visible', 1);
account.put('calendar_color', '-9206951');
account.put('calendar_access_level', '700');
account.put('sync_events', 1);
account.put('calendar_timezone', TimeZone_str);
account.put('ownerAccount', 'OA@xxx.com.com');
account.put('canOrganizerRespond', 0);
//保存账户信息
plus.android.invoke(main.getContentResolver(), 'insert', plus.android.invoke(buildUpon, 'build'), account);
}
}); 实现功能:
- 建立自己的账户,每次插入日历都使用自己的账户,区分第三方日历账户与系统日历账户
- 实现建立的日历删除
- 实现2次闹钟提醒,(addcalendar中的参数 fr, tr的值必须为分钟数字,比如:你的闹钟设置是1个小时提醒,输入的参数必须是60)
mui.plusReady(function() {
if(mui.os.ios) {
} else {
var calanderURL = 'content://com.android.calendar/calendars',
eventsURL = 'content://com.android.calendar/events',
ContentValues = plus.android.importClass("android.content.ContentValues"),
Uri = plus.android.importClass('android.net.Uri'),
ContentUris = plus.android.importClass('android.content.ContentUris'),
Calendar = plus.android.importClass('java.util.Calendar'),
main = plus.android.runtimeMainActivity(),
userCursor = plus.android.invoke(main.getContentResolver(), 'query', Uri.parse(calanderURL), null, null, null, null),
userCursor_count = plus.android.invoke(userCursor, 'getCount'),
TimeZone = plus.android.importClass('java.util.TimeZone'),
TimeZone_str = plus.android.invoke(TimeZone.getDefault(), 'getID');
}
//Nid参数为数据库中的一个id,可以不用,我用这个Nid实现与手机系统的日历事件id进行关联
addcalendar = function(Nid, title, description, date_str, etime, fr, tr) {
if(userCursor_count <= 0) { //如果没有日历账户
addcalendaraccount();
userCursor = plus.android.invoke(main.getContentResolver(), 'query', Uri.parse(calanderURL), null, null, null, null);
userCursor_count++;
}
plus.android.invoke(userCursor, 'moveToFirst');//第一个
//plus.android.invoke(userCursor, 'moveToLast');//最后一个
//plus.android.invoke(userCursor, 'moveToNext');//下一个
for(var i = 0; i < userCursor_count; i++) {
var calName = plus.android.invoke(userCursor, 'getString', plus.android.invoke(userCursor, 'getColumnIndex', 'calendar_displayName'));
//获得日历的描述名称
if(calName == "OA日历") {
break;
}
if(i == (userCursor_count - 1)) {
addcalendaraccount();
userCursor = plus.android.invoke(main.getContentResolver(), 'query', Uri.parse(calanderURL), null, null, null, null);
userCursor_count++;
}
plus.android.invoke(userCursor, 'moveToNext');
}
try {
var calId = plus.android.invoke(userCursor, 'getString', plus.android.invoke(userCursor, 'getColumnIndex', '_id')),
events = new ContentValues(),
mCalendar = Calendar.getInstance(),
date = date_str.split(/\s{1}|:|-/g);
plus.android.invoke(mCalendar, 'set', Calendar.YEAR, ~~date[0]);
plus.android.invoke(mCalendar, 'set', Calendar.MONTH, ((~~date[1]) - 1));
plus.android.invoke(mCalendar, 'set', Calendar.DATE, ~~date[2]);
plus.android.invoke(mCalendar, 'set', Calendar.HOUR_OF_DAY, ~~date[3]);
plus.android.invoke(mCalendar, 'set', Calendar.MINUTE, ~~date[4]);
var start = plus.android.invoke(plus.android.invoke(mCalendar, 'getTime'), 'getTime');
//设置日历事件
var etimestamp = new Date(etime.replace(/-/g, "\/")).getTime();//时间可以用传入参数的模式
events.put('title', title);
events.put('description', description);
events.put('calendar_id', calId);
events.put('dtstart', start);
events.put('dtend', etimestamp);
//events.put('ALL_DAY', 0); //值为 1 表示此事件占用一整天(按照本地时区的定义)。 值为 0 表示它是常规事件,可在一天内的任何时间开始和结束。
//events.put('RRULE')
events.put('hasAlarm', 1);
events.put('eventTimezone', TimeZone_str);
var newEvent = plus.android.invoke(main.getContentResolver(), 'insert', Uri.parse('content://com.android.calendar/events'), events);
var id = plus.android.invoke(newEvent, 'getLastPathSegment');
if(fr.length > 0) {
var values = new ContentValues();
values.put('event_id', id);
values.put('minutes', fr);
values.put('method', '1');
plus.android.invoke(main.getContentResolver(), 'insert', Uri.parse('content://com.android.calendar/reminders'), values);
}
if(tr.length > 0) {
var values2 = new ContentValues();
values2.put('event_id', id);
values2.put('minutes', tr);
values2.put('method', '1');
plus.android.invoke(main.getContentResolver(), 'insert', Uri.parse('content://com.android.calendar/reminders'), values2);
}
//SaveCalendID(id, Nid, callSetProRmData); 把插入日历的id保存起来,便于删除调用
//也可以用于更新(先删后插入);
} catch(e) {
mui.alert("您没有允许APP访问日历的权限");
}
}
deletecalendar = function(eventID) {
if(userCursor_count <= 0) { //如果没有日历账户
addcalendaraccount();
}
var id = Number(eventID);
//alert(id);
var deleteUri = ContentUris.withAppendedId(Uri.parse(eventsURL), id);
var rows = plus.android.invoke(main.getContentResolver(), "delete", deleteUri, null, null);
if(rows == -1) {
return;
}
}
addcalendaraccount = function() {
var account = new ContentValues(),
buildUpon = plus.android.invoke(Uri.parse(calanderURL), 'buildUpon'),
CalendarContract = plus.android.importClass('android.provider.CalendarContract');
plus.android.invoke(buildUpon, 'appendQueryParameter', CalendarContract.CALLER_IS_SYNCADAPTER, 'true');
plus.android.invoke(buildUpon, 'appendQueryParameter', 'account_name', 'OA@xxx.com.com');
plus.android.invoke(buildUpon, 'appendQueryParameter', 'account_type', 'com.android.exchange');
//设置账户信息
account.put('name', 'OAAppAdmin');
account.put('account_name', 'OA@xxx.com.com');
account.put('account_type', 'com.android.exchange');
account.put('calendar_displayName', 'OA日历');
account.put('visible', 1);
account.put('calendar_color', '-9206951');
account.put('calendar_access_level', '700');
account.put('sync_events', 1);
account.put('calendar_timezone', TimeZone_str);
account.put('ownerAccount', 'OA@xxx.com.com');
account.put('canOrganizerRespond', 0);
//保存账户信息
plus.android.invoke(main.getContentResolver(), 'insert', plus.android.invoke(buildUpon, 'build'), account);
}
}); 收起阅读 »






















