提交 57a15d53 编写于 作者: Q qiang

Merge branch 'alpha'

# Conflicts:
#	docs/component/video.md
......@@ -11,10 +11,20 @@ App端如需要更丰富的相机拍照API(如直接调用前置摄像头)
|sizeType|Array<String>|否|original 原图,compressed 压缩图,默认二者都有|App、微信小程序、支付宝小程序、百度小程序|
|extension|Array<String>|否|根据文件拓展名过滤,每一项都不能是空字符串。默认不过滤。|H5(HBuilder X2.9.9+)|
|sourceType|Array<String>|否|album 从相册选图,camera 使用相机,默认二者都有。如需直接开相机或直接选相册,请只使用一个选项||
|crop|Object|否|图像裁剪参数,设置后 sizeType 失效|App 3.1.19+|
|success|Function|是|成功则返回图片的本地文件路径列表 tempFilePaths||
|fail|Function|否|接口调用失败的回调函数|小程序、App|
|complete|Function|否|接口调用结束的回调函数(调用成功、失败都会执行)| |
**crop 参数说明**
|参数名|类型|必填|说明|
|:-|:-|:-|:-|
|quality|Number|否|取值范围为1-100,数值越小,质量越低(仅对jpg格式有效)。默认值为80。|
|width|Number|是|裁剪的宽度,单位为px,用于计算裁剪宽高比。|
|height|Number|是|裁剪的高度,单位为px,用于计算裁剪宽高比。|
|resize|Boolean|否|是否将width和height作为裁剪保存图片真实的像素值。默认值为true。注:设置为false时在裁剪编辑界面显示图片的像素值,设置为true时不显示|
**Tips**
- count 值在 H5 平台的表现,基于浏览器本身的规范。目前测试的结果来看,只能限制单选/多选,并不能限制数量。并且,在实际的手机浏览器很少有能够支持多选的。
......
......@@ -354,7 +354,8 @@ Tips:关于摇树优化(treeShaking)原理及优化结果,参考:[http
|workers|String|Worker 代码放置的目录。 [详见](https://developers.weixin.qq.com/miniprogram/dev/framework/workers.html)|
|optimization|Object| 对微信小程序的优化配置 |
|cloudfunctionRoot|String| 配置云开发目录,参考[setting](/collocation/manifest?id=cloudfunctionRoot)|
|uniStatistics|Object|[微信小程序是否开启 uni 统计,配置方法同全局配置](/collocation/manifest?id=uniStatistics)||
|uniStatistics|Object|[微信小程序是否开启 uni 统计,配置方法同全局配置](/collocation/manifest?id=uniStatistics)|
|scopedSlotsCompiler|String|作用域插槽编译模式,HBuilderX 3.1.19+ 开始支持,可选:legacy、auto、augmented,默认:auto|
#### setting
......@@ -431,6 +432,7 @@ Tips:关于摇树优化(treeShaking)原理及优化结果,参考:[http
|prefetches|Array|预请求的所有url的列表,[详见](https://smartprogram.baidu.com/docs/develop/tutorial/process/#prefetches) |
|optimization|Object| 对百度小程序的优化配置 |
|uniStatistics|Object|[百度小程序是否开启 uni 统计,配置方法同全局配置](/collocation/manifest?id=uniStatistics)|
|scopedSlotsCompiler|String|作用域插槽编译模式,HBuilderX 3.1.19+ 开始支持,可选:legacy、auto、augmented,默认:auto|
#### optimization
......@@ -449,6 +451,7 @@ Tips:关于摇树优化(treeShaking)原理及优化结果,参考:[http
|usingComponents|Boolean| 是否启用自定义组件模式,`v2.0+`,默认为false,[编译模式区别详情](https://ask.dcloud.net.cn/article/35843)|
|navigateToMiniProgramAppIdList |Array|需要跳转的小程序列表,[详见](https://developer.toutiao.com/dev/cn/mini-app/develop/framework/basic-reference/general-configuration) |
|uniStatistics|Object|[字节跳动小程序是否开启 uni 统计,配置方法同全局配置](/collocation/manifest?id=uniStatistics)|
|scopedSlotsCompiler|String|作用域插槽编译模式,HBuilderX 3.1.19+ 开始支持,可选:legacy、auto、augmented,默认:auto|
#### 字节跳动小程序项目设置@mp-toutiao-setting
......@@ -471,6 +474,7 @@ Tips:关于摇树优化(treeShaking)原理及优化结果,参考:[http
|groupIdList |String Array |需要打开群资料卡的群号列表,详见button的open-type |
|optimization|Object| 对QQ小程序的优化配置 |
|uniStatistics|Object|[QQ小程序是否开启 uni 统计,配置方法同全局配置](/collocation/manifest?id=uniStatistics)|
|scopedSlotsCompiler|String|作用域插槽编译模式,HBuilderX 3.1.19+ 开始支持,可选:legacy、auto、augmented,默认:auto|
#### optimization
......
......@@ -24,6 +24,7 @@
|adjust-position|Boolean|true|键盘弹起时,是否自动上推页面|App-Android(vue 页面 softinputMode 为 adjustResize 时无效)、微信小程序、百度小程序、QQ小程序|
|hold-keyboard|boolean|false|focus时,点击页面的时候不收起键盘|微信小程序2.8.2|
|auto-blur|boolean|false|键盘收起时,是否自动失去焦点|App 3.0.0+|
|verifyNumber|boolean|false|当设置`type="number"`时,是否对输入的字符执行`当前输入是否有效`判断|HBuilder 3.1.19+|
|@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}||
......@@ -36,6 +37,10 @@
- 如果遇到 value 属性设置不生效的问题参考:[组件属性设置不生效解决办法](/vue-api?id=_4-组件属性设置不生效解决办法)
- `input` 组件上有默认的 `min-height` 样式,如果 `min-height` 的值大于 `height` 的值那么 `height` 样式无效。
- H5 暂未支持动态切换,请使用 `v-if`进行整体切换。
- `verifyNumber`:是否对输入的字符执行输入是否有效判断判断
-`false`时:不执行输入是否有效判断,输入时会响应`input`事件,此时`event.detail = {value,valid}`,属性`valid`用来表明当前输入是否有效。
-`true`时:执行输入是否有效判断, 输入非数字字符将不会被赋值,也不会响应`input`事件。例如:`-(负号)`就是非数字字符。输入负数时,需要输入数字后再移动光标到数字最前面输入`-(负号)`
```html
<!-- 错误写法 -->
<input :type="isText?'text':'number'" placeholder="请输入内容" />
......
......@@ -38,6 +38,7 @@
|codec|String|hardware|解码器选择,hardware:硬解码(硬解码可以增加解码算力,提高视频清晰度。少部分老旧硬件可能存在兼容性问题);software:ffmpeg 软解码;|App-Android 3.1.0+|
|http-cache|Boolean|true|是否对 http、https 视频源开启本地缓存。缓存策略:开启了此开关的视频源,在视频播放时会在本地保存缓存文件,如果本地缓存池已超过100M,在进行缓存前会清空之前的缓存(不适用于m3u8等流媒体协议)|App-Android 3.1.0+|
|play-strategy|Number|0| 播放策略,0:普通模式,适合绝大部分视频播放场景;1:平滑播放模式(降级),增加缓冲区大小,采用open sl解码音频,避免音视频脱轨的问题,可能会降低首屏展现速度、视频帧率,出现开屏音频延迟等。 适用于高码率视频的极端场景;3: M3U8优化模式,增加缓冲区大小,提升视频加载速度和流畅度,可能会降低首屏展现速度。 适用于M3U8在线播放的场景 |App-Android 3.1.0+|
|header|Object||HTTP 请求 Header|App 3.1.19+|
|@play|EventHandle||当开始/继续播放时触发play事件|字节跳动小程序不支持|
|@pause|EventHandle||当暂停播放时触发 pause 事件|字节跳动小程序不支持|
|@ended|EventHandle||当播放到末尾时触发 ended 事件|字节跳动小程序不支持|
......
......@@ -213,9 +213,11 @@ univerifyStyle 数据结构:
"iconWidth": "45px", // 图标宽度(高度等比例缩放) 默认值:45px
"list": [
{
"provider": "apple",
"iconPath": "/static/apple.png" // 图标路径仅支持本地图片
},
{
"provider": "weixin",
"iconPath": "/static/wechat.png" // 图标路径仅支持本地图片
}
]
......@@ -262,7 +264,8 @@ uni.closeAuthView()
{
"code": "30008",
"errMsg": "用户点击了自定义按钮",
"index": 0 // 第几个按钮
"index": 0, // 第几个按钮
"provider": "apple",
}
```
......
......@@ -398,7 +398,7 @@ export default {
详细的小程序端不支持列表:
* 作用域插槽(字节小程序不支持、除支付宝小程序外仅支持解构插槽、不可使用作用域外数据
* 作用域插槽(HBuilderX 3.1.19 以下仅支持解构插槽且不可使用作用域外数据以及使用复杂的表达式
* 动态组件
* 异步组件
* ``inline-template``
......
......@@ -945,7 +945,7 @@ Vue 实现了一套内容分发的 API,将 `slot` 元素作为承载分发内
## 小程序不支持列表
- 作用域插槽(仅支持解构插槽、插槽内不支持复杂表达式且不可使用作用域外数据
- 作用域插槽(HBuilderX 3.1.19 以下仅支持解构插槽且不可使用作用域外数据以及使用复杂的表达式
- 动态组件
- 异步组件
- `inline-template`
......
......@@ -12,5 +12,5 @@
"message": "chore(release): publish %s"
}
},
"version": "2.0.0-31920210609001"
"version": "2.0.0-alpha-31920210611001"
}
......@@ -34,7 +34,6 @@
"release:v3": "npm run lint:cli && lerna publish --no-git-tag-version --force-publish=* --npm-tag=v3"
},
"dependencies": {
"@dcloudio/uni-i18n": "^0.0.3",
"base64-arraybuffer": "^0.2.0",
"intersection-observer": "^0.7.0",
"pako": "^1.0.11",
......@@ -42,6 +41,7 @@
},
"private": true,
"devDependencies": {
"@dcloudio/uni-i18n": "^2.0.0-31920210514002",
"@rollup/plugin-alias": "^3.1.0",
"@rollup/plugin-commonjs": "^11.1.0",
"@rollup/plugin-json": "^4.1.0",
......@@ -148,4 +148,4 @@
"main": "index.js",
"description": "",
"author": ""
}
}
{
"name": "@dcloudio/uni-app-plus-nvue",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app app-plus-nvue",
"main": "dist/index.js",
"repository": {
......
......@@ -900,6 +900,11 @@ function initProperties (props, isBehavior = false, file = '') {
type: Object,
value: null
};
// scopedSlotsCompiler auto
properties.scopedSlotsCompiler = {
type: String,
value: ''
};
properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type: null,
value: [],
......
......@@ -6707,7 +6707,8 @@ var serviceContext = (function () {
function chooseImage$1 ({
count,
sizeType,
sourceType
sourceType,
crop
} = {}, callbackId) {
const errorCallback = warpPlusErrorCallback(callbackId, 'chooseImage', 'cancel');
......@@ -6723,7 +6724,7 @@ var serviceContext = (function () {
// 压缩阈值 0.5 兆
const THRESHOLD = 1024 * 1024 * 0.5;
// 判断是否需要压缩
if (sizeType.includes('compressed') && size > THRESHOLD) {
if (!crop && sizeType.includes('compressed') && size > THRESHOLD) {
return compressImage$1(path).then(dstPath => {
path = dstPath;
return getFileInfo$2(path)
......@@ -6751,7 +6752,8 @@ var serviceContext = (function () {
camera.captureImage(path => successCallback([path]),
errorCallback, {
filename: TEMP_PATH + '/camera/',
resolution: 'high'
resolution: 'high',
crop
});
}
......@@ -6761,7 +6763,8 @@ var serviceContext = (function () {
multiple: true,
system: false,
filename: TEMP_PATH + '/gallery/',
permissionAlert: true
permissionAlert: true,
crop
});
}
......@@ -7801,7 +7804,8 @@ var serviceContext = (function () {
errorCallback({
code: '30008',
message: '用户点击了自定义按钮',
index
index,
provider: button.provider
});
});
};
......
{
"name": "@dcloudio/uni-app-plus",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app app-plus",
"main": "dist/index.js",
"repository": {
......
{
"name": "@dcloudio/uni-automator",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app automator",
"main": "dist/index.js",
"repository": {
......
......@@ -570,7 +570,7 @@ export default {
complete && complete()
})
},
_getCollection() {
_getCollection () {
const index = this.collection.indexOf(',')
const collection = index > 0 ? this.collection.substring(0, index) : this.collection
return collection
......
{
"name": "@dcloudio/uni-cli-shared",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-cli-shared",
"main": "lib/index.js",
"repository": {
......
{
"name": "@dcloudio/uni-h5-ui",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app h5 ui",
"main": "dist/index.umd.min.js",
"repository": {
......
......@@ -466,6 +466,19 @@
]
]
],
"setClipboardData": [
"/platforms/h5/service/api/device/clipboard.js",
[
[
"/core/helpers/protocol/device/set-clipboard-data.js",
"setClipboardData"
]
]
],
"getClipboardData": [
"/platforms/h5/service/api/device/clipboard.js",
[]
],
"vibrateLong": [
"/platforms/h5/service/api/device/vibrate.js",
[]
......
{
"name": "@dcloudio/uni-h5",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app h5",
"main": "dist/index.umd.min.js",
"repository": {
......@@ -14,7 +14,6 @@
"author": "fxy060608",
"license": "Apache-2.0",
"dependencies": {
"@dcloudio/uni-i18n": "^0.0.3",
"base64-arraybuffer": "^0.2.0",
"intersection-observer": "^0.7.0",
"pako": "^1.0.11",
......
{
"name": "@dcloudio/uni-i18n",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "@dcloudio/uni-i18n",
"main": "dist/uni-i18n.cjs.js",
"module": "dist/uni-i18n.esm.js",
......
{
"name": "@dcloudio/uni-migration",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app migration",
"main": "lib/index.js",
"repository": {
......
......@@ -1636,6 +1636,11 @@ function initProperties (props, isBehavior = false, file = '') {
type: Object,
value: null
};
// scopedSlotsCompiler auto
properties.scopedSlotsCompiler = {
type: String,
value: ''
};
properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type: null,
value: [],
......
{
"name": "@dcloudio/uni-mp-alipay",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app mp-alipay",
"main": "dist/index.js",
"repository": {
......
......@@ -1313,6 +1313,11 @@ function initProperties (props, isBehavior = false, file = '') {
type: Object,
value: null
};
// scopedSlotsCompiler auto
properties.scopedSlotsCompiler = {
type: String,
value: ''
};
properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type: null,
value: [],
......@@ -1883,7 +1888,8 @@ const mocks = ['nodeId', 'componentName', '_componentId', 'uniquePrefix'];
function isPage () {
// 百度小程序组件的id,某些情况下可能是number类型的0,不能直接return !this.ownerId 判断当前组件是否是Page
// 否则会导致mounted不执行
return typeof this.ownerId === 'undefined'
// 基础库 3.290.33 及以上 ownerId 为 null
return typeof this.ownerId === 'undefined' || this.ownerId === null
}
function initRelation (detail) {
......
{
"name": "@dcloudio/uni-mp-baidu",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app mp-baidu",
"main": "dist/index.js",
"repository": {
......
......@@ -1072,6 +1072,11 @@ function initProperties (props, isBehavior = false, file = '') {
type: Object,
value: null
};
// scopedSlotsCompiler auto
properties.scopedSlotsCompiler = {
type: String,
value: ''
};
properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type: null,
value: [],
......
{
"name": "@dcloudio/uni-mp-kuaishou",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app mp-kuaishou",
"main": "dist/index.js",
"repository": {
......
......@@ -1233,6 +1233,11 @@ function initProperties (props, isBehavior = false, file = '') {
type: Object,
value: null
};
// scopedSlotsCompiler auto
properties.scopedSlotsCompiler = {
type: String,
value: ''
};
properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type: null,
value: [],
......
{
"name": "@dcloudio/uni-mp-qq",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app mp-qq",
"main": "dist/index.js",
"repository": {
......
......@@ -1325,6 +1325,11 @@ function initProperties (props, isBehavior = false, file = '') {
type: Object,
value: null
};
// scopedSlotsCompiler auto
properties.scopedSlotsCompiler = {
type: String,
value: ''
};
properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type: null,
value: [],
......@@ -2121,34 +2126,50 @@ function parseBaseComponent (vueComponentOptions, {
return [componentOptions, VueComponent]
}
const components = [];
function parseComponent (vueOptions) {
const [componentOptions, VueComponent] = parseBaseComponent(vueOptions);
// 基础库 2.0 以上 attached 顺序错乱,按照 created 顺序强制纠正
componentOptions.lifetimes.created = function created () {
components.push(this);
};
componentOptions.lifetimes.attached = function attached () {
const properties = this.properties;
this.__lifetimes_attached = function () {
const properties = this.properties;
const options = {
mpType: isPage.call(this) ? 'page' : 'component',
mpInstance: this,
propsData: properties
};
const options = {
mpType: isPage.call(this) ? 'page' : 'component',
mpInstance: this,
propsData: properties
};
initVueIds(properties.vueId, this);
initVueIds(properties.vueId, this);
// 初始化 vue 实例
this.$vm = new VueComponent(options);
// 初始化 vue 实例
this.$vm = new VueComponent(options);
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
initSlots(this.$vm, properties.vueSlots);
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
initSlots(this.$vm, properties.vueSlots);
// 处理父子关系
initRelation.call(this, {
vuePid: this._$vuePid,
mpInstance: this
});
// 处理父子关系
initRelation.call(this, {
vuePid: this._$vuePid,
mpInstance: this
});
// 触发首次 setData
this.$vm.$mount();
// 触发首次 setData
this.$vm.$mount();
};
let component = this;
while (component && component.__lifetimes_attached && components[0] && component === components[0]) {
components.shift();
component.__lifetimes_attached();
delete component.__lifetimes_attached;
component = components[0];
}
};
// ready 比 handleLink 还早,初始化逻辑放到 handleLink 中
......
{
"name": "@dcloudio/uni-mp-toutiao",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app mp-toutiao",
"main": "dist/index.js",
"repository": {
......
{
"name": "@dcloudio/uni-mp-vue",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "@dcloudio/uni-mp-vue",
"main": "dist/vue.runtime.esm.js",
"module": "dist/vue.runtime.esm.js",
......
......@@ -969,6 +969,11 @@ function initProperties (props, isBehavior = false, file = '') {
type: Object,
value: null
};
// scopedSlotsCompiler auto
properties.scopedSlotsCompiler = {
type: String,
value: ''
};
properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type: null,
value: [],
......
{
"name": "@dcloudio/uni-mp-weixin",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app mp-weixin",
"main": "dist/index.js",
"repository": {
......
{
"name": "@dcloudio/uni-quickapp-native",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app quickapp-native",
"main": "dist/vue.prod.js",
"repository": {
......
......@@ -1039,6 +1039,11 @@ function initProperties (props, isBehavior = false, file = '') {
type: Object,
value: null
};
// scopedSlotsCompiler auto
properties.scopedSlotsCompiler = {
type: String,
value: ''
};
properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type: null,
value: [],
......@@ -1477,7 +1482,8 @@ const mocks = ['nodeId', 'componentName', '_componentId', 'uniquePrefix'];
function isPage () {
// 百度小程序组件的id,某些情况下可能是number类型的0,不能直接return !this.ownerId 判断当前组件是否是Page
// 否则会导致mounted不执行
return typeof this.ownerId === 'undefined'
// 基础库 3.290.33 及以上 ownerId 为 null
return typeof this.ownerId === 'undefined' || this.ownerId === null
}
function findVmByVueId (vm, vuePid) {
......
{
"name": "@dcloudio/uni-quickapp-webview",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app quickapp-webview",
"main": "dist/index.js",
"repository": {
......
{
"name": "@dcloudio/uni-stat",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "",
"main": "dist/index.js",
"repository": {
......
......@@ -87,6 +87,49 @@ describe('mp:compiler-mp-alipay', () => {
)
})
it('generate scoped slot with scopedSlotsCompiler: auto', () => {
assertCodegen(
'<my-component><template v-slot="{item}">{{item}}<template></my-component>',
'<my-component vue-id="551070e6-1" onVueInit="__l"><view slot-scope="__SCOPED__">{{__SCOPED__.item}}</view></my-component>',
'with(this){}',
{
scopedSlotsCompiler: 'auto'
}
)
assertCodegen(
'<my-component><template v-slot="{item}">{{getValue(item)}}<template></my-component>',
'<my-component scoped-slots-compiler="augmented" vue-id="551070e6-1" onVueInit="__l"><block><block a:if="{{$root.m0}}">{{$root.m1}}</block></block></my-component>',
'with(this){var m0=$hasScopedSlotsParams("551070e6-1");var m1=m0?getValue($getScopedSlotsParams("551070e6-1","default","item")):null;$mp.data=Object.assign({},{$root:{m0:m0,m1:m1}})}',
{
scopedSlotsCompiler: 'auto'
}
)
assertCodegen(
'<my-component><template v-slot="item">{{getValue(item.text)}}<template></my-component>',
'<my-component scoped-slots-compiler="augmented" vue-id="551070e6-1" onVueInit="__l"><block><block a:if="{{$root.m0}}">{{$root.m1}}</block></block></my-component>',
'with(this){var m0=$hasScopedSlotsParams("551070e6-1");var m1=m0?getValue($getScopedSlotsParams("551070e6-1","default").text):null;$mp.data=Object.assign({},{$root:{m0:m0,m1:m1}})}',
{
scopedSlotsCompiler: 'auto'
}
)
assertCodegen(
'<view><slot :item="item"><slot></view>',
'<view><block a:if="{{$slots.$default}}"><slot item="{{item}}"></slot></block><block a:else><slot></slot></block></view>',
'with(this){if($scope.props.scopedSlotsCompiler==="augmented"){const $root=$mp.data.$root;$setScopedSlotsParams("default",{"item":item})}}',
{
scopedSlotsCompiler: 'auto'
}
)
assertCodegen(
'<view><slot v-bind="object"><slot></view>',
'<view><block a:if="{{$slots.$default}}"><slot></slot></block><block a:else><slot></slot></block></view>',
'with(this){if($scope.props.scopedSlotsCompiler==="augmented"){const $root=$mp.data.$root;$setScopedSlotsParams("default",object)}}',
{
scopedSlotsCompiler: 'auto'
}
)
})
it('generate class binding', () => {
assertCodegen(
'<div :class="{ active: isActive }">1</div>',
......
......@@ -65,6 +65,49 @@ describe('mp:compiler-mp-baidu', () => {
)
})
it('generate scoped slot with scopedSlotsCompiler: auto', () => {
assertCodegen(
'<my-component><template v-slot="{item}">{{item}}<template></my-component>',
'<my-component vue-id="551070e6-1" vue-slots="{{[\'default\']}}"><view>{{item}}</view></my-component>',
'with(this){}',
{
scopedSlotsCompiler: 'auto'
}
)
assertCodegen(
'<my-component><template v-slot="{item}">{{getValue(item)}}<template></my-component>',
'<my-component scoped-slots-compiler="augmented" vue-id="551070e6-1" vue-slots="{{[\'default\']}}"><block><block s-if="{{$root.m0}}">{{$root.m1}}</block></block></my-component>',
'with(this){var m0=$hasScopedSlotsParams("551070e6-1");var m1=m0?getValue($getScopedSlotsParams("551070e6-1","default","item")):null;$mp.data=Object.assign({},{$root:{m0:m0,m1:m1}})}',
{
scopedSlotsCompiler: 'auto'
}
)
assertCodegen(
'<my-component><template v-slot="item">{{getValue(item.text)}}<template></my-component>',
'<my-component scoped-slots-compiler="augmented" vue-id="551070e6-1" vue-slots="{{[\'default\']}}"><block><block s-if="{{$root.m0}}">{{$root.m1}}</block></block></my-component>',
'with(this){var m0=$hasScopedSlotsParams("551070e6-1");var m1=m0?getValue($getScopedSlotsParams("551070e6-1","default").text):null;$mp.data=Object.assign({},{$root:{m0:m0,m1:m1}})}',
{
scopedSlotsCompiler: 'auto'
}
)
assertCodegen(
'<view><slot :item="item"><slot></view>',
'<view><block s-if="{{$slots.default}}"><slot var-item="item"></slot></block><block s-else><slot></slot></block></view>',
'with(this){if($scope.data.scopedSlotsCompiler==="augmented"){const $root=$mp.data.$root;$setScopedSlotsParams("default",{"item":item})}}',
{
scopedSlotsCompiler: 'auto'
}
)
assertCodegen(
'<view><slot v-bind="object"><slot></view>',
'<view><block s-if="{{$slots.default}}"><slot></slot></block><block s-else><slot></slot></block></view>',
'with(this){if($scope.data.scopedSlotsCompiler==="augmented"){const $root=$mp.data.$root;$setScopedSlotsParams("default",object)}}',
{
scopedSlotsCompiler: 'auto'
}
)
})
it('generate vue id', () => {
assertCodegen(
'<Test/>',
......
......@@ -82,13 +82,64 @@ describe('mp:compiler-mp-weixin', () => {
)
})
it('generate scoped slot with filter', () => {
it('generate scoped slot with scopedSlotsCompiler: auto', () => {
assertCodegen(
'<my-component><template v-slot="{item}">{{item}}<template></my-component>',
'<my-component generic:scoped-slots-default="test-my-component-default" data-vue-generic="scoped" vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"></my-component>',
'with(this){}',
{
scopedSlotsCompiler: 'auto'
}
)
assertCodegen(
'<my-component><template v-slot="{item}">{{getValue(item)}}<template></my-component>',
'<my-component scoped-slots-compiler="augmented" vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"><block><block wx:if="{{$root.m0}}">{{$root.m1}}</block></block></my-component>',
'with(this){var m0=$hasScopedSlotsParams("551070e6-1");var m1=m0?getValue($getScopedSlotsParams("551070e6-1","default","item")):null;$mp.data=Object.assign({},{$root:{m0:m0,m1:m1}})}',
{
scopedSlotsCompiler: 'auto'
}
)
assertCodegen(
'<my-component><template v-slot="item">{{getValue(item.text)}}<template></my-component>',
'<my-component scoped-slots-compiler="augmented" vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"><block><block wx:if="{{$root.m0}}">{{$root.m1}}</block></block></my-component>',
'with(this){var m0=$hasScopedSlotsParams("551070e6-1");var m1=m0?getValue($getScopedSlotsParams("551070e6-1","default").text):null;$mp.data=Object.assign({},{$root:{m0:m0,m1:m1}})}',
{
scopedSlotsCompiler: 'auto'
}
)
assertCodegen(
'<view><slot :item="item"><slot></view>',
'<view><block wx:if="{{$slots.default}}"><slot></slot><scoped-slots-default item="{{item}}" class="scoped-ref" bind:__l="__l"></scoped-slots-default></block><block wx:else><slot></slot></block></view>',
'with(this){if($scope.data.scopedSlotsCompiler==="augmented"){const $root=$mp.data.$root;$setScopedSlotsParams("default",{"item":item})}}',
{
scopedSlotsCompiler: 'auto'
}
)
assertCodegen(
'<view><slot :item="getValue(item)"><slot></view>',
'<view><block wx:if="{{$slots.default}}"><slot></slot><scoped-slots-default item="{{$root.m0}}" class="scoped-ref" bind:__l="__l"></scoped-slots-default></block><block wx:else><slot></slot></block></view>',
'with(this){var m0=getValue(item);$mp.data=Object.assign({},{$root:{m0:m0}});if($scope.data.scopedSlotsCompiler==="augmented"){const $root=$mp.data.$root;$setScopedSlotsParams("default",{"item":$root.m0})}}',
{
scopedSlotsCompiler: 'auto'
}
)
assertCodegen(
'<view><slot v-bind="object"><slot></view>',
'<view><block wx:if="{{$slots.default}}"><slot></slot></block><block wx:else><slot></slot></block></view>',
'with(this){if($scope.data.scopedSlotsCompiler==="augmented"){const $root=$mp.data.$root;$setScopedSlotsParams("default",object)}}',
{
scopedSlotsCompiler: 'auto'
}
)
})
it('generate scoped slot with scopedSlotsCompiler: augmented', () => {
assertCodegen(
'<my-component><template v-slot="{item}">{{getValue(item)}}<template></my-component>',
'<my-component vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"><block><block wx:if="{{$root.m0}}">{{$root.m1}}</block></block></my-component>',
'with(this){var m0=$hasScopedSlotsParams("551070e6-1");var m1=m0?getValue($getScopedSlotsParams("551070e6-1","default","item")):null;$mp.data=Object.assign({},{$root:{m0:m0,m1:m1}})}',
{
betterScopedSlots: true
scopedSlotsCompiler: 'augmented'
}
)
assertCodegen(
......@@ -96,7 +147,7 @@ describe('mp:compiler-mp-weixin', () => {
'<my-component vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"><block><block wx:if="{{$root.m0}}">{{$root.m1}}</block></block></my-component>',
'with(this){var m0=$hasScopedSlotsParams("551070e6-1");var m1=m0?getValue($getScopedSlotsParams("551070e6-1","default").text):null;$mp.data=Object.assign({},{$root:{m0:m0,m1:m1}})}',
{
betterScopedSlots: true
scopedSlotsCompiler: 'augmented'
}
)
assertCodegen(
......@@ -104,7 +155,15 @@ describe('mp:compiler-mp-weixin', () => {
'<view><block wx:if="{{$slots.default}}"><slot></slot></block><block wx:else><slot></slot></block></view>',
'with(this){$setScopedSlotsParams("default",{"item":item})}',
{
betterScopedSlots: true
scopedSlotsCompiler: 'augmented'
}
)
assertCodegen(
'<view><slot :item="getValue(item)"><slot></view>',
'<view><block wx:if="{{$slots.default}}"><slot></slot></block><block wx:else><slot></slot></block></view>',
'with(this){$setScopedSlotsParams("default",{"item":getValue(item)})}',
{
scopedSlotsCompiler: 'augmented'
}
)
assertCodegen(
......@@ -112,7 +171,7 @@ describe('mp:compiler-mp-weixin', () => {
'<view><block wx:if="{{$slots.default}}"><slot></slot></block><block wx:else><slot></slot></block></view>',
'with(this){$setScopedSlotsParams("default",object)}',
{
betterScopedSlots: true
scopedSlotsCompiler: 'augmented'
}
)
})
......
......@@ -114,7 +114,22 @@ module.exports = function traverse (ast, state) {
}
if (renderSlotStatementArray.length) {
blockStatementBody.push(...renderSlotStatementArray)
if (state.options.scopedSlotsCompiler === 'auto') {
const node = t.ifStatement(
t.binaryExpression('===',
t.memberExpression(t.memberExpression(t.identifier('$scope'), t.identifier(state.options.platform.name === 'mp-alipay' ? 'props' : 'data')), t.identifier('scopedSlotsCompiler')), t.stringLiteral('augmented')
),
t.blockStatement([
t.variableDeclaration('const', [t.variableDeclarator(t.identifier('$root'),
t.memberExpression(t.memberExpression(t.identifier('$mp'), t.identifier('data')), t.identifier('$root'))
)]),
...renderSlotStatementArray
])
)
blockStatementBody.push(node)
} else {
blockStatementBody.push(...renderSlotStatementArray)
}
}
reIdentifier(identifierArray)
......
......@@ -15,13 +15,15 @@ module.exports = function getRenderSlot (path, state) {
const newProperties = []
propertiesPath.forEach(path => {
const properties = path.get('key').isStringLiteral({ value: 'SLOT_DEFAULT' }) ? oldProperties : newProperties
properties.push(path.node)
properties.push(state.options.scopedSlotsCompiler === 'auto' ? path.node : t.cloneDeep(path.node))
})
if (!newProperties.length) {
return
}
valueNode = t.objectExpression(newProperties)
arg2.replaceWith(t.objectExpression(oldProperties))
if (state.options.scopedSlotsCompiler !== 'auto') {
arg2.replaceWith(t.objectExpression(oldProperties))
}
} else {
valueNode = arg2.node
}
......
const t = require('@babel/types')
const {
METHOD_BUILT_IN,
METHOD_CREATE_EMPTY_VNODE
} = require('../../constants')
function needSlotMode (path, ids) {
let need
path.traverse({
noScope: false,
Identifier (path) {
const name = path.node.name
if (path.key !== 'key' && (path.key !== 'property' || path.parent.computed)) {
// 使用方法或作用域外数据
if (name in ids) {
need = path.key === 'callee' ? true : need
} else if (!path.scope.hasBinding(name) && !METHOD_BUILT_IN.includes(name)) {
need = true
}
}
}
})
return need
}
function replaceId (path, ids) {
let replaced
path.traverse({
......@@ -26,11 +46,11 @@ module.exports = function getResolveScopedSlots (parent, state) {
if (!params) {
return
}
const vueId = parent.parentPath.parentPath.get('properties').find(path => path.get('key').isIdentifier({ name: 'attrs' })).get('value').get('properties').find(path => path.get('key').isStringLiteral({ value: 'vue-id' })).get('value').node.value
const vueId = parent.parentPath.parentPath.get('properties').find(path => path.get('key').isIdentifier({ name: 'attrs' })).get('value').get('properties').find(path => path.get('key').isStringLiteral({ value: 'vue-id' })).get('value').node
const slot = properties.find(path => path.get('key').isIdentifier({ name: 'key' })).get('value').node.value
const ids = {}
function updateIds (vueId, slot, value, key) {
const array = [t.stringLiteral(vueId), t.stringLiteral(slot)]
const array = [vueId, t.stringLiteral(slot)]
if (key) {
array.push(t.stringLiteral(key))
}
......@@ -44,11 +64,15 @@ module.exports = function getResolveScopedSlots (parent, state) {
updateIds(vueId, slot, params.node.name)
}
const fnBody = fn.get('value.body')
if (replaceId(fnBody, ids)) {
const orgin = fnBody.get('body.0.argument')
const elements = orgin.get('elements')
const node = (elements.length === 1 ? elements[0] : orgin).node
const test = t.callExpression(t.identifier('$hasScopedSlotsParams'), [t.stringLiteral(vueId)])
orgin.replaceWith(t.arrayExpression([t.conditionalExpression(test, node, t.callExpression(t.identifier(METHOD_CREATE_EMPTY_VNODE), []))]))
if (needSlotMode(fnBody, ids)) {
if (replaceId(fnBody, ids)) {
const orgin = fnBody.get('body.0.argument')
const elements = orgin.get('elements')
const node = (elements.length === 1 ? elements[0] : orgin).node
const test = t.callExpression(t.identifier('$hasScopedSlotsParams'), [vueId])
orgin.replaceWith(t.arrayExpression([t.conditionalExpression(test, node, t.callExpression(t.identifier(METHOD_CREATE_EMPTY_VNODE), []))]))
// scopedSlotsCompiler auto
parent.get('arguments.0.elements.0').node.scopedSlotsCompiler = 'augmented'
}
}
}
......@@ -221,7 +221,7 @@ module.exports = {
this
)
)
} else if (this.options.betterScopedSlots) {
} else if (this.options.scopedSlotsCompiler === 'auto' || this.options.scopedSlotsCompiler === 'augmented') {
if (methodName === METHOD_RESOLVE_SCOPED_SLOTS) {
getResolveScopedSlots(path, this)
} else if (methodName === METHOD_RENDER_SLOT) {
......
......@@ -304,7 +304,7 @@ function traverseRenderSlot (callExprNode, state) {
const slotName = callExprNode.arguments[0].value
let deleteSlotName = false // 标记是否组件 slot 手动指定了 name="default"
if (!state.options.betterScopedSlots && callExprNode.arguments.length > 2) { // 作用域插槽
if (state.options.scopedSlotsCompiler !== 'augmented' && callExprNode.arguments.length > 2) { // 作用域插槽
const props = {}
callExprNode.arguments[2].properties.forEach(property => {
props[property.key.value] = genCode(property.value)
......@@ -369,11 +369,11 @@ function traverseResolveScopedSlots (callExprNode, state) {
})
const slotName = keyProperty.value.value
const returnExprNodes = fnProperty.value.body.body[0].argument
if (!state.options.betterScopedSlots && !proxyProperty) {
const parentNode = callExprNode.$node
if (slotNode.scopedSlotsCompiler !== 'augmented' && !proxyProperty) {
const resourcePath = state.options.resourcePath
const ownerName = path.basename(resourcePath, path.extname(resourcePath))
const parentNode = callExprNode.$node
const parentName = parentNode.type
const paramExprNode = fnProperty.value.params[0]
......@@ -397,6 +397,9 @@ function traverseResolveScopedSlots (callExprNode, state) {
state
)
}
if (state.options.scopedSlotsCompiler === 'auto' && slotNode.scopedSlotsCompiler === 'augmented') {
parentNode.attr['scoped-slots-compiler'] = 'augmented'
}
const children = normalizeChildren(traverseExpr(returnExprNodes, state))
// 除百度、字节外其他小程序仅默认插槽可以支持多个节点
if (single(children, slotName, ['template', 'block'])) {
......
{
"name": "@dcloudio/uni-template-compiler",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-template-compiler",
"main": "lib/index.js",
"repository": {
......
{
"name": "@dcloudio/vue-cli-plugin-hbuilderx",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "HBuilderX plugin for vue-cli 3",
"main": "index.js",
"repository": {
......
{
"name": "@dcloudio/vue-cli-plugin-uni-optimize",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app optimize plugin for vue-cli 3",
"main": "index.js",
"repository": {
......
......@@ -261,9 +261,10 @@ if (platformOptions.usingComponents === true) {
}
}
if (platformOptions.betterScopedSlots) {
process.env.BETTER_SCOPED_SLOTS = true
}
// 兼容历史配置 betterScopedSlots
const modes = ['legacy', 'auto', 'augmented']
const scopedSlotsCompiler = !platformOptions.scopedSlotsCompiler && platformOptions.betterScopedSlots ? modes[2] : platformOptions.scopedSlotsCompiler
process.env.SCOPED_SLOTS_COMPILER = modes.includes(scopedSlotsCompiler) ? scopedSlotsCompiler : modes[1]
if (
process.env.UNI_USING_COMPONENTS ||
......
{
"name": "@dcloudio/vue-cli-plugin-uni",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app plugin for vue-cli 3",
"main": "index.js",
"repository": {
......@@ -17,7 +17,7 @@
"author": "fxy060608",
"license": "Apache-2.0",
"dependencies": {
"@dcloudio/uni-stat": "^2.0.0-31920210609001",
"@dcloudio/uni-stat": "^2.0.0-alpha-31920210611001",
"buffer-json": "^2.0.0",
"copy-webpack-plugin": "^5.1.1",
"cross-env": "^5.2.0",
......
......@@ -15,6 +15,16 @@ const EMPTY_COMPONENT = 'Component({})'
const usingComponentsMap = {}
// 百度小程序动态组件库 usingSwanComponents 引用组件
const mpBaiduDynamicLibs = [
'dynamicLib://editorLib/editor',
'dynamicLib://echartsLib/chart',
'dynamicLib://myModelviewer/modelviewer',
'dynamicLib://myDynamicLib/panoviewer',
'dynamicLib://myDynamicLib/spintileviewer',
'dynamicLib://myDynamicLib/vrvideo'
]
function analyzeUsingComponents () {
if (!process.env.UNI_OPT_SUBPACKAGES) {
return
......@@ -130,13 +140,15 @@ module.exports = function generateJson (compilation) {
const value = usingComponents[key]
if (value.includes('://')) {
/**
* 百度小程序部分组件(如:editor)使用‘usingSwanComponents’ 引入
* 部分组件(如:swan-sitemap-list)使用'usingComponents'引入
* 经测试,两者保留都不会报错,因此去除以下 delete 语句
* 部分动态库组件(如:editor)使用‘usingSwanComponents’ 引入
* 部分动态库组件(如:swan-sitemap-list)使用'usingComponents'引入
* 做白名单机制
*/
// delete usingComponents[key]
jsonObj.usingSwanComponents = jsonObj.usingSwanComponents || {}
jsonObj.usingSwanComponents[key] = value
if (mpBaiduDynamicLibs.includes(value)) {
delete usingComponents[key]
jsonObj.usingSwanComponents = jsonObj.usingSwanComponents || {}
jsonObj.usingSwanComponents[key] = value
}
}
})
}
......
......@@ -66,7 +66,7 @@ module.exports = function (content, map) {
Object.assign(vueLoaderOptions.options.compilerOptions, {
mp: {
platform: process.env.UNI_PLATFORM,
betterScopedSlots: process.env.BETTER_SCOPED_SLOTS
scopedSlotsCompiler: process.env.SCOPED_SLOTS_COMPILER
},
filterModules,
filterTagName,
......
{
"name": "@dcloudio/webpack-uni-mp-loader",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "webpack-uni-mp-loader",
"main": "index.js",
"repository": {
......
......@@ -74,6 +74,10 @@ module.exports = function (pagesJson, manifestJson) {
app.plugins = platformJson.plugins
}
if (platformJson.useDynamicPlugins) {
app.useDynamicPlugins = true
}
if (app.usingComponents) {
updateAppJsonUsingComponents(app.usingComponents)
}
......@@ -81,6 +85,7 @@ module.exports = function (pagesJson, manifestJson) {
const project = Object.assign({}, manifestJson['mp-alipay'] || {})
delete project.usingComponents
delete project.plugins
delete project.useDynamicPlugins
return [{
name: 'app',
......
{
"name": "@dcloudio/webpack-uni-pages-loader",
"version": "2.0.0-31920210609001",
"version": "2.0.0-alpha-31920210611001",
"description": "uni-app pages.json loader",
"main": "lib/index.js",
"repository": {
......@@ -21,7 +21,7 @@
"strip-json-comments": "^2.0.1"
},
"uni-app": {
"compilerVersion": "3.1.18"
"compilerVersion": "3.1.19"
},
"gitHead": "2033cd540cff5d8469ff77e87779cd4daa5c9121"
}
......@@ -237,6 +237,11 @@ export function initProperties (props, isBehavior = false, file = '') {
type: Object,
value: null
}
// scopedSlotsCompiler auto
properties.scopedSlotsCompiler = {
type: String,
value: ''
}
properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type: null,
value: [],
......@@ -572,4 +577,4 @@ export function handleEvent (event) {
) {
return ret[0]
}
}
}
......@@ -16,6 +16,7 @@ import HTMLParser from 'uni-helpers/html-parser'
import * as formats from './formats'
import loadScript from './load-script'
let textChanging = false
export default {
name: 'Editor',
mixins: [subscriber, emitter, keyboard],
......@@ -149,11 +150,14 @@ export default {
const path = this.$getRealPath(src)
quill.insertEmbed(range.index, 'image', path, Quill.sources.USER)
const local = /^(file|blob):/.test(path) ? path : false
// 防止 formatText 多次触发 Quill.events.TEXT_CHANGE 事件
textChanging = true
quill.formatText(range.index, 1, 'data-local', local)
quill.formatText(range.index, 1, 'alt', alt)
quill.formatText(range.index, 1, 'width', width)
quill.formatText(range.index, 1, 'height', height)
quill.formatText(range.index, 1, 'class', extClass)
textChanging = false
quill.formatText(range.index, 1, 'data-custom', Object.keys(data).map(key => `${key}=${data[key]}`).join('&'))
quill.setSelection(range.index + 1, Quill.sources.SILENT)
}
......@@ -262,7 +266,9 @@ export default {
})
})
quill.on(Quill.events.TEXT_CHANGE, () => {
this.$trigger('input', {}, this.getContents())
if (!textChanging) {
this.$trigger('input', {}, this.getContents())
}
})
quill.on(Quill.events.SELECTION_CHANGE, this.updateStatus.bind(this))
quill.on(Quill.events.SCROLL_OPTIMIZE, () => {
......
......@@ -94,6 +94,10 @@ export default {
confirmType: {
type: String,
default: 'done'
},
verifyNumber: {
type: Boolean,
default: false
}
},
data () {
......@@ -179,20 +183,21 @@ export default {
}
if (~NUMBER_TYPES.indexOf(this.type)) {
// 在输入 - 负号 的情况下,event.target.value没有值,但是会触发校验 false,因此做此处理
// 在输入 - 负号 的情况下,event.target.value没有值,但是会触发校验 false
this.valid = this.$refs.input.validity && this.$refs.input.validity.valid
this.cachedValue = this.valueSync
// 处理部分输入法可以输入其它字符的情况
// 上一处理导致无法输入 - ,因此去除
/* if (this.$refs.input.validity && !this.$refs.input.validity.valid) {
$event.target.value = this.cachedValue
this.valueSync = $event.target.value
// 输入非法字符不触发 input 事件
return
} else {
if (!this.verifyNumber) {
this.cachedValue = this.valueSync
} */
} else {
// 处理部分输入法可以输入其它字符的情况,此处理无法先输入 -(负号),只能输入数字再移动光标输入负号
if (this.$refs.input.validity && !this.valid) {
$event.target.value = this.cachedValue
this.valueSync = $event.target.value
// 输入非法字符不触发 input 事件
return
} else {
this.cachedValue = this.valueSync
}
}
}
// type="number" 不支持 maxlength 属性,因此需要主动限制长度。
......@@ -205,9 +210,16 @@ export default {
return
}
}
this.$triggerInput($event, {
this.$triggerInput($event, Object.assign({
value: this.valueSync
}, force)
}, (() => {
if (!this.verifyNumber) {
return {
valid: this.valid
}
}
})()), force)
},
_onComposition ($event) {
if ($event.type === 'compositionstart') {
......
......@@ -49,7 +49,8 @@ function compressImage (tempFilePath) {
export function chooseImage ({
count,
sizeType,
sourceType
sourceType,
crop
} = {}, callbackId) {
const errorCallback = warpPlusErrorCallback(callbackId, 'chooseImage', 'cancel')
......@@ -65,7 +66,7 @@ export function chooseImage ({
// 压缩阈值 0.5 兆
const THRESHOLD = 1024 * 1024 * 0.5
// 判断是否需要压缩
if (sizeType.includes('compressed') && size > THRESHOLD) {
if (!crop && sizeType.includes('compressed') && size > THRESHOLD) {
return compressImage(path).then(dstPath => {
path = dstPath
return getFileInfo(path)
......@@ -93,7 +94,8 @@ export function chooseImage ({
camera.captureImage(path => successCallback([path]),
errorCallback, {
filename: TEMP_PATH + '/camera/',
resolution: 'high'
resolution: 'high',
crop
})
}
......@@ -103,7 +105,8 @@ export function chooseImage ({
multiple: true,
system: false,
filename: TEMP_PATH + '/gallery/',
permissionAlert: true
permissionAlert: true,
crop
})
}
......
......@@ -146,7 +146,8 @@ function univerifyButtonsClickHandling (univerifyStyle, errorCallback) {
errorCallback({
code: '30008',
message: '用户点击了自定义按钮',
index
index,
provider: button.provider
})
})
}
......
......@@ -61,7 +61,9 @@ const attrs = [
'showLoading',
'codec',
'httpCache',
'playStrategy'
'playStrategy',
'header',
'advanced'
]
export default {
......@@ -169,6 +171,18 @@ export default {
playStrategy: {
type: [Number, String],
default: 0
},
header: {
type: Object,
defult () {
return {}
}
},
advanced: {
type: Array,
defult () {
return []
}
}
},
computed: {
......
......@@ -13,8 +13,8 @@ export default [
'startGyroscope',
'stopGyroscope',
'scanCode',
'setClipboardData',
'getClipboardData',
// 'setClipboardData',
// 'getClipboardData',
'setScreenBrightness',
'getScreenBrightness',
'setKeepScreenOn',
......
export function getClipboardData () {
const pasteText = document.getElementById('#clipboard')
const data = pasteText ? pasteText.value : undefined
if (data) {
return {
data,
errMsg: 'getClipboardData:ok'
}
} else {
return {
errMsg: 'getClipboardData:fail'
}
}
}
export function setClipboardData ({
data
}) {
const pasteText = document.getElementById('#clipboard')
pasteText && pasteText.remove()
const textarea = document.createElement('textarea')
textarea.id = '#clipboard'
textarea.style.position = 'absolute'
textarea.style.top = '0'
textarea.style.zIndex = '-9999'
document.body.appendChild(textarea)
textarea.value = data
textarea.focus()
textarea.select()
const result = document.execCommand('Copy', false, null)
if (result) {
uni.showToast({
title: '复制成功',
icon: 'none'
})
return {
errMsg: 'setClipboardData:ok'
}
} else {
return {
errMsg: 'setClipboardData:fail'
}
}
}
......@@ -3,7 +3,8 @@ export const mocks = ['nodeId', 'componentName', '_componentId', 'uniquePrefix']
export function isPage () {
// 百度小程序组件的id,某些情况下可能是number类型的0,不能直接return !this.ownerId 判断当前组件是否是Page
// 否则会导致mounted不执行
return typeof this.ownerId === 'undefined'
// 基础库 3.290.33 及以上 ownerId 为 null
return typeof this.ownerId === 'undefined' || this.ownerId === null
}
export function initRelation (detail) {
......
......@@ -11,34 +11,50 @@ import {
import parseBaseComponent from '../../../mp-weixin/runtime/wrapper/component-base-parser'
const components = []
export default function parseComponent (vueOptions) {
const [componentOptions, VueComponent] = parseBaseComponent(vueOptions)
// 基础库 2.0 以上 attached 顺序错乱,按照 created 顺序强制纠正
componentOptions.lifetimes.created = function created () {
components.push(this)
}
componentOptions.lifetimes.attached = function attached () {
const properties = this.properties
this.__lifetimes_attached = function () {
const properties = this.properties
const options = {
mpType: isPage.call(this) ? 'page' : 'component',
mpInstance: this,
propsData: properties
}
const options = {
mpType: isPage.call(this) ? 'page' : 'component',
mpInstance: this,
propsData: properties
}
initVueIds(properties.vueId, this)
initVueIds(properties.vueId, this)
// 初始化 vue 实例
this.$vm = new VueComponent(options)
// 初始化 vue 实例
this.$vm = new VueComponent(options)
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
initSlots(this.$vm, properties.vueSlots)
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
initSlots(this.$vm, properties.vueSlots)
// 处理父子关系
initRelation.call(this, {
vuePid: this._$vuePid,
mpInstance: this
})
// 处理父子关系
initRelation.call(this, {
vuePid: this._$vuePid,
mpInstance: this
})
// 触发首次 setData
this.$vm.$mount()
// 触发首次 setData
this.$vm.$mount()
}
let component = this
while (component && component.__lifetimes_attached && components[0] && component === components[0]) {
components.shift()
component.__lifetimes_attached()
delete component.__lifetimes_attached
component = components[0]
}
}
// ready 比 handleLink 还早,初始化逻辑放到 handleLink 中
......@@ -47,4 +63,4 @@ export default function parseComponent (vueOptions) {
componentOptions.methods.__l = handleLink
return componentOptions
}
}
......@@ -743,10 +743,10 @@
exec-sh "^0.3.2"
minimist "^1.2.0"
"@dcloudio/uni-i18n@^0.0.3":
version "0.0.3"
resolved "https://registry.yarnpkg.com/@dcloudio/uni-i18n/-/uni-i18n-0.0.3.tgz#c7ff6ea6a4ea5cd5ef8dc3d674afa2e64502c151"
integrity sha512-BJGl0yUkuTMv6v0r1lUzq2EURkSoM/CoKbjlf7xlDXDTUqkhUGjK5epTq2hwsi26HTxTjvl6/vf50Q5wSTFApA==
"@dcloudio/uni-i18n@^2.0.0-31920210514002":
version "2.0.0-31920210514002"
resolved "https://registry.yarnpkg.com/@dcloudio/uni-i18n/-/uni-i18n-2.0.0-31920210514002.tgz#f63d14c234ea0353fabe2d8c681601c7ba07e488"
integrity sha512-shHf27U0KEs//ieCBG1R1aRKNDn6KwcVUIb5GsPuDOqoN7WQY+nEz9QFdOSQY8j9tX4ABOAc1ra0Opz8xFVngA==
"@hapi/address@2.x.x":
version "2.1.4"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册