提交 6d7abbc9 编写于 作者: M mehaotian

Merge branch 'dev' of https://github.com/dcloudio/uni-app into dev

* 'dev' of https://github.com/dcloudio/uni-app: (62 commits)
  fix(App): 修改特定分辨率(iPhone12 Pro)下文字换行错误的问题 question/114636
  fix: 华为快应用IDE V3.0.2+无法导入项目的问题
  fix: 修复 picker 组件特点情况下设置 start、end 表现异常的问题 question/114223
  update: unicloud-db组件增加属性startwith limitlevel
  update: unicloud-db组件新增gettree属性
  docs: 增加 onInit 生命周期说明
  feat(mp): mp-baidu onInit close #2197
  docs: 更新 uni.saveImageToPhotosAlbum 文档
  feat(App): uni.saveImageToPhotosAlbum 支持返回保存路径
  feat(cli): ignored *.md
  fix(App): v-for recursion
  fix(uniCloud): 修复调试时较早请求云函数且无法连接本地调试服务时报错的Bug
  fix(App): nvue 支持更多简写样式:border、border-top、border-right、border-bottom、border-left、border-style、border-width、border-color、border-radius、flex-flow、font、background
  docs(subPackages): 添加字节小程序分包支持文档
  fix: unicloud-db 组件在微信小程序上出错的问题
  update: unicloud-db getone 优先 page-data
  fix(App): manifest 支持全屏配置
  fix: <unicloud-db> H5平台开发环境下 属性:getone="true"时报错的问题
  fix(docs): preloadRule文档错误修改
  feat: 字节跳动支持分包加载
  ...
......@@ -220,6 +220,7 @@ function async request () {
|:-|:-|
|[uni.getNetworkType](api/system/network?id=getnetworktype)|获取网络类型|
|[uni.onNetworkStatusChange](api/system/network?id=onnetworkstatuschange)|监听网络状态变化|
|[uni.offNetworkStatusChange](api/system/network?id=offnetworkstatuschange)|取消监听网络状态变化|
##### 加速度计
|API|说明|
......
......@@ -166,3 +166,64 @@ editor 组件对应的 editorContext 实例,可通过 [uni.createSelectorQuery
| success | Function | | 否 | 接口调用成功的回调函数 |
| fail | Function | | 否 | 接口调用失败的回调函数 |
| complete | Function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## editorContext.blur(OBJECT)
编辑器失焦,同时收起键盘。
**平台差异说明**
|App|H5|微信小程序|支付宝小程序|百度小程序|字节跳动小程序|QQ小程序|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|√`HBuilderX 3.0.3`|√`HBuilderX 3.0.3`|√`基础库2.8.3`|x|x|x|x|
**OBJECT 参数说明**
| 属性 | 类型 | 默认值 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| success | Function | | 否 | 接口调用成功的回调函数 |
| fail | Function | | 否 | 接口调用失败的回调函数 |
| complete | Function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## editorContext.scrollIntoView(OBJECT)
使得编辑器光标处滚动到窗口可视区域内。
**平台差异说明**
|App|H5|微信小程序|支付宝小程序|百度小程序|字节跳动小程序|QQ小程序|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|√`HBuilderX 3.0.3`|√`HBuilderX 3.0.3`|√`基础库2.8.3`|x|x|x|x|
**OBJECT 参数说明**
| 属性 | 类型 | 默认值 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| success | Function | | 否 | 接口调用成功的回调函数 |
| fail | Function | | 否 | 接口调用失败的回调函数 |
| complete | Function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
## editorContext.getSelectionText(OBJECT)
获取编辑器已选区域内的纯文本内容。当编辑器失焦或未选中一段区间时,返回内容为空。
**平台差异说明**
|App|H5|微信小程序|支付宝小程序|百度小程序|字节跳动小程序|QQ小程序|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|√`HBuilderX 3.0.3`|√`HBuilderX 3.0.3`|√`基础库2.10.2`|x|x|x|x|
**OBJECT 参数说明**
| 属性 | 类型 | 默认值 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| success | Function | | 否 | 接口调用成功的回调函数 |
| fail | Function | | 否 | 接口调用失败的回调函数 |
| complete | Function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
**success 返回参数说明:**
|参数|类型|说明|
|:-|:-|:-|
|errMsg|String|接口调用结果|
|text|String|纯文本内容|
\ No newline at end of file
......@@ -220,6 +220,7 @@ uni.chooseImage({
|参数名|类型|说明|
|:-|:-|:-|
|path|String|保存到相册的图片路径,仅 App 3.0.5+ 支持|
|errMsg|String|调用结果|
**注意**
......@@ -260,8 +261,8 @@ uni.chooseImage({
| :- | :- | :- | :- | :- | :- |
| src | String | | 是 | 图片路径,图片的路径,可以是相对路径、临时文件路径、存储文件路径 ||
| quality | Number | 80 | 否 | 压缩质量,范围0~100,数值越小,质量越低,压缩率越高(仅对jpg有效) ||
| width | String | auto | 否 | 缩放图片的宽度,支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即根据height与源图高的缩放比例计算,若未设置height则使用源图高度)|App 2.9.11+|
| height | String | auto | 否 | 缩放图片的高度,支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即根据height与源图高的缩放比例计算,若未设置height则使用源图高度)|App 2.9.11+|
| width | String | auto | 否 | 缩放图片的宽度,支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即根据height与源图高的缩放比例计算,若未设置height则使用源图高度)|App 3.0.0+|
| height | String | auto | 否 | 缩放图片的高度,支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即根据height与源图高的缩放比例计算,若未设置height则使用源图高度)|App 3.0.0+|
| success | Function | | 否 | 接口调用成功的回调函数 ||
| fail | Function | | 否 | 接口调用失败的回调函数 ||
| complete | Function | | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) ||
......
......@@ -19,7 +19,7 @@ H5平台登陆注意事项:
|provider|String|否|登录服务提供商,通过 [uni.getProvider](/api/plugins/provider) 获取,如果不设置则弹出登录列表选择界面||
|scopes|String/Array|见平台差异说明|授权类型,默认 auth_base。支持 auth_base(静默授权)/ auth_user(主动授权) / auth_zhima(芝麻信用)|支付宝小程序|
|timeout|Number|否|超时时间,单位ms|微信小程序、百度小程序|
|univerifyStyle|Object|否|[一键登录](https://ask.dcloud.net.cn/article/38009)页面样式|App 2.9.11+|
|univerifyStyle|Object|否|[一键登录](/univerify)页面样式|App 3.0.0+|
|success|Function|否|接口调用成功的回调||
|fail|Function|否|接口调用失败的回调函数||
|complete|Function|否|接口调用结束的回调函数(调用成功、失败都会执行)|&nbsp;|
......@@ -39,7 +39,7 @@ H5平台登陆注意事项:
* [百度小程序登录](https://smartprogram.baidu.com/docs/develop/api/open_log/#%E6%8E%88%E6%9D%83%E6%B5%81%E7%A8%8B%E8%AF%B4%E6%98%8E/)
* [字节跳动小程序登录](https://developer.toutiao.com/dev/cn/mini-app/develop/open-capacity/log-in/login)
* [Apple登录、苹果登录、Sign in with Apple](https://ask.dcloud.net.cn/article/36651)
* [一键登陆](https://ask.dcloud.net.cn/article/38009)
* [一键登陆](/univerify)
**示例**
......@@ -169,23 +169,23 @@ uni.login({
|App|H5|微信小程序|支付宝小程序|百度小程序|字节跳动小程序|QQ小程序|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|2.9.11+|x|x|x|x|x|x|
|3.0.0+|x|x|x|x|x|x|
**OBJECT 参数说明**
|参数名|类型|必填|说明|
|:-|:-|:-|:-|
|provider|String|否|登录服务提供商,通过 [uni.getProvider](/api/plugins/provider) 获取,目前仅支持[一键登陆](https://ask.dcloud.net.cn/article/38009)|
|provider|String|否|登录服务提供商,通过 [uni.getProvider](/api/plugins/provider) 获取,目前仅支持[一键登陆](/univerify)|
|success|Function|否|接口调用成功的回调|
|fail|Function|否|接口调用失败的回调函数|
|complete|Function|否|接口调用结束的回调函数(调用成功、失败都会执行)|
### uni.closeAuthView()
关闭[一键登陆](https://ask.dcloud.net.cn/article/38009)页面。
关闭[一键登陆](/univerify)页面。
**平台差异说明**
|App|H5|微信小程序|支付宝小程序|百度小程序|字节跳动小程序|QQ小程序|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|2.9.11+|x|x|x|x|x|x|
|3.0.0+|x|x|x|x|x|x|
......@@ -46,7 +46,7 @@
||qq|QQ登录||
||sinaweibo|新浪微博登录||
||xiaomi|小米登录||
||univerify|[一键登录](https://ask.dcloud.net.cn/article/38009)|App 2.9.11+|
||univerify|[一键登录](/univerify)|App 3.0.0+|
||apple|[Apple登录](https://ask.dcloud.net.cn/article/36651)|仅iOS13支持,App 2.4.7+|
|share|sinaweibo|新浪微博分享||
||qq|分享到QQ好友||
......
......@@ -27,6 +27,9 @@ uni.onCompassChange(function (res) {
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|HBuilderX 2.9.6+|HBuilderX 2.9.6+|基础库 2.9.3+|x|x|x|x|
**Tips**
- `CALLBACK`为调用`uni.onCompassChange`时传入的`CALLBACK`
### uni.startCompass(OBJECT)
开始监听罗盘数据。
......
......@@ -38,7 +38,7 @@ uni.getNetworkType({
```
### uni.onNetworkStatusChange(CALLBACK)
监听网络状态变化。
监听网络状态变化。可使用`uni.offNetworkStatusChange`取消监听。
**CALLBACK 返回参数**
......@@ -54,4 +54,15 @@ uni.onNetworkStatusChange(function (res) {
console.log(res.isConnected);
console.log(res.networkType);
});
```
\ No newline at end of file
```
### uni.offNetworkStatusChange(CALLBACK)
取消监听网络状态变化。
**平台差异说明**
|App|H5|微信小程序|支付宝小程序|百度小程序|字节跳动小程序|QQ小程序|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|HBuilderX 3.0.1+|HBuilderX 3.0.1+|基础库 2.9.3+|x|x|x|x|
**Tips**
- `CALLBACK`为调用`uni.onNetworkStatusChange`时传入的`CALLBACK`
......@@ -41,6 +41,7 @@
|函数名|说明|平台差异说明|最低版本|
|:-|:-|:-|:-|
|onInit|监听页面初始化,其参数同 onLoad 参数,为上个页面传递的数据,参数类型为Object(用于页面传参)|百度小程序|3.0.5+|
|onLoad|监听页面加载,其参数为上个页面传递的数据,参数类型为Object(用于页面传参),参考[示例](/api/router?id=navigateto)|||
|onShow|监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面|||
|onReady|监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发|||
......@@ -60,6 +61,11 @@
|onShareTimeline|监听用户点击右上角转发到朋友圈|微信小程序|2.8.1+|
|onAddToFavorites|监听用户点击右上角收藏|微信小程序|2.8.1+|
``onInit``使用注意
- 仅百度小程序基础库 3.260 以上支持 onInit 生命周期,如百度开发者工具基础库版本过低可使用真机进行测试。
- onInit 生命周期早于 beforeCreate 生命周期,如需访问 Vue 实例的数据对象,请在 created 生命周期内访问。
- 当支持 onInit 生命周期时 Vue 实例会较早创建,故一般情况可使用 created 生命周期替代 onInit 生命周期。
``onReachBottom``使用注意
可在pages.json里定义具体页面底部的触发距离[onReachBottomDistance](/collocation/pages),比如设为50,那么滚动页面到距离底部50px时,就会触发onReachBottom事件。
......
......@@ -478,7 +478,7 @@ mp-qq只支持自定义组件模式,不存在usingComponents配置
### 关于分包优化的说明
- 在对应平台的配置下添加`"optimization":{"subPackages":true}`开启分包优化
- 目前只支持`mp-weixin``mp-qq``mp-baidu`的分包优化
- 目前只支持`mp-weixin``mp-qq``mp-baidu``mp-toutiao`的分包优化
- 分包优化具体逻辑:
+ 静态文件:分包下支持 static 等静态资源拷贝,即分包目录内放置的静态资源不会被打包到主包中,也不可在主包中使用
+ js文件:当某个 js 仅被一个分包引用时,该 js 会被打包到该分包内,否则仍打到主包(即被主包引用,或被超过 1 个分包引用)
......
......@@ -911,15 +911,15 @@ h5 平台下拉刷新动画,只有 circle 类型。
|color|HexColor|是||tab 上的文字默认颜色||
|selectedColor|HexColor|是||tab 上的文字选中时的颜色||
|backgroundColor|HexColor|是||tab 的背景色||
|borderStyle|String|否|black|tabbar 上边框的颜色,可选值 black/white|App 2.3.4+ 支持其他颜色值、H5(HBuilder X 2.9.11+)|
|blurEffect|String|否|none|iOS 高斯模糊效果,可选值 dark/extralight/light/none(参考:[使用说明](https://ask.dcloud.net.cn/article/36617))|App 2.4.0+ 支持、H5(HBuilder X 2.9.11+,只有最新版浏览器才支持)|
|borderStyle|String|否|black|tabbar 上边框的颜色,可选值 black/white|App 2.3.4+ 支持其他颜色值、H5 3.0.0+|
|blurEffect|String|否|none|iOS 高斯模糊效果,可选值 dark/extralight/light/none(参考:[使用说明](https://ask.dcloud.net.cn/article/36617))|App 2.4.0+ 支持、H5 3.0.0+(只有最新版浏览器才支持)|
|list|Array|是||tab 的列表,详见 list 属性说明,最少2个、最多5个 tab||
|position|String|否|bottom|可选值 bottom、top|top 值仅微信小程序支持|
|fontSize|String|否|10px|文字默认大小|App 2.3.4+、H5(HBuilder X 2.9.11+)|
|iconWidth|String|否|24px|图标默认宽度(高度等比例缩放)|App 2.3.4+、H5(HBuilder X 2.9.11+)|
|spacing|String|否|3px|图标和文字的间距|App 2.3.4+、H5(HBuilder X 2.9.11+)|
|height|String|否|50px|tabBar 默认高度|App 2.3.4+、H5(HBuilder X 2.9.11+)|
|midButton|Object|否||中间按钮 仅在 list 项为偶数时有效|App 2.3.4+、H5(HBuilder X 2.9.11+)|
|fontSize|String|否|10px|文字默认大小|App 2.3.4+、H5 3.0.0+|
|iconWidth|String|否|24px|图标默认宽度(高度等比例缩放)|App 2.3.4+、H5 3.0.0+|
|spacing|String|否|3px|图标和文字的间距|App 2.3.4+、H5 3.0.0+|
|height|String|否|50px|tabBar 默认高度|App 2.3.4+、H5 3.0.0+|
|midButton|Object|否||中间按钮 仅在 list 项为偶数时有效|App 2.3.4+、H5 3.0.0+|
其中 list 接收一个数组,数组中的每个项都是一个对象,其属性值如下:
......@@ -1047,7 +1047,7 @@ subPackages 节点接收一个数组,数组每一项都是应用的子包,
- 支付宝小程序每个分包的大小是2M,总体积一共不能超过4M。
- QQ小程序每个分包的大小是2M,总体积一共不能超过24M。
- 分包下支持独立的 ```static``` 目录,用来对静态资源进行分包。
- `uni-app`内支持对微信小程序、QQ小程序、百度小程序分包优化,即将静态资源或者js文件放入分包内不占用主包大小。详情请参考:[关于分包优化的说明](/collocation/manifest?id=关于分包优化的说明)
- `uni-app`内支持对`微信小程序``QQ小程序``百度小程序``字节小程序(HBuilderX 3.0.3+)`分包优化,即将静态资源或者js文件放入分包内不占用主包大小。详情请参考:[关于分包优化的说明](/collocation/manifest?id=关于分包优化的说明)
- 针对`vendor.js`过大的情况可以使用运行时压缩代码
+ `HBuilderX`创建的项目勾选`运行-->运行到小程序模拟器-->运行时是否压缩代码`
+ `cli`创建的项目可以在`pacakge.json`中添加参数`--minimize`,示例:`"dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize"`
......@@ -1125,7 +1125,7 @@ subPackages 节点接收一个数组,数组每一项都是应用的子包,
|字段|类型|必填|默认值|说明|
|---|---|---|---|---|
|packages|StringArray |是|无|进入页面后预下载分包的 root 或 name。__APP__ 表示主包。|
|packages|StringArray |是|无|进入页面后预下载分包的 `root``name``__APP__` 表示主包。|
|network|String|否 |wifi|在指定网络下预下载,可选值为:all(不限网络)、wifi(仅wifi下预下载)|
app的分包,同样支持preloadRule,但网络规则无效。
......
......@@ -23,7 +23,7 @@
|selection-end|Number|-1|光标结束位置,自动聚集时有效,需与selection-start搭配使用||
|adjust-position|Boolean|true|键盘弹起时,是否自动上推页面|App-Android(vue 页面 softinputMode 为 adjustResize 时无效)、微信小程序、百度小程序、QQ小程序|
|hold-keyboard|boolean|false|focus时,点击页面的时候不收起键盘|微信小程序2.8.2|
|auto-blur|boolean|false|键盘收起时,是否自动失去焦点|APP(HBuilder x2.9.11)|
|auto-blur|boolean|false|键盘收起时,是否自动失去焦点|App 3.0.0+|
|@input|EventHandle||当键盘输入时,触发input事件,event.detail = {value}|差异见下方 Tips|
|@focus|EventHandle||输入框聚焦时触发,event.detail = { value, height },height 为键盘高度|仅微信小程序、App(2.2.3+) 、QQ小程序支持 height|
|@blur|EventHandle||输入框失去焦点时触发,event.detail = {value: value}||
......
......@@ -24,7 +24,7 @@
|adjust-position|Boolean|true|键盘弹起时,是否自动上推页面|App-Android(softinputMode 为 adjustResize 时无效)、微信小程序、百度小程序、QQ小程序|
|disable-default-padding|boolean|false|是否去掉 iOS 下的默认内边距|微信小程序2.10.0|
|hold-keyboard|boolean|false|focus时,点击页面的时候不收起键盘|微信小程序2.8.2|
|auto-blur|boolean|false|键盘收起时,是否自动失去焦点|APP(HBuilder x2.9.11)|
|auto-blur|boolean|false|键盘收起时,是否自动失去焦点|App 3.0.0+|
|@focus|EventHandle||输入框聚焦时触发,event.detail = { value, height },height 为键盘高度|仅微信小程序、App(HBuilderX 2.0+ [nvue uni-app模式](http://ask.dcloud.net.cn/article/36074)) 、QQ小程序支持 height|
|@blur|EventHandle||输入框失去焦点时触发,event.detail = {value, cursor}||
|@linechange|EventHandle||输入框行数变化时调用,event.detail = {height: 0, heightRpx: 0, lineCount: 0}|字节跳动小程序不支持,nvue ios暂不支持|
......
......@@ -372,9 +372,11 @@ collection.field()
使用示例
```js
collection.field({ 'age': true }) //只返回age字段,其他字段不返回
collection.field({ 'age': true }) //只返回age字段、_id字段,其他字段不返回
```
备注:只能指定要返回的字段或者不要返回的字段。即{'a': true, 'b': false}是一种错误的参数格式
备注:只能指定要返回的字段或者不要返回的字段。即{'a': true, 'b': false}是一种错误的参数格式
**使用白名单模式_id会默认带上,即使没有配置{_id: true}以上面示例为例,返回的字段除age外还包含一个_id。**
### 查询指令
......
......@@ -443,6 +443,7 @@ db.collection('order')
- field参数字符串内没有冒号,{}为联表查询标志
- 上述示例中如果order表的`book_id`字段是数组形式存放多个book_id,也跟上述写法一致,clientDB会自动根据字段类型进行联表查询
- 各个表的_id字段会默认带上,即使没有指定返回
### 查询列表分页
......
......@@ -34,8 +34,8 @@
![](https://img.cdn.aliyun.dcloud.net.cn/uni-app/uniCloud/cloud-function-urlify.png)
>- 每个服务空间最多绑定1个自定义域名。
>- uniCloud提供默认域名供体验和测试该特性,域名规范如:`${spaceId}.service.tcloudbase.com`
>- 绑定自定义域名之前,请先设置您默认域名的 CNAME 记录值为`${spaceId}.service.tcloudbase.com`,CNAME 记录不存在时会导致域名绑定失败,另外需要注意的是此域名必须已经备案。
>- uniCloud提供默认域名供体验和测试该特性。
>- 绑定自定义域名之前,请先设置您默认域名的 CNAME 记录值为默认域名,CNAME 记录不存在时会导致域名绑定失败,另外需要注意的是此域名必须已经备案。
>- 单个服务空间可支持被访问的最大 QPS 为5000,单个云函数可支持被访问的最大 QPS 为2000(具体频次受函数并发限制)。
>- 默认域名可支持被访问的最大 QPS 为200,推荐您绑定自定义域名以获取更大的访问频次。
......@@ -47,12 +47,12 @@
### 通过 HTTP URL 方式访问云函数
- 方式一:通过`https://${spaceId}.service.tcloudbase.com/${path}`直接访问函数,其中`${spaceId}`是服务空间 ID,`${path}`是配置的函数触发路径。
- 方式一:通过`https://${云函数Url化域名}/${path}`直接访问函数,其中`${spaceId}`是服务空间 ID,`${path}`是配置的函数触发路径。
```sh
$ curl https://${spaceId}.service.tcloudbase.com/${path}
$ curl https://${云函数Url化域名}/${path}
```
- 方式二:直接在浏览器内打开`https://${spaceId}.service.tcloudbase.com/${path}`
- 方式二:直接在浏览器内打开`https://${云函数Url化域名}/${path}`
### 云函数的入参
......@@ -76,7 +76,7 @@ $ curl https://${spaceId}.service.tcloudbase.com/${path}
path: '/',
httpMethod: 'GET',
headers: {
'host': 'env-id.service.tcloudbase.com',
'host': 'xxx.service.tcloudbase.com',
'connection': 'close',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
......@@ -97,7 +97,7 @@ $ curl https://${spaceId}.service.tcloudbase.com/${path}
**示例**
使用GET请求`https://${spaceId}.service.tcloudbase.com/${functionPath}?a=1&b=2`,云函数接收到的`event`
使用GET请求`https://${云函数Url化域名}/${functionPath}?a=1&b=2`,云函数接收到的`event`
```
{
......@@ -111,13 +111,13 @@ $ curl https://${spaceId}.service.tcloudbase.com/${path}
```
使用POST请求`https://${spaceId}.service.tcloudbase.com/${functionPath}`,云函数接收到的`event`为请求发送的数据,**uni.request默认content-type为application/json**
使用POST请求`https://${云函数Url化域名}/${functionPath}`,云函数接收到的`event`为请求发送的数据,**uni.request默认content-type为application/json**
```js
// 以uni.request为例
uni.request({
method: 'POST',
url: 'https://${spaceId}.service.tcloudbase.com/${functionPath}',
url: 'https://${云函数Url化域名}/${functionPath}',
data: {
a: 1,
b: 2
......
......@@ -125,5 +125,5 @@ uniCloud提供包月、按量计费两种计费方式(仅腾讯云),具体
- 如果之前没有开通免费版腾讯云服务空间,则新开通的一个按量付费服务空间可以选择是否占用免费资源。如果选择了占用免费资源将无法创建预付费免费版。
- 按量计费服务空间开通时会自动开通前端网页托管,如果按量付费服务空间拥有免费额度,会默认赠送一个月前端网站托管(容量1GB、流量5GB),一个月之后会正常按量收费。
- 按量计费服务空间删除有次数限制,每个月最多删除一次,每个账号一共可以删除4次,删除之前需要关闭前端网页托管服务并删除所有云端资源(包括云函数、数据库、云存储)
- 按量计费是延迟结算,可能存在余额超支的情况,故创建按量付费服务空间时,需支付一定的保证金,用以抵消超支结算的情况。如果您不再申请使用uniCloud服务,可以申请退还保证金
- 按量计费是延迟结算,可能存在余额超支的情况,故创建按量付费服务空间时,需支付一定的保证金,用以抵消超支结算的情况。如果不再使用按量计费服务,可发送邮件到service@dcloud.io申请退款,说明退款账号即可,一般五个工作日退回。退款前请先删除按量计费服务空间,不然无法操作退款
- 目前使用腾讯云包月套餐会默认自动续费,如果包月套餐到期时uniCloud腾讯云账户余额够用则自动从余额中扣除一个月的费用,近期会提供关闭选项
此差异已折叠。
......@@ -6,7 +6,7 @@ univerify是替代短信验证登录的下一代登录验证方式,能消除
## 客户端@client
客户端如何使用一键登录请参考此文档:[univerify 使用指南](https://ask.dcloud.net.cn/article/38009)
客户端如何使用一键登录请参考此文档:[univerify 使用指南](/univerify)
## 云函数@cloud
......
......@@ -624,12 +624,12 @@ export default {
|-- |-- |-- |-- |-- |-- |
|Vue.config.silent |支持 |支持 |支持 |支持 |- |
|Vue.config.optionMergeStrategies |支持 |支持 |支持 |支持 |- |
|Vue.config.devtools |支持 |不支持 |不支持 |不支持 |只在`Web`环境下支持 |
|Vue.config.devtools |支持 |× |× |× |只在`Web`环境下支持 |
|Vue.config.errorHandler |支持 |支持 |支持 |支持 |- |
|Vue.config.warnHandler |支持 |支持 |支持 |支持 |- |
|Vue.config.ignoredElements |支持 |支持 |支持 |支持 |强烈不推荐,会覆盖`uni-app`框架配置的内置组件|
|Vue.config.keyCodes |支持 |不支持 |不支持 |不支持 |- |
|Vue.config.performance |支持 |不支持 |不支持 |不支持 |只在`Web`环境下支持 |
|Vue.config.ignoredElements |支持 |支持 |支持 |支持 |`强烈不推荐`,会覆盖`uni-app`框架配置的内置组件|
|Vue.config.keyCodes |支持 |× |× |× |- |
|Vue.config.performance |支持 |× |× |× |只在`Web`环境下支持 |
|Vue.config.productionTip |支持 |支持 |支持 |支持 |- |
......@@ -637,17 +637,17 @@ export default {
|Vue 全局 API |H5 |App端旧版|App端V3|微信小程序|说明 |
|-- |-- |-- |-- |-- |-- |
|Vue.extend |支持 |不支持 |支持 |不支持 |不可作为组件使用 |
|Vue.nextTick |支持 |不支持 |不支持 |不支持 |- |
|Vue.extend |支持 |× |支持 |× |不可作为组件使用 |
|Vue.nextTick |支持 |× |× |× |- |
|Vue.set |支持 |支持 |支持 |支持 |- |
|Vue.delete |支持 |支持 |支持 |支持 |- |
|Vue.directive|支持 |不支持 |支持 |不支持 |- |
|Vue.filter |支持 |支持 |支持 |支持 |App端旧版不可以在`class`中使用 |
|Vue.directive|支持 |× |支持 |× |- |
|Vue.filter |支持 |支持 |支持 |支持 |`App端旧版`不可以在`class`中使用 |
|Vue.component|支持 |支持 |支持 |支持 |- |
|Vue.use |支持 |支持 |支持 |支持 |- |
|Vue.mixin |支持 |支持 |支持 |支持 |- |
|Vue.version |支持 |支持 |支持 |支持 |- |
|Vue.compile |支持 |不支持 |不支持 |不支持 |`uni-app`使用的`vue`是只包含运行时的版本 |
|Vue.compile |支持 |× |× |× |`uni-app`使用的`vue`是只包含运行时的版本 |
#### 选项
......@@ -655,28 +655,28 @@ export default {
|Vue 选项 |H5 |App端旧版|App端V3|微信小程序|说明 |
|-- |-- |-- |-- |-- |-- |
|data |支持 |支持 |支持 |支持 |- |
|props |支持 |支持 |支持 |支持 |App端旧版不可以传递函数 |
|props |支持 |支持 |支持 |支持 |`App端旧版`不可以传递函数 |
|propsData |支持 |支持 |支持 |支持 |- |
|computed |支持 |支持 |支持 |支持 |- |
|methods |支持 |支持 |支持 |支持 |- |
|watch |支持 |支持 |支持 |支持 |- |
|el |支持 |不支持 |不支持 |不支持 | |
|template |支持 |不支持 |不支持 |不支持 |`uni-app`使用的`vue`是只包含运行时的版本 |
|render |支持 |不支持 |不支持 |不支持 |- |
|renderError |支持 |不支持 |不支持 |不支持 |- |
|directives |支持 |不支持 |支持 |不支持 |- |
|filters |支持 |支持 |支持 |支持 |App端旧版不可以在`class`中使用 |
|el |支持 |× |× |× | |
|template |支持 |× |× |× |`uni-app`使用的`vue`是只包含运行时的版本 |
|render |支持 |× |× |× |- |
|renderError |支持 |× |× |× |- |
|directives |支持 |× |支持 |× |- |
|filters |支持 |支持 |支持 |支持 |`App端旧版`不可以在`class`中使用 |
|components |支持 |支持 |支持 |支持 |- |
|parent |支持 |支持 |支持 |支持 |不推荐 |
|mixins |支持 |支持 |支持 |支持 |- |
|extends |支持 |支持 |支持 |支持 |- |
|provide/inject |支持 |支持 |支持 |支持 |App端旧版部分支持 |
|name |支持 |支持 |支持 |支持 |App端旧版不支持递归组件 |
|delimiters |支持 |不支持 |不支持 |不支持 |- |
|functional |支持 |不支持 |不支持 |不支持 |- |
|model |支持 |不支持 |支持 |不支持 |- |
|inheritAttrs |支持 |不支持 |支持 |不支持 |- |
|comments |支持 |不支持 |不支持 |不支持 |- |
|provide/inject |支持 |支持 |支持 |支持 |`App端旧版`部分支持 |
|name |支持 |支持 |支持 |支持 |`App端旧版`不支持递归组件 |
|delimiters |支持 |× |× |× |- |
|functional |支持 |× |× |× |- |
|model |支持 |× |支持 |× |- |
|inheritAttrs |支持 |× |支持 |× |- |
|comments |支持 |× |× |× |- |
#### 生命周期钩子
......@@ -689,8 +689,8 @@ export default {
|mounted |支持 |支持 |支持 |支持 |- |
|beforeUpdate |支持 |支持 |支持 |支持 |- |
|updated |支持 |支持 |支持 |支持 |- |
|activated |支持 |不支持 |支持 |不支持 |- |
|deactivated |支持 |不支持 |支持 |不支持 |- |
|activated |支持 |× |支持 |× |- |
|deactivated |支持 |× |支持 |× |- |
|beforeDestroy |支持 |支持 |支持 |支持 |- |
|destroyed |支持 |支持 |支持 |支持 |- |
|errorCaptured |支持 |支持 |支持 |支持 |- |
......@@ -701,17 +701,17 @@ export default {
|-- |-- |-- |-- |-- |-- |
|vm.$data |支持 |支持 |支持 |支持 |- |
|vm.$props |支持 |支持 |支持 |支持 |- |
|vm.$el |支持 |不支持 |不支持 |不支持 |- |
|vm.$el |支持 |× |× |× |- |
|vm.$options |支持 |支持 |支持 |支持 |- |
|vm.$parent |支持 |支持 |支持 |支持 |H5端 `view`、`text` 等内置标签是以 Vue 组件方式实现,`$parent` 会获取这些内置组件 |
|vm.$parent |支持 |支持 |支持 |支持 |`H5端`:`view`、`text` 等内置标签是以 Vue 组件方式实现,`$parent` 会获取这些内置组件 |
|vm.$root |支持 |支持 |支持 |支持 |- |
|vm.$children |支持 |支持 |支持 |支持 |H5端 `view`、`text` 等内置标签是以 Vue 组件方式实现,`$children` 会获取这些内置组件|
|vm.$slots |支持 |支持 |不支持 |支持 |App端旧版获取值为`{'slotName':true/false}`比如:`{"footer":true}` |
|vm.$scopedSlots|支持 |支持 |支持 |支持 |App端旧版获取值为`{'slotName':true/false}`比如:`{"footer":true}` |
|vm.$refs |支持 |支持 |支持 |支持 |非H5端只能用于获取自定义组件,不能用于获取内置组件实例(如:view、text)|
|vm.$isServer |支持 |不支持 |支持 |不支持 |App端V3总是返回false |
|vm.$attrs |支持 |不支持 |支持 |不支持 |- |
|vm.$listeners |支持 |不支持 |支持 |不支持 |- |
|vm.$children |支持 |支持 |支持 |支持 |`H5端`:`view`、`text` 等内置标签是以 Vue 组件方式实现,`$children` 会获取这些内置组件|
|vm.$slots |支持 |支持 |× |支持 |`App端旧版`:获取值为`{'slotName':true/false}`比如:`{"footer":true}` |
|vm.$scopedSlots|支持 |支持 |支持 |支持 |`App端旧版`:获取值为`{'slotName':true/false}`比如:`{"footer":true}` |
|vm.$refs |支持 |支持 |支持 |支持 |`非H5端`只能用于获取自定义组件,不能用于获取内置组件实例(如:view、text)|
|vm.$isServer |支持 |× |支持 |× |`App端V3`总是返回false |
|vm.$attrs |支持 |× |支持 |× |- |
|vm.$listeners |支持 |× |支持 |× |- |
#### 实例方法
......@@ -725,7 +725,7 @@ export default {
|vm.$once() |支持 |支持 |支持 |支持 |- |
|vm.$off() |支持 |支持 |支持 |支持 |- |
|vm.$emit() |支持 |支持 |支持 |支持 |- |
|vm.$mount() |支持 |不支持 |不支持 |不支持 |- |
|vm.$mount() |支持 |× |× |× |- |
|vm.$forceUpdate()|支持 |支持 |支持 |支持 |- |
|vm.$nextTick() |支持 |支持 |支持 |支持 |- |
|vm.$destroy() |支持 |支持 |支持 |支持 |- |
......@@ -733,38 +733,38 @@ export default {
#### 模板指令
|Vue 指令 |H5 |App端旧版|App端V3|微信小程序|说明 |
|Vue 指令|H5|App端旧版|App端V3|微信小程序|说明 |
|-- |-- |-- |-- |-- |-- |
|v-text |支持 |支持 |支持 |支持 |- |
|v-html |支持 |不支持 |支持 |不支持 |- |
|v-html |支持 |× |支持 |× |- |
|v-show |支持 |支持 |支持 |支持 |- |
|v-if |支持 |支持 |支持 |支持 |- |
|v-else |支持 |支持 |支持 |支持 |- |
|v-else-if|支持 |支持 |支持 |支持 |- |
|v-for |支持 |支持 |支持 |支持 |- |
|v-on |支持 |支持 |支持 |支持 |- |
|v-bind |支持 |支持 |支持 |支持 |App端旧版不支持`v-bind="{key:value}"`类似用法|
|v-bind |支持 |支持 |支持 |支持 |`App端旧版`和`微信小程序`不支持`v-bind="{key:value}"`类似用法|
|v-model |支持 |支持 |支持 |支持 |- |
|v-pre |支持 |不支持 |支持 |不支持 |- |
|v-cloak |支持 |不支持 |不支持 |不支持 |- |
|v-once |支持 |不支持 |支持 |不支持 |- |
|v-pre |支持 |× |支持 |× |- |
|v-cloak |支持 |× |× |× |- |
|v-once |支持 |× |支持 |× |- |
#### 特殊属性
|Vue 特殊属性 |H5 |App端旧版|App端V3|微信小程序|说明 |
|-- |-- |-- |-- |-- |-- |
|key |支持 |支持 |支持 |支持 |App端旧版不支持表达式|
|key |支持 |支持 |支持 |支持 |`App端旧版`不支持表达式|
|ref |支持 |支持 |支持 |支持 |- |
|is |支持 |不支持 |支持 |不支持 |- |
|is |支持 |× |支持 |× |- |
#### 内置组件
|Vue 内置组件 |H5 |App端旧版|App端V3|微信小程序 |说明 |
|-- |-- |-- |-- |-- |-- |
|component |支持 |不支持 |支持 |不支持 |- |
|transition |支持 |不支持 |不支持 |不支持 |- |
|transition-group |支持 |不支持 |不支持 |不支持 |- |
|keep-alive |支持 |不支持 |支持 |不支持 |- |
|component |支持 |× |支持 |× |- |
|transition |支持 |× |× |× |- |
|transition-group |支持 |× |× |× |- |
|keep-alive |支持 |× |支持 |× |- |
|slot |支持 |支持 |支持 |支持 |- |
......@@ -73,6 +73,7 @@ const device = [
'onMemoryWarning',
'getNetworkType',
'onNetworkStatusChange',
'offNetworkStatusChange',
'onAccelerometerChange',
'offAccelerometerChange',
'startAccelerometer',
......
......@@ -77,10 +77,12 @@
"uni.onMemoryWarning": true,
"uni.getNetworkType": true,
"uni.onNetworkStatusChange": true,
"uni.offNetworkStatusChange": true,
"uni.onAccelerometerChange": true,
"uni.startAccelerometer": true,
"uni.stopAccelerometer": true,
"uni.onCompassChange": true,
"uni.offCompassChange": true,
"uni.startCompass": true,
"uni.stopCompass": true,
"uni.onGyroscopeChange": true,
......
......@@ -83,8 +83,9 @@ export default {
}
},
created () {
const pages = getCurrentPages()
const pages = getCurrentPages()
const page = pages[pages.length - 1]
this.__$page = page
this.$watch('title', () => {
this.setNavigationBarTitle()
})
......@@ -101,7 +102,7 @@ export default {
this.setNavigationBarColor()
})
// #ifdef APP-PLUS
this._webview = page.$getAppWebview()
this.__$webview = page.$getAppWebview()
attrs.forEach(key => {
const titleNView = {}
if (this[key] || this[key].length > 0) {
......@@ -124,14 +125,18 @@ export default {
methods: {
setNavigationBarTitle () {
uni.setNavigationBarTitle({
__page__: this.__$page,
title: this.title
})
},
setNavigationBarLoading () {
uni[(this.loading ? 'show' : 'hide') + 'NavigationBarLoading']()
uni[(this.loading ? 'show' : 'hide') + 'NavigationBarLoading']({
__page__: this.__$page
})
},
setNavigationBarColor () {
uni.setNavigationBarColor({
__page__: this.__$page,
frontColor: this.frontColor,
backgroundColor: this.backgroundColor,
animation: {
......@@ -141,7 +146,7 @@ export default {
})
},
setTitleNView (titleNView) {
const webview = this._webview
const webview = this.__$webview
const style = webview.getStyle()
if (style && style.titleNView) {
webview.setStyle({
......
......@@ -5,6 +5,7 @@
:data="dataList"
:pagination="paginationInternal"
:loading="loading"
:hasMore="hasMore"
:error="errorMessage"
/>
</view>
......@@ -52,6 +53,14 @@ export default {
type: String,
default: ''
},
orderby: {
type: String,
default: ''
},
where: {
type: [String, Object],
default: ''
},
pageData: {
type: String,
default: 'add'
......@@ -68,18 +77,22 @@ export default {
type: [Boolean, String],
default: false
},
orderby: {
type: String,
default: ''
},
where: {
type: [String, Object],
default: ''
},
getone: {
type: [Boolean, String],
default: false
},
gettree: {
type: [Boolean, String],
default: false
},
startwith: {
type: String,
default: ''
},
limitlevel: {
type: Number,
default: 10
},
manual: {
type: Boolean,
default: false
......@@ -88,7 +101,8 @@ export default {
data () {
return {
loading: false,
dataList: this.getone ? {} : [],
hasMore: false,
dataList: this.getone ? undefined : [],
paginationInternal: {
current: this.pageCurrent,
size: this.pageSize,
......@@ -107,7 +121,7 @@ export default {
})
return al
}, (newValue, oldValue) => {
this.paginationInternal.pageSize = this.pageSize
this.paginationInternal.size = this.pageSize
let needReset = false
for (let i = 2; i < newValue.length; i++) {
......@@ -309,19 +323,20 @@ export default {
count
} = res.result
this._isEnded = data.length < this.pageSize
this.hasMore = !this._isEnded
const data2 = this.getone ? (data.length ? data[0] : undefined) : data
callback && callback(data2, this._isEnded)
this._dispatchEvent(events.load, data2)
if (this.pageData === pageMode.add) {
if (this.getone || this.pageData === pageMode.replace) {
this.dataList = data2
} else {
this.dataList.push(...data2)
if (this.dataList.length) {
this.paginationInternal.current++
}
} else {
this.dataList = data2
}
if (this.getcount) {
......@@ -331,7 +346,12 @@ export default {
// #ifdef H5
if (process.env.NODE_ENV === 'development') {
this._debugDataList.length = 0
this._debugDataList.push(...JSON.parse(JSON.stringify(this.dataList)))
const formatData = JSON.parse(JSON.stringify(this.dataList))
if (Array.isArray(this.dataList)) {
this._debugDataList.push(...formatData)
} else {
this._debugDataList.push(formatData)
}
}
// #endif
}).catch((err) => {
......@@ -368,9 +388,17 @@ export default {
current,
size
} = this.paginationInternal
db = db.skip(size * (current - 1)).limit(size).get({
getCount: this.getcount
})
const getOptions = {}
if (this.getcount) {
getOptions.getCount = this.getcount
}
if (this.gettree) {
getOptions.getTree = {
limitLevel: this.limitlevel,
startWith: this.startwith
}
}
db = db.skip(size * (current - 1)).limit(size).get(getOptions)
return db
},
......
......@@ -426,20 +426,25 @@ function isPlainObject (obj) {
return _toString.call(obj) === '[object Object]'
}
function initBuiltInEasycom (components, usingAutoImportComponents) {
components.forEach(name => {
const easycomName = `^${name}$`
if (!usingAutoImportComponents[easycomName]) {
usingAutoImportComponents[easycomName] =
'@dcloudio/uni-cli-shared/components/' + name + '.vue'
}
})
}
function initAutoImportComponents (easycom = {}) {
let usingAutoImportComponents = easycom.custom || easycom || {}
if (!isPlainObject(usingAutoImportComponents)) {
usingAutoImportComponents = {}
}
initBuiltInEasycom(BUILT_IN_EASYCOMS, usingAutoImportComponents)
// 目前仅 mp-weixin 内置支持 page-meta 等组件
if (process.env.UNI_PLATFORM !== 'mp-weixin') {
BUILT_IN_COMPONENTS.forEach(name => {
const easycomName = `^${name}$`
if (!usingAutoImportComponents[easycomName]) {
usingAutoImportComponents[easycomName] =
'@dcloudio/uni-cli-shared/components/' + name + '.vue'
}
})
initBuiltInEasycom(BUILT_IN_COMPONENTS, usingAutoImportComponents)
}
const newUsingAutoImportComponentsJson = JSON.stringify(usingAutoImportComponents)
......@@ -504,13 +509,18 @@ function parseUsingAutoImportComponents (usingAutoImportComponents) {
return autoImportComponents
}
const BUILT_IN_COMPONENTS = ['page-meta', 'navigation-bar', 'uni-match-media', 'unicloud-db']
const BUILT_IN_COMPONENTS = ['page-meta', 'navigation-bar', 'uni-match-media']
function isBuiltInComponent (name) {
const BUILT_IN_EASYCOMS = ['unicloud-db']
function isBuiltInComponent (name) { // uni-template-compiler/lib/util.js 识别微信内置组件
return BUILT_IN_COMPONENTS.includes(name)
}
function isBuiltInComponentPath (modulePath) {
function isBuiltInComponentPath (modulePath) { // 内置的 easycom 类组件
if (BUILT_IN_EASYCOMS.find(name => modulePath.includes(name))) {
return true
}
return !!BUILT_IN_COMPONENTS.find(name => modulePath.includes(name))
}
......
......@@ -74,11 +74,11 @@ function initExtends (name, plugin, plugins) {
console.error('目前仅支持基于 h5 平台做扩展')
process.exit(0)
}
const extendsPlugin = plugins.find(plugin => plugin.name === extendsPlatform)
if (!plugin) {
console.error(`缺少平台 ${extendsPlatform} 插件`)
process.exit(0)
}
}
const extendsPlugin = plugins.find(plugin => plugin.name === extendsPlatform)
process.env.UNI_SUB_PLATFORM = name
process.env.UNI_PLATFORM = extendsPlatform
initPlugin(extendsPlugin)
......
......@@ -93,7 +93,7 @@ const NODE_MODULES_REGEX = /(\.\.\/)?node_modules/g
function normalizeNodeModules (str) {
str = normalizePath(str).replace(NODE_MODULES_REGEX, 'node-modules')
// HBuilderX 内置模块路径转换
str = str.replace(/.*HBuilderX\/plugins\/uniapp-cli\/node[-_]modules/, 'node-modules')
str = str.replace(/.*\/plugins\/uniapp-cli\/node[-_]modules/, 'node-modules')
if (process.env.UNI_PLATFORM === 'mp-alipay') {
str = str.replace('node-modules/@', 'node-modules/npm-scope-')
}
......
......@@ -31,11 +31,21 @@ const EVENTS = {
callouttap: 'calloutTap',
controltap: 'controlTap',
regionchange: 'regionChange',
paneltap: 'panelTap',
// scroll-view
scrolltoupper: 'scrollToUpper',
scrolltolower: 'scrollToLower',
// movable-view
changeend: 'changeEnd'
changeend: 'changeEnd',
// video
timeupdate: 'timeUpdate',
waiting: 'loading',
fullscreenchange: 'fullScreenChange',
useraction: 'userAction',
renderstart: 'renderStart',
loadedmetadata: 'renderStart',
// swiper
animationfinish: 'animationEnd'
}
module.exports = {
......
......@@ -11,6 +11,7 @@ module.exports = {
style: '.ttss',
template: '.ttml'
},
subPackages: true,
project: 'project.tt.json'
},
copyWebpackOptions (platformOptions, vueOptions) {
......@@ -20,4 +21,4 @@ module.exports = {
})
return copyOptions
}
}
}
const compiler = require('../lib')
function assertCodegen (template, templateCode, renderCode = 'with(this){}', options = {}) {
const res = compiler.compile(template, {
function assertCodegen (template, templateCode, renderCode = 'with(this){}', mpOptions = {}, baseOptions = {}) {
const res = compiler.compile(template, Object.assign({
resourcePath: 'test.wxml',
mp: Object.assign({
minified: true,
isTest: true,
platform: 'mp-alipay'
}, options)
})
}, mpOptions)
}, baseOptions))
expect(res.template).toBe(templateCode)
expect(res.render).toBe(renderCode)
......@@ -45,6 +45,15 @@ describe('mp:compiler-mp-alipay', () => {
'<component1 v-for="item in items" :ref="c4"></component1>',
'<component1 vue-id="{{\'551070e6-1-\'+__i0__}}" ref="__r" data-ref-in-for="{{c4}}" a:for="{{items}}" a:for-item="item" a:for-index="__i0__" onVueInit="__l"></component1>'
)
assertCodegen(
'<component1 @change="onChange">text</component1>',
'<component1 onChange="__e" vue-id="551070e6-1" data-event-opts="{{[[\'^change\',[[\'onChange\']]]]}}" data-com-type="wx" ref="__r" onVueInit="__l">text</component1>',
undefined,
undefined,
{
wxComponents: { component1: '/mycomponents/component1' }
}
)
})
it('generate default slot', () => {
assertCodegen(
......
......@@ -44,6 +44,14 @@ module.exports = function traverseData (path, state, tagName) {
t.stringLiteral('wx')
)
)
if (state.options.platform.name === 'mp-alipay') {
addAttrProperties.push(
t.objectProperty(
t.stringLiteral('ref'),
t.stringLiteral('__r')
)
)
}
}
if (addAttrProperties.length) {
......@@ -56,4 +64,4 @@ module.exports = function traverseData (path, state, tagName) {
)
}
}
}
}
......@@ -78,8 +78,9 @@ function processElement (ast, state, isRoot) {
if (ast.attr.id && ast.attr.id.indexOf('{{') === 0) {
state.tips.add(`id 作为属性保留名,不允许在自定义组件 ${ast.type} 中定义为 props`)
}
if (hasOwn(ast.attr, 'data') && platformName !== 'mp-toutiao') { // 百度中会出现异常情况
state.tips.add(`data 作为属性保留名,不允许在自定义组件 ${ast.type} 中定义为 props`)
if (hasOwn(ast.attr, 'data') && platformName !== 'mp-toutiao') { // 百度中会出现异常情况
// TODO 暂不输出
// state.tips.add(`data 作为属性保留名,不允许在自定义组件 ${ast.type} 中定义为 props`)
}
}
}
......
......@@ -18,7 +18,32 @@ const TAGS = [
'slider'
]
const modules = []
const modules = [{
// render-whole => append="tree"
preTransformNode (el, options) {
if (!Object.hasOwnProperty.call(el.attrsMap, 'append')) {
const name = 'render-whole'
const value = el.attrsMap[name]
if (value === true || value === 'true') {
// remove
delete el.attrsMap.append
const index = el.attrsList.findIndex(item => item.name === name)
const attr = el.attrsList[index]
el.attrsList.splice(index, 1)
el.appendAsTree = true
el.attrsMap.append = 'tree'
el.attrsList.push({
name: 'append',
value: 'tree',
bool: false,
start: attr.start,
end: attr.end
})
}
}
}
}]
const deprecated = {
events: {
......@@ -105,7 +130,7 @@ const oldCompile = compiler.compile
compiler.compile = function (source, options = {}) {
(options.modules || (options.modules = [])).push(autoComponentsModule)
options.modules.push(require('@dcloudio/uni-template-compiler/lib/asset-url'))
options.modules.push(require('@dcloudio/uni-template-compiler/lib/asset-url'))
options.modules.push(require('@dcloudio/uni-template-compiler/lib/bool-attr'))
options.isUnaryTag = isUnaryTag
......
......@@ -5,7 +5,7 @@ var {
} = require('@dcloudio/uni-cli-shared')
module.exports = function (content, map) {
this.cacheable && this.cacheable()
this.callback(null, 'module.exports = ' + genStyleString(content.replace(/!important/g, ''), this), map)
this.callback(null, 'module.exports = ' + genStyleString(content, this), map)
}
// @todo:
......@@ -67,4 +67,4 @@ function genStyleString (input, loader) {
}
})
return output
}
}
......@@ -4,27 +4,53 @@ var css = require('css')
var util = require('./lib/util')
var validateItem = require('./lib/validator').validate
var shorthandParser = require('./lib/shorthand-parser')
var importantStr = ' !important'
// padding & margin shorthand parsing
function convertLengthShorthand (rule, prop) {
for (var i = 0; i < rule.declarations.length; i++) {
var declaration = rule.declarations[i]
if (declaration.property === prop) {
var values = declaration.value.split(/\s+/)
var values = declaration.value.split(/\s+/)
// values[0] = values[0] || 0
values[1] = values[1] || values[0]
values[2] = values[2] || values[0]
values[3] = values[3] || values[1]
rule.declarations.splice(i, 1)
rule.declarations.splice(i, 0, {type: 'declaration', property: prop + '-left', value: values[3], position: declaration.position})
rule.declarations.splice(i, 0, {type: 'declaration', property: prop + '-bottom', value: values[2], position: declaration.position})
rule.declarations.splice(i, 0, {type: 'declaration', property: prop + '-right', value: values[1], position: declaration.position})
rule.declarations.splice(i, 0, {type: 'declaration', property: prop + '-top', value: values[0], position: declaration.position})
rule.declarations.splice(i, 0, { type: 'declaration', property: prop + '-left', value: values[3], position: declaration.position })
rule.declarations.splice(i, 0, { type: 'declaration', property: prop + '-bottom', value: values[2], position: declaration.position })
rule.declarations.splice(i, 0, { type: 'declaration', property: prop + '-right', value: values[1], position: declaration.position })
rule.declarations.splice(i, 0, { type: 'declaration', property: prop + '-top', value: values[0], position: declaration.position })
// break
}
}
}
/**
* mergeStyle
* @param {*} object
* @param {*} classNames
* @param {*} preClassNames
* @param {*} ruleResult
* @param {*} prop
* @param {*} index
*/
function mergeStyle (object, classNames, preClassNames, ruleResult, prop, index) {
if (!process.env.UNI_USING_NVUE_STYLE_COMPILER) {
object[classNames] = object[classNames] || {}
object[classNames][prop] = ruleResult[prop]
return
}
classNames = classNames.split('.').map(str => '.' + str).slice(1)
var className = classNames.find(className => className in object) || classNames[0]
// 假设选择器已经去重简化
preClassNames += classNames.filter(str => str !== className).sort().join('')
var rules = object[className] = object[className] || {}
var style = rules[preClassNames] = rules[preClassNames] || {}
// 增加其他权重信息
style[prop] = [...ruleResult[prop], preClassNames.split('.').length - 1, index]
}
/**
* Parse `<style>` code to a JSON Object and log errors & warnings
*
......@@ -34,25 +60,25 @@ function convertLengthShorthand (rule, prop) {
* - data.jsonStyle{}: `classname.propname.value`-like object
* - data.log[{line, column, reason}]
*/
function parse(code, done) {
function parse (code, done) {
var ast, err, jsonStyle = {}, log = []
// css parse
ast = css.parse(code, {silent: true})
ast = css.parse(code, { silent: true })
// catch syntax error
if (ast.stylesheet.parsingErrors && ast.stylesheet.parsingErrors.length) {
err = ast.stylesheet.parsingErrors
err.forEach(function (error) {
log.push({line: error.line, column: error.column, reason: error.toString().replace('Error', 'ERROR')})
log.push({ line: error.line, column: error.column, reason: error.toString().replace('Error', 'ERROR') })
})
}
// walk all
/* istanbul ignore else */
if (ast && ast.type === 'stylesheet' && ast.stylesheet &&
ast.stylesheet.rules && ast.stylesheet.rules.length) {
ast.stylesheet.rules.forEach(function (rule) {
ast.stylesheet.rules && ast.stylesheet.rules.length) {
ast.stylesheet.rules.forEach(function (rule, index) {
var type = rule.type
var ruleResult = {}
var ruleLog = []
......@@ -75,6 +101,8 @@ function parse(code, done) {
name = declaration.property
value = declaration.value
var important = value.endsWith(importantStr)
value = value.replace(new RegExp(importantStr, 'g'), '')
// validate declarations and collect them to result
camelCasedName = util.hyphenedToCamelCase(name)
......@@ -82,7 +110,8 @@ function parse(code, done) {
/* istanbul ignore else */
if (typeof subResult.value === 'number' || typeof subResult.value === 'string') {
ruleResult[camelCasedName] = subResult.value
// 增加 important 权重信息
ruleResult[camelCasedName] = process.env.UNI_USING_NVUE_STYLE_COMPILER ? [subResult.value, Number(important)] : subResult.value
}
if (subResult.log) {
subResult.log.line = declaration.position.start.line
......@@ -92,14 +121,18 @@ function parse(code, done) {
})
rule.selectors.forEach(function (selector) {
if (selector.match(/^\.[A-Za-z0-9_\-:]+$/)) {
var className = selector.slice(1)
selector = selector.replace(/\s*([\+\~\>])\s*/g, '$1').replace(/\s+/, ' ')
// 支持组合选择器
const res = selector.match(process.env.UNI_USING_NVUE_STYLE_COMPILER ? /^((?:(?:\.[A-Za-z0-9_\-]+)+[\+\~\> ])*)((?:\.[A-Za-z0-9_\-\:]+)+)$/ : /^(\.)([A-Za-z0-9_\-:]+)$/)
if (res) {
var preClassNames = res[1]
var classNames = res[2]
// handle pseudo class
var pseudoIndex = className.indexOf(':')
var pseudoIndex = classNames.indexOf(':')
if (pseudoIndex > -1) {
var pseudoCls = className.slice(pseudoIndex)
className = className.slice(0, pseudoIndex)
var pseudoCls = classNames.slice(pseudoIndex)
classNames = classNames.slice(0, pseudoIndex)
var pseudoRuleResult = {}
Object.keys(ruleResult).forEach(function (prop) {
pseudoRuleResult[prop + pseudoCls] = ruleResult[prop]
......@@ -109,24 +142,22 @@ function parse(code, done) {
// merge style
Object.keys(ruleResult).forEach(function (prop) {
// handle transition
if (prop.indexOf('transition') === 0 && prop !== 'transition') {
var realProp = prop.replace('transition', '')
realProp = realProp[0].toLowerCase() + realProp.slice(1)
jsonStyle['@TRANSITION'] = jsonStyle['@TRANSITION'] || {}
jsonStyle['@TRANSITION'][className] = jsonStyle['@TRANSITION'][className] || {}
jsonStyle['@TRANSITION'][className][realProp] = ruleResult[prop]
}
jsonStyle[className] = jsonStyle[className] || {}
jsonStyle[className][prop] = ruleResult[prop]
// // handle transition
// if (prop.indexOf('transition') === 0 && prop !== 'transition') {
// var realProp = prop.replace('transition', '')
// realProp = realProp[0].toLowerCase() + realProp.slice(1)
// var object = jsonStyle['@TRANSITION'] = jsonStyle['@TRANSITION'] || {}
// mergeStyle(object, classNames, preClassNames, ruleResult, prop, index)
// }
mergeStyle(jsonStyle, classNames, preClassNames, ruleResult, prop, index)
})
}
else {
log.push({
line: rule.position.start.line,
column: rule.position.start.column,
reason: 'ERROR: Selector `' + selector + '` is not supported. Weex only support single-classname selector'
reason: 'ERROR: Selector `' + selector + '` is not supported. Weex only support classname selector'
})
}
})
......@@ -158,7 +189,9 @@ function parse(code, done) {
})
}
done(err, {jsonStyle: jsonStyle, log: log})
jsonStyle['@VERSION'] = 2
done(err, { jsonStyle: jsonStyle, log: log })
}
/**
......@@ -170,7 +203,7 @@ function parse(code, done) {
* - data.jsonStyle{}: `classname.propname.value`-like object
* - data.log[{reason}]
*/
function validate(json, done) {
function validate (json, done) {
var log = []
var err
......
function generateDeclaration (property, value, position) {
function generateDeclaration (property, value, important, position) {
return {
type: 'declaration',
property,
value,
value: value + (important ? ' !important' : ''),
position
}
}
function clearImportant (value) {
var newValue = value.replace(/ !important$/, '')
return {
value: newValue,
important: value !== newValue
}
}
function transition (declaration) {
var CHUNK_REGEXP = /^(\S*)?\s*(\d*\.?\d+(?:ms|s)?)?\s*(\S*)?\s*(\d*\.?\d+(?:ms|s)?)?$/
var match = declaration.value.match(CHUNK_REGEXP)
var { value, important } = clearImportant(declaration.value)
var match = value.match(CHUNK_REGEXP)
var result = []
var position = declaration.position
match[1] && result.push(generateDeclaration('transition-property', match[1], position))
match[2] && result.push(generateDeclaration('transition-duration', match[2], position))
match[3] && result.push(generateDeclaration('transition-timing-function', match[3], position))
match[4] && result.push(generateDeclaration('transition-delay', match[4], position))
match[1] && result.push(generateDeclaration('transition-property', match[1], important, position))
match[2] && result.push(generateDeclaration('transition-duration', match[2], important, position))
match[3] && result.push(generateDeclaration('transition-timing-function', match[3], important, position))
match[4] && result.push(generateDeclaration('transition-delay', match[4], important, position))
return result
}
function margin (declaration) {
var { value, important } = clearImportant(declaration.value)
var position = declaration.position
var splitResult = declaration.value.split(/\s+/)
var splitResult = value.split(/\s+/)
var result = []
switch (splitResult.length) {
case 1:
......@@ -34,17 +45,145 @@ function margin (declaration) {
break
}
result.push(
generateDeclaration('margin-top', splitResult[0], position),
generateDeclaration('margin-right', splitResult[1], position),
generateDeclaration('margin-bottom', splitResult[2], position),
generateDeclaration('margin-left', splitResult[3], position)
generateDeclaration('margin-top', splitResult[0], important, position),
generateDeclaration('margin-right', splitResult[1], important, position),
generateDeclaration('margin-bottom', splitResult[2], important, position),
generateDeclaration('margin-left', splitResult[3], important, position)
)
return result
}
function border (declaration) {
var { value, important } = clearImportant(declaration.value)
var property = declaration.property
var position = declaration.position
var result = (' ' + value).match(/^(\s+[\d\.]+\S*)?(\s+(?:solid|dashed|dotted))?(\s+\S+)?$/)
if (!result) {
declaration
}
return [
generateDeclaration(property + '-width', (result[1] || '0').trim(), important, position),
generateDeclaration(property + '-style', (result[2] || 'solid').trim(), important, position),
generateDeclaration(property + '-color', (result[3] || '#000000').trim(), important, position)
]
}
function borderProperty (declaration) {
var { value, important } = clearImportant(declaration.value)
var position = declaration.position
var property = declaration.property.split('-')[1]
var splitResult = value.split(/\s+/)
var result = []
switch (splitResult.length) {
case 1:
return declaration
case 2:
splitResult.push(splitResult[0], splitResult[1])
break
case 3:
splitResult.push(splitResult[1])
break
}
result.push(
generateDeclaration('border-top-' + property, splitResult[0], important, position),
generateDeclaration('border-right-' + property, splitResult[1], important, position),
generateDeclaration('border-bottom-' + property, splitResult[2], important, position),
generateDeclaration('border-left-' + property, splitResult[3], important, position)
)
return result
}
function borderRadius (declaration) {
var { value, important } = clearImportant(declaration.value)
var position = declaration.position
var splitResult = value.split(/\s+/)
var result = []
if (value.includes('/')) {
return declaration
}
switch (splitResult.length) {
case 1:
return declaration
case 2:
splitResult.push(splitResult[0], splitResult[1])
break
case 3:
splitResult.push(splitResult[1])
break
}
result.push(
generateDeclaration('border-top-left-radius', splitResult[0], important, position),
generateDeclaration('border-top-right-radius', splitResult[1], important, position),
generateDeclaration('border-bottom-right-radius', splitResult[2], important, position),
generateDeclaration('border-bottom-left-radius', splitResult[3], important, position)
)
return result
}
function flexFlow (declaration) {
var { value, important } = clearImportant(declaration.value)
var position = declaration.position
var result = value.match(/^(column|column-reverse|row|row-reverse)?\s*(\bnowrap|\bwrap|\bwrap-reverse)?$/)
if (!result) {
declaration
}
return [
generateDeclaration('flex-direction', result[1] || 'column', important, position),
generateDeclaration('flex-wrap', result[2] || 'nowrap', important, position)
]
}
function font (declaration) {
var { value, important } = clearImportant(declaration.value)
var position = declaration.position
var splitResult = value.replace(/,\s*/g, ',').replace(/\s*\/\s*/, '/').replace(/['"].+?['"]/g, str => str.replace(/\s+/g, '#')).split(/\s+/)
var result = []
var styleValues = ['normal', 'italic', 'oblique']
result.push(generateDeclaration('font-style', styleValues[Math.max(0, styleValues.indexOf(splitResult[0]))], important, position))
var weight = splitResult.slice(0, -2).find(str => /normal|bold|lighter|bolder|\d+/.test(str))
if (weight) {
result.push(generateDeclaration('font-weight', weight, important, position))
}
splitResult = splitResult.slice(-2)
if (/[\d\.]+\S*(\/[\d\.]+\S*)?/.test(splitResult[0])) {
var [size, height] = splitResult[0].split('/')
result.push(
generateDeclaration('font-size', size, important, position),
generateDeclaration('line-height', height || 'normal', important, position),
generateDeclaration('font-family', splitResult[1].replace(/#/g, ' '), important, position)
)
return result
}
return []
}
function background (declaration) {
var { value, important } = clearImportant(declaration.value)
var position = declaration.position
if (/^#?\S+$/.test(value) || /^rgba?(.+)$/.test(value)) {
return generateDeclaration('background-color', value, important, position)
} else if (/^linear-gradient(.+)$/.test(value)) {
return generateDeclaration('background-image', value, important, position)
} else {
return declaration
}
}
var parserCollection = {
transition,
margin
margin,
border,
'border-top': border,
'border-right': border,
'border-bottom': border,
'border-left': border,
'border-style': borderProperty,
'border-width': borderProperty,
'border-color': borderProperty,
'border-radius': borderRadius,
'flex-flow': flexFlow,
font,
background
}
module.exports = function (declarations) {
......
......@@ -4560,8 +4560,8 @@ var props = {
// The "unitary tag" means that the tag node and its children
// must be sent to the native together.
var isUnitaryTag = makeMap('cell,header,cell-slot,recycle-list', true);
var isUnitaryTag = makeMap('cell,header,cell-slot,recycle-list,text,u-text', true);
// fixed by xxxxxx
function preTransformNode (el) {
if (isUnitaryTag(el.tag) && !el.attrsList.some(function (item) { return item.name === 'append'; })) {
el.attrsMap.append = 'tree';
......
......@@ -242,6 +242,10 @@ if (isNVueCompiler) {
process.env.UNI_USING_NVUE_COMPILER = true
}
if (platformOptions.nvueStyleCompiler !== 'weex') {
process.env.UNI_USING_NVUE_STYLE_COMPILER = true
}
if (platformOptions.usingComponents === true) {
if (process.env.UNI_PLATFORM !== 'h5') {
process.env.UNI_USING_COMPONENTS = true
......@@ -425,4 +429,4 @@ runByHBuilderX && console.log('正在编译中...')
module.exports = {
manifestPlatformOptions: platformOptions
}
}
......@@ -21,7 +21,12 @@ module.exports = {
getWatchOptions () {
return {
ignored: [
/node_modules/,
/node_modules/,
path.resolve(process.env.UNI_INPUT_DIR, '*.md'),
path.resolve(process.env.UNI_INPUT_DIR, '.hbuilderx'),
path.resolve(process.env.UNI_INPUT_DIR, '.editorconfig'),
path.resolve(process.env.UNI_INPUT_DIR, '.gitignore'),
path.resolve(process.env.UNI_INPUT_DIR, 'LICENSE'),
path.resolve(process.env.UNI_INPUT_DIR, 'unpackage'),
path.resolve(process.env.UNI_INPUT_DIR, 'uniCloud-aliyun'),
path.resolve(process.env.UNI_INPUT_DIR, 'uniCloud-tcb'),
......
......@@ -246,7 +246,7 @@ function processCss(css) {
.replace(VAR_WINDOW_LEFT, '0px')
.replace(VAR_WINDOW_RIGHT, '0px')
}
return css.replace(/\{[\s\S]+?\}/g, function (css) {
return css.replace(/\{[\s\S]+?\}|@media.+\{/g, function (css) {
return css.replace(UPX_RE, function (a, b) {
return uni.upx2px(b) + 'px'
})
......
......@@ -245,17 +245,17 @@ function processCss(css) {
var offset = getWindowOffset()
css = css.replace(VAR_STATUS_BAR_HEIGHT, '0px')
.replace(VAR_WINDOW_TOP, offset.top + 'px')
.replace(VAR_WINDOW_BOTTOM, offset.bottom + 'px')
.replace(VAR_WINDOW_LEFT, '0px')
.replace(VAR_WINDOW_BOTTOM, offset.bottom + 'px')
.replace(VAR_WINDOW_LEFT, '0px')
.replace(VAR_WINDOW_RIGHT, '0px')
}
return css
.replace(BODY_SCOPED_RE, page)
.replace(BODY_RE, '')
.replace(PAGE_SCOPED_RE, 'body.' + page + ' uni-page-body')
.replace(/\{[\s\S]+?\}/g, function (css) {
if(typeof uni === 'undefined'){
return css
.replace(/\{[\s\S]+?\}|@media.+\{/g, function (css) {
if(typeof uni === 'undefined'){
return css
}
return css.replace(UPX_RE, function (a, b) {
return uni.upx2px(b) + 'px'
......
......@@ -57,8 +57,8 @@ if (process.env.UNI_USING_V3) {
)
}
const tranformValue = function (decl, opts) {
return valueParser(decl.value)
const tranformValue = function (value, opts) {
return valueParser(value)
.walk(node => {
if (node.type === 'word') {
parseWord(node, opts)
......@@ -205,10 +205,16 @@ if (process.env.UNI_USING_V3) {
}
}
// Transform each property declaration here
decl.value = tranformValue(decl, opts)
decl.value = tranformValue(decl.value, opts)
})
})
root.walkAtRules(rule => {
if (rule.name === 'media') {
rule.params = tranformValue(rule.params, opts)
}
})
if (bgDecls.length) {
const rule = postcss.rule({
selector: 'body.?%PAGE?%'
......@@ -240,7 +246,7 @@ if (process.env.UNI_USING_V3) {
}
}
// Transform each property declaration here
decl.value = tranformValue(decl, opts)
decl.value = tranformValue(decl.value, opts)
})
if (process.env.UNI_PLATFORM !== 'quickapp-native') {
rule.selectors = rule.selectors.map(complexSelector => {
......
......@@ -171,6 +171,9 @@ module.exports = function (pagesJson, userManifestJson, isAppView) {
}
}
// 全屏配置
manifestJson.fullscreen = manifestJson.plus.fullscreen
// 地图坐标系
if (manifestJson.permissions && manifestJson.permissions.Maps) {
manifestJson.permissions.Maps.coordType = 'gcj02'
......@@ -271,6 +274,8 @@ module.exports = function (pagesJson, userManifestJson, isAppView) {
appJson.nvueCompiler = 'weex'
}
appJson.nvueStyleCompiler = process.env.UNI_USING_NVUE_STYLE_COMPILER ? 'uni-app' : 'weex'
if (manifestJson.plus.renderer === 'native') {
appJson.renderer = 'native'
} else {
......@@ -522,4 +527,4 @@ module.exports = function (pagesJson, userManifestJson, isAppView) {
}, isAppView)
}
return [app, manifest]
}
}
......@@ -9,7 +9,8 @@ module.exports = function (pagesJson, manifestJson) {
project
} = require('../mp')(pagesJson, manifestJson, require('./project.config.json'))
const baseJson = {
const baseJson = {
appType: 'webapp', // 华为IDE V3.0.2+ 需要此属性,否则无法导入
minPlatformVersion: 1070
}
manifestJson.name && (baseJson.name = manifestJson.name)
......
......@@ -542,7 +542,7 @@ export function handleEvent (event) {
}
handler.once = true
}
const params = processEventArgs(
let params = processEventArgs(
this.$vm,
event,
eventArray[1],
......@@ -550,9 +550,13 @@ export function handleEvent (event) {
isCustom,
methodName
)
params = Array.isArray(params) ? params : []
// 参数尾部增加原始事件对象用于复杂表达式内获取额外数据
// eslint-disable-next-line no-sparse-arrays
ret.push(handler.apply(handlerCtx, (Array.isArray(params) ? params : []).concat([, , , , , , , , , , event])))
if (/=\s*\S+\.eventParams\s*\|\|\s*\S+\[['"]event-params['"]\]/.test(handler.toString())) {
// eslint-disable-next-line no-sparse-arrays
params = params.concat([, , , , , , , , , , event])
}
ret.push(handler.apply(handlerCtx, params))
}
})
}
......
......@@ -848,7 +848,8 @@ export function canvasPutImageData ({
invoke(callbackId, data)
})
let compressed
if (__PLATFORM__ === 'app-plus') {
// iOS真机非调试模式压缩太慢暂时排除
if (__PLATFORM__ === 'app-plus' && (plus.os.name !== 'iOS' || typeof __WEEX_DEVTOOL__ === 'boolean')) {
const pako = require('pako')
data = pako.deflateRaw(data, { to: 'string' })
compressed = true
......
......@@ -17,7 +17,7 @@ UniServiceJSBridge.subscribe('onEditorMethodCallback', ({
callback.invoke(callbackId, data)
})
const methods = ['insertDivider', 'insertImage', 'insertText', 'setContents', 'getContents', 'clear', 'removeFormat', 'undo', 'redo']
const methods = ['insertDivider', 'insertImage', 'insertText', 'setContents', 'getContents', 'clear', 'removeFormat', 'undo', 'redo', 'blur', 'getSelectionText', 'scrollIntoView']
export class EditorContext {
constructor (id, pageId) {
......
......@@ -16,4 +16,14 @@ onMethod('onNetworkStatusChange', res => {
export function onNetworkStatusChange (callbackId) {
callbacks.push(callbackId)
}
}
export function offNetworkStatusChange (callbackId) {
// 暂不支持移除所有监听
if (callbackId) {
const index = callbacks.indexOf(callbackId)
if (index >= 0) {
callbacks.splice(index, 1)
}
}
}
......@@ -2,7 +2,9 @@ import createCallbacks from 'uni-helpers/callbacks'
import {
getCurrentPageVm
} from '../../platform'
import {
checkInWindows
} from 'uni-helpers/windows'
const createMediaQueryObserverCallbacks = createCallbacks('requestMediaQueryObserver')
class ServiceMediaQueryObserver {
......@@ -24,13 +26,13 @@ class ServiceMediaQueryObserver {
reqId: this.reqId,
component: this.component,
options: this.options
})
}, checkInWindows(this.component) ? this.component : this.pageId)
}
disconnect () {
UniServiceJSBridge.publishHandler('destroyMediaQueryObserver', {
reqId: this.reqId
})
}, checkInWindows(this.component) ? this.component : this.pageId)
}
}
......
......@@ -33,7 +33,7 @@ function humpToLine (name) {
export function requestMediaQueryObserver ({
reqId,
options
}, pageId) {
}) {
// 创建一个媒体查询对象
const mediaQueryObserver = mediaQueryObservers[reqId] = window.matchMedia(handleMediaQueryStr(options))
......
......@@ -365,12 +365,10 @@ export default {
}) {
const canvas = this.$refs.canvas
let data
if (!width) {
width = canvas.offsetWidth - x
}
if (!height) {
height = canvas.offsetHeight - y
}
const maxWidth = canvas.offsetWidth - x
width = width ? Math.min(width, maxWidth) : maxWidth
const maxHeight = canvas.offsetHeight - y
height = height ? Math.min(height, maxWidth) : maxHeight
if (!hidpi) {
if (!destWidth && !destHeight) {
destWidth = Math.round(width * pixelRatio)
......
......@@ -205,6 +205,19 @@ export default {
case 'redo':
quill.history.redo()
break
case 'blur':
quill.blur()
break
case 'getSelectionText':
range = quill.selection.savedRange
res = { text: '' }
if (range && range.length !== 0) {
res.text = quill.getText(range.index, range.length)
}
break
case 'scrollIntoView':
quill.scrollIntoView()
break
default:
break
}
......
......@@ -46,7 +46,7 @@ export default {
if (n.onTouchStart) {
n.onTouchStart()
}
event.preventDefault()
e.preventDefault()
}
},
_handleTouchMove: function (event) {
......
......@@ -69,6 +69,8 @@ export function previewImagePlus ({
}
plus.gallery.save(res.url, function (GallerySaveEvent) {
plus.nativeUI.toast('保存图片到相册成功')
}, function () {
plus.nativeUI.toast('保存图片到相册失败')
})
} else if (hasLongPressActions) {
publish(longPressActions.callbackId, {
......
import {
getRealPath
getRealPath,
warpPlusSuccessCallback,
warpPlusErrorCallback
} from '../util'
import {
invoke
} from '../../bridge'
export function saveImageToPhotosAlbum ({
filePath
} = {}, callbackId) {
plus.gallery.save(getRealPath(filePath), e => {
invoke(callbackId, {
errMsg: 'saveImageToPhotosAlbum:ok'
})
}, e => {
invoke(callbackId, {
errMsg: 'saveImageToPhotosAlbum:fail'
})
})
const successCallback = warpPlusSuccessCallback(callbackId, 'saveImageToPhotosAlbum')
const errorCallback = warpPlusErrorCallback(callbackId, 'saveImageToPhotosAlbum')
plus.gallery.save(getRealPath(filePath), successCallback, errorCallback)
}
......@@ -31,7 +31,7 @@ export function login (params, callbackId) {
authResult: authResult,
errMsg: 'login:ok'
})
}, errorCallback, provider === 'apple' ? { scope: 'email' } : params.univerifyStyle || {})
}, errorCallback, provider === 'apple' ? { scope: 'email' } : { univerifyStyle: params.univerifyStyle } || {})
}
// 先注销再登录
// apple登录logout之后无法重新触发获取email,fullname;一键登录无logout
......
import {
getLastWebview
getWebview
} from '../util'
export function setNavigationBarTitle ({
__page__,
title = ''
} = {}) {
const webview = getLastWebview()
const webview = getWebview(__page__)
if (webview) {
const style = webview.getStyle()
if (style && style.titleNView) {
......@@ -49,11 +50,12 @@ function setPageMeta (statusBarStyle) {
pages[pages.length - 1].$page.meta.statusBarStyle = statusBarStyle
}
export function setNavigationBarColor ({
export function setNavigationBarColor ({
__page__,
frontColor,
backgroundColor
} = {}) {
const webview = getLastWebview()
const webview = getWebview(__page__)
if (webview) {
const styles = {}
if (frontColor) {
......@@ -85,4 +87,4 @@ export function setNavigationBarColor ({
return {
errMsg: 'setNavigationBarColor:fail'
}
}
}
......@@ -15,6 +15,13 @@ export function callApiSync (api, args, name, alias) {
return ret
}
export function getWebview (__page__) {
if (__page__) {
return __page__.$getAppWebview()
}
return getLastWebview()
}
export function getLastWebview () {
try {
const pages = getCurrentPages()
......@@ -178,21 +185,21 @@ export function warpPlusEvent (module, name) {
}
}
export function warpPlusSuccessCallback (callbackId, neme) {
export function warpPlusSuccessCallback (callbackId, name) {
return function errorCallback (result) {
result = result || {}
invoke(callbackId, Object.assign({}, result, {
errMsg: `${neme}:ok`
errMsg: `${name}:ok`
}))
}
}
export function warpPlusErrorCallback (callbackId, neme, errMsg) {
export function warpPlusErrorCallback (callbackId, name, errMsg) {
return function errorCallback (error) {
error = error || {}
const code = error.code || 0
invoke(callbackId, {
errMsg: `${neme}:fail ${error.message || errMsg || ''}`,
errMsg: `${name}:fail ${error.message || errMsg || ''}`,
errCode: code,
code
})
......
......@@ -204,7 +204,10 @@ function setForData (id, value) {
if (!hasOwn(value, 'keyIndex')) {
vForData[forIndex] = key
} else {
(vForData[forIndex] || (vForData[forIndex] = {}))['k' + value.keyIndex] = key
if (typeof vForData[forIndex] !== 'object') {
vForData[forIndex] = {}
}
vForData[forIndex]['k' + value.keyIndex] = key
}
return key
}
......@@ -30,7 +30,7 @@ function parseTitleNViewButtons (titleNView) {
export function parseTitleNView (routeOptions) {
const windowOptions = routeOptions.window
const titleNView = windowOptions.titleNView
const titleNView = windowOptions.titleNView
routeOptions.meta.statusBarStyle = windowOptions.navigationBarTextStyle === 'black' ? 'dark' : 'light'
if ( // 无头
titleNView === false ||
......@@ -54,12 +54,13 @@ export function parseTitleNView (routeOptions) {
always: 'float'
}
const navigationBarBackgroundColor = windowOptions.navigationBarBackgroundColor
const ret = {
autoBackButton: !routeOptions.meta.isQuit,
titleText: titleImage === '' ? windowOptions.navigationBarTitleText || '' : '',
titleColor: windowOptions.navigationBarTextStyle === 'black' ? '#000000' : '#ffffff',
type: titleNViewTypeList[transparentTitle],
backgroundColor: windowOptions.navigationBarBackgroundColor || '#f8f8f8',
backgroundColor: (/^#[a-z0-9]{6}$/i.test(navigationBarBackgroundColor) || navigationBarBackgroundColor === 'transparent') ? navigationBarBackgroundColor : '#f7f7f7',
tags: titleImage === '' ? [] : [{
tag: 'img',
src: titleImage,
......@@ -77,4 +78,4 @@ export function parseTitleNView (routeOptions) {
}
return ret
}
}
......@@ -45,7 +45,7 @@ export function parseWebviewStyle (id, path, routeOptions = {}) {
})
const backgroundColor = routeOptions.window.backgroundColor
if (backgroundColor) {
if (/^#[a-z0-9]{6}$/i.test(backgroundColor) || backgroundColor === 'transparent') {
if (!webviewStyle.background) {
webviewStyle.background = backgroundColor
}
......@@ -94,4 +94,4 @@ export function parseWebviewStyle (id, path, routeOptions = {}) {
}
return webviewStyle
}
}
......@@ -148,7 +148,7 @@ export default {
_updateStyle () {
const style = getComputedStyle(this.$el)
base.concat(text, image).forEach(key => {
this.style[key] = style[key]
this.$set(this.style, key, style[key])
})
},
_requestStyleUpdate () {
......
......@@ -12,7 +12,17 @@
:style="popupStyle.content"
class="uni-actionsheet"
>
<div class="uni-actionsheet__menu">
<div
ref="main"
class="uni-actionsheet__menu"
@wheel="_handleWheel"
>
<!-- title占位 -->
<div
v-if="title"
class="uni-actionsheet__cell"
:style="{height:`${titleHeight}px`}"
/>
<div
v-if="title"
class="uni-actionsheet__title"
......@@ -20,13 +30,21 @@
{{ title }}
</div>
<div
v-for="(itemTitle, index) in itemList"
:key="index"
:style="{ color: itemColor }"
class="uni-actionsheet__cell"
@click="_close(index)"
:style="{maxHeight:`${HEIGHT}px`,overflow:'hidden'}"
>
{{ itemTitle }}
<div
ref="content"
>
<div
v-for="(itemTitle, index) in itemList"
:key="index"
:style="{ color: itemColor }"
class="uni-actionsheet__cell"
@click="_close(index)"
>
{{ itemTitle }}
</div>
</div>
</div>
</div>
<div class="uni-actionsheet__action">
......@@ -49,11 +67,50 @@
<script>
import popup from './mixins/popup'
import keypress from '../../../helpers/keypress'
import touchtrack from 'uni-mixins/touchtrack'
import scroller from 'uni-mixins/scroller/index'
import {
Friction
} from 'uni-mixins/scroller/Friction'
import {
Spring
} from 'uni-mixins/scroller/Spring'
import {
initScrollBounce,
disableScrollBounce
} from 'uni-platform/helpers/scroll'
// 由于模拟滚动阻止了点击,使用自定义事件来触发点击事件
function initClick (dom) {
const MAX_MOVE = 20
let x = 0
let y = 0
dom.addEventListener('touchstart', (event) => {
const info = event.changedTouches[0]
x = info.clientX
y = info.clientY
})
dom.addEventListener('touchend', (event) => {
const info = event.changedTouches[0]
if (Math.abs(info.clientX - x) < MAX_MOVE && Math.abs(info.clientY - y) < MAX_MOVE) {
const customEvent = new CustomEvent('click', {
bubbles: true,
cancelable: true,
target: event.target,
currentTarget: event.currentTarget
});
['screenX', 'screenY', 'clientX', 'clientY', 'pageX', 'pageY'].forEach(key => {
customEvent[key] = info[key]
})
event.target.dispatchEvent(customEvent)
}
})
}
export default {
name: 'ActionSheet',
components: { keypress },
mixins: [popup],
mixins: [popup, touchtrack, scroller],
props: {
title: {
type: String,
......@@ -78,9 +135,87 @@ export default {
default: false
}
},
data () {
return {
HEIGHT: 260,
contentHeight: 0,
titleHeight: 0,
deltaY: 0,
scrollTop: 0
}
},
watch: {
visible (newValue) {
if (newValue) {
this.$nextTick(() => {
// title 占位
if (this.title) { this.titleHeight = document.querySelector('.uni-actionsheet__title').offsetHeight }
// 滚动条更新
this._scroller.update()
// 获取contentHeight 滚动时使用
this.contentHeight = this.$refs.content.clientHeight - this.HEIGHT
// 给每一个项添加点击事件
document.querySelectorAll('.uni-actionsheet__cell').forEach(item => {
initClick(item)
})
})
}
}
},
mounted () {
// 模拟滚动使用
this.touchtrack(this.$refs.content, '_handleTrack', true)
this.$nextTick(() => {
this.initScroller(this.$refs.content, {
enableY: true,
friction: new Friction(0.0001),
spring: new Spring(2, 90, 20),
onScroll: (e) => {
this.scrollTop = e.target.scrollTop
}
})
})
initScrollBounce()
},
methods: {
_close (tapIndex) {
this.$emit('close', tapIndex)
},
_handleTrack: function (e) {
if (this._scroller) {
switch (e.detail.state) {
case 'start':
this._handleTouchStart(e)
disableScrollBounce({
disable: true
})
break
case 'move':
this._handleTouchMove(e)
break
case 'end':
case 'cancel':
this._handleTouchEnd(e)
disableScrollBounce({
disable: false
})
}
}
},
_handleWheel ($event) {
const deltaY = this.deltaY + $event.deltaY
if (Math.abs(deltaY) > 10) {
this.scrollTop += deltaY / 3
this.scrollTop = this.scrollTop >= this.contentHeight
? this.contentHeight
: this.scrollTop <= 0
? 0
: this.scrollTop
this._scroller.scrollTo(this.scrollTop)
} else {
this.deltaY = deltaY
}
$event.preventDefault()
}
}
}
......@@ -133,6 +268,17 @@ uni-actionsheet .uni-actionsheet__title {
cursor: pointer;
}
uni-actionsheet .uni-actionsheet__title{
position: absolute;
top: 0;
right: 0;
left: 0;
z-index: 1;
background-color: #fff;
border-radius: 5px 5px 0 0;
border-bottom: 1px solid #e5e5e5;
}
uni-actionsheet .uni-actionsheet__cell:before {
content: " ";
position: absolute;
......
......@@ -25,6 +25,7 @@
:style="_uniTabbarBdStyle(item)"
>
<img
v-if="item.iconPath"
:style="{width: item.iconWidth,height:item.iconWidth}"
:src="_getRealPath(item.iconPath)"
>
......
......@@ -28,6 +28,25 @@ export function onNetworkStatusChange (callbackId) {
}
}
export function offNetworkStatusChange (callbackId) {
// 暂不支持移除所有监听
if (callbackId) {
const index = callbackIds.indexOf(callbackId)
if (index >= 0) {
callbackIds.splice(index, 1)
}
}
if (!callbackIds.length) {
const connection = navigator.connection || navigator.webkitConnection
if (connection) {
connection.removeEventListener('change', changeHandler)
} else {
window.removeEventListener('offline', changeHandler)
window.removeEventListener('online', changeHandler)
}
}
}
export function getNetworkType () {
const connection = navigator.connection || navigator.webkitConnection
let networkType = 'unknown'
......
function setNavigationBar (type, args) {
const pages = getCurrentPages()
if (pages.length) {
const page = pages[pages.length - 1].$holder
import {
isCurrentPage,
getPageHolder
} from '../util.js'
function setNavigationBar (type, args = {}) {
const page = getPageHolder(args.__page__)
if (page) {
switch (type) {
case 'setNavigationBarColor':
{
......@@ -43,7 +46,9 @@ function setNavigationBar (type, args) {
title
} = args
page.navigationBar.titleText = title
document.title = title
if (isCurrentPage(page)) { // 仅当前页面
document.title = title
}
UniServiceJSBridge.emit('onNavigationBarChange', {
titleText: title
})
......@@ -58,12 +63,12 @@ export function setNavigationBarColor (args) {
return setNavigationBar('setNavigationBarColor', args)
}
export function showNavigationBarLoading () {
return setNavigationBar('showNavigationBarLoading')
export function showNavigationBarLoading (args) {
return setNavigationBar('showNavigationBarLoading', args)
}
export function hideNavigationBarLoading () {
return setNavigationBar('hideNavigationBarLoading')
export function hideNavigationBarLoading (args) {
return setNavigationBar('hideNavigationBarLoading', args)
}
export function setNavigationBarTitle (args) {
......
export function getPageHolder (__page__) {
if (__page__) {
return __page__.$holder
}
const pages = getCurrentPages()
const len = pages.length
if (len) {
return pages[len - 1].$holder
}
}
export function isCurrentPage (pageHolder) {
const pages = getCurrentPages()
const len = pages.length
if (len) {
return pages[len - 1].$holder === pageHolder
}
return false
}
......@@ -447,7 +447,8 @@ export default {
return val[0] * 60 + val[1]
},
_getDateValue (val) {
return val[0] * 366 + (val[1] || 0) * 31 + (val[2] || 0)
const DAY = 31
return val[0] * DAY * 12 + (val[1] || 0) * DAY + (val[2] || 0)
},
/**
* 将右侧数组值同步到左侧(交集部分)
......
......@@ -112,6 +112,36 @@ export function handleRef (ref) {
if (!ref) {
return
}
if (ref.props['data-com-type'] === 'wx') {
const eventProps = {}
let refProps = ref.props
// 初始化支付宝小程序组件事件
Object.keys(refProps).forEach(key => {
const handler = refProps[key]
const res = key.match(/^on([A-Z])(\S*)/)
if (res && typeof handler === 'function' && handler.name === 'bound handleEvent') {
const event = res && (res[1].toLowerCase() + res[2])
refProps[key] = eventProps[key] = function () {
const props = Object.assign({}, refProps)
props[key] = handler
// 由于支付宝事件可能包含多个参数,不使用微信小程序事件格式
delete props['data-com-type']
triggerEvent.bind({ props })(event, {
__args__: [...arguments]
})
}
}
})
// 处理 props 重写
Object.defineProperty(ref, 'props', {
get () {
return refProps
},
set (value) {
refProps = Object.assign(value, eventProps)
}
})
}
const refName = ref.props['data-ref']
const refInForName = ref.props['data-ref-in-for']
if (refName) {
......@@ -129,11 +159,13 @@ export function triggerEvent (type, detail, options) {
const eventOpts = this.props['data-event-opts']
const eventParams = this.props['data-event-params']
const comType = this.props['data-com-type']
const target = {
dataset: {
eventOpts,
eventParams
eventParams,
comType
}
}
......
import {
hasOwn
hasOwn,
noop
} from 'uni-shared'
import {
......@@ -24,10 +25,17 @@ export default function parseComponent (vueOptions) {
// 关于百度小程序生命周期的说明(组件作为页面时):
// lifetimes:attached --> methods:onShow --> methods:onLoad --> methods:onReady
// 这里在强制将onShow挪到onLoad之后触发,另外一处修改在page-parser.js
const oldAttached = componentOptions.lifetimes.attached
let oldAttached = componentOptions.lifetimes.attached
// 百度小程序基础库 3.260 以上支持页面 onInit 生命周期,提前创建 vm 实例
componentOptions.lifetimes.onInit = function onInit (query) {
oldAttached.call(this)
oldAttached = noop
this.pageinstance.$vm = this.$vm
this.$vm.__call_hook('onInit', query)
}
componentOptions.lifetimes.attached = function attached () {
oldAttached.call(this)
if (isPage.call(this)) { // 百度 onLoad 在 attached 之前触发
if (isPage.call(this)) { // 百度 onLoad 在 attached 之前触发(基础库小于 3.70)
// 百度 当组件作为页面时 pageinstancce 不是原来组件的 instance
this.pageinstance.$vm = this.$vm
if (hasOwn(this.pageinstance, '_$args')) {
......@@ -62,4 +70,4 @@ export default function parseComponent (vueOptions) {
delete componentOptions.methods.__l
return componentOptions
}
}
......@@ -42,7 +42,7 @@ export default function parsePage (vuePageOptions) {
}
pageOptions.methods.onLoad = function onLoad (query) {
// 百度 onLoad 在 attached 之前触发,先存储 args, 在 attached 里边触发 onLoad
// 百度 onLoad 在 attached 之前触发(基础库小于 3.70),先存储 args, 在 attached 里边触发 onLoad
if (this.$vm) {
const copyQuery = Object.assign({}, query)
delete copyQuery.__id__
......@@ -63,4 +63,4 @@ export default function parsePage (vuePageOptions) {
}
return pageOptions
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册