HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

uni-app V3版本上线,App端性能、功能大幅提升

v3 uniapp

目前v3版本已经经过非常稳定,uni-app也已移除非v3版本支持,此文档不再更新维护。

公告1:App老版“自定义组件编译模式”将于2020年4月发布的HBuilderX 2.7版本下线,详见

公告2:v3是一个性能更高且更为稳定的版本,大家可以放心使用。后续新增功能仅支持v3版本,非v3版本将不再维护。如果您坚持使用老的编译器,有两个方案:1. 离线打包;2. 使用HBuilderX 2.6.16 版(参考https://ask.dcloud.net.cn/article/37302下载历史版本),该版本将继续支持云端打包(iOS 由于 xcode 版本过老已不支持提交到 AppStore),其它老的HBuilderX版本将不再支持云端打包。

遇到问题在本贴下留言建议同时发一个报Bug的帖子,这样点头像就能看到,让问题排查更有效率。

uni-app的App端,历经了最初的模板编译模式、自定义组件编译模式,如今迎来了第三次重大突破。这个版本,被命名为V3。

v3解决了App端的7个问题:

  • 运行更快
  • 框架体积更小
  • 开发编译更快
  • 提供视图层调试方案
  • 支持更多vue语法和指令(比如v-html)
  • 解开小程序的限制,提供更灵活的能力(比如视图层通过wxs可操作dom,支持renderjs)
  • 规整源码结构,为更大规模的开源共研做准备

如何启用V3版本编译器

  1. 确保HBuilderX 2.5.1以上版本

  2. manifest.json可视化视图-App其他常用设置里勾选v3编译器,或者源码视图里的app-plus节点下添加"compilerVersion": 3即可开启V3,体验畅爽的App端开发。

注意:开启成功之后,编译App时控制台会输出编译器版本:*.*.*(v3)

v3的优势详述

1. 启动速度

以hello uni-app为例,在一款2015年出厂的安卓低端机测试多次

  • 旧版本启动耗时均值: (7493+7261+7343+7151+7313)/5 = 7312
  • v3 版本启动耗时均值:(2499+2371+2385+2487+2356)/5 = 2419
    以上单位为毫秒。

hello uni-app的首页是nvue。如果你的App首页是vue,优化幅度没这么大,但也有明显提升。

欢迎开发者使用v3,并将首页改为nvue以提升启动速度。

2. 框架体积

v3版的App端前端框架体积减少了0.8M。

3. 开发编译速度

  1. 初次点击运行到App,耗时减少58.27%。
  2. 支持二次运行diff更新
  3. 支持保存后diff同步手机

初次点击运行到App耗时测试结果

  • 所用电脑为17款MacBook
  • 所用项目为首页调整为vue后的Hello uni-app
  • 测试时间为从开始编译到应用启动(单位:毫秒)
手机型号:小米2s 第一次 第二次 第三次 第四次 第五次 平均
旧版本 12095 12256 12027 12118 12033 12105.8
v3版本 4341 4518 4243 4275 4229 4321.2
手机型号:红米1 第一次 第二次 第三次 第四次 第五次 平均
旧版本 13726 14809 14606 14146 14761 14409.6
v3版本 8385 9371 8238 8471 9284 8749.8
手机型号:Nexus 5 第一次 第二次 第三次 第四次 第五次 平均
旧版本 11735 11696 11809 11835 11809 11776.8
v3新版本 4859 4617 4713 4963 4950 4820.4
手机型号:一加3T 第一次 第二次 第三次 第四次 第五次 平均
旧版本 9028 9049 9265 9150 9035 9105.4
v3新版本 3455 3319 3281 3436 3415 3381.2

4. 视图层通过webview调试

老版uni-app一直无法方便的调试视图元素,v3支持webkit remote debug,在视图菜单打开webview调试控制,手机端运行可调试的基座,打开vue页面,即可在控制台看到该页面。点击“Inspect(调试)”。

注意:目前仅支持安卓调试

注意:

  • uni-app 只有v3模式下的vue页面支持webview调试。nvue不支持,原生的tabbar、navigationbar、video、map、subnvue、cover-view等也均无法审查界面
  • webview调试只能调试视图层的dom,方便布局排版。但不能debug js,因为js不运行在webview里。debug js仍然使用之前控制台右上角的debug虫子图标
  • iOS包必须使用自己的测试开发证书打自定义基座包,然后在mac电脑上的safari里才能调试。

5. 更全的vue语法支持

uni-app虽然相较于市面其他多端框架,是对vue支持最全面的。但仍然有部分vue语法不支持。本次在App端拉齐了支持度(小程序端暂未变化)

尤其是很多开发者喜欢的 v-html 指令,终于可以在App端正常运行了。

以下为新增支持vue语法:

全局 API

全局 API 说明
Vue.extend 不可作为组件使用
Vue.directive -
Vue.filter 旧版不可以在class中使用

选项

选项 说明
props 旧版不可以传递函数
directives -
filters 旧版不可以在class中使用
provide/inject 旧版部分支持
name 旧版不支持递归组件
model -
inheritAttrs -

生命周期钩子

生命周期钩子 说明
activated -
deactivated -

实例属性

实例属性 说明
vm.$isServer V3总是返回false
vm.$attrs -
vm.$listeners -

模板指令

模板指令 说明
v-html -
v-bind 旧版不支持v-bind="{who:me}"类似用法
v-pre -
v-once -

特殊属性

特殊属性 说明
is -

内置组件

内置组件 说明
component -

目前仍有少部分vue语法未支持。具体见附录。

6. 解禁的视图层js,推出renderjs

  • 大幅降低逻辑层和视图层的通讯损耗,提供高性能视图交互能力
    逻辑层和视图层分离有很多好处,但也有一个副作用是在造成了两层之间通信阻塞。尤其是小程序和App的Android端阻塞问题影响了高性能应用的制作。
    微信小程序推出了wxs缓解此问题。
    uni-app兼容wxs,并且在App和H5端也实现了wxs。但微信定义的wxs限制太多,还是有很多高性能需求无法满足。
    于是renderjs诞生。
    renderjs只有App和H5支持,但它可以极大的提升通信效率。
    来看个基于renderjs的示例,App端流畅的canvas动画,超过了微信小程序的性能。

hello uni-app示例中可真实体验,对比App端和小程序端的性能差异。下图是App端录屏gif。

  • 在视图层操作dom,运行for web的js库
    官方不建议在uni-app里操作dom,但如果你不开发小程序,想使用一些操作了dom、window的库,其实可以使用renderjs来解决。
    在app-vue环境下,视图层由webview渲染,而renderjs运行在视图层,自然可以操作dom和window。
    这是一个基于renderjs运行echart完整版的示例:renderjs版echart
    同理,f2、threejs等库都可以用了。

戳此查看renderjs的文档

范围注意

  • v3是针对App的改进,尤其是vue页面的改进。与其他平台无关。
  • app-nvue下,仍然无法支持v-html和wxs/renderjs等技术
  • v3模式加速了首页 nvue 的启动速度,当在首页 nvue 中访问 getApp 不一定可以获取真正的 App 对象。对此v3版本提供了const app = getApp({allowDefault: true})用来获取原始的app对象,可以用来在首页对globalData等初始化
  • 同样是由于加速了首页 nvue 的启动速度,视图层启动速度可能快于逻辑层,v3版本在nvue首页使用vuex时也可能遇到不可使用的问题,后续会对此进行优化
  • v3模式下无法使用wgt热更新的问题,已经在2.6.4修复。

附:Vue特性支持表(App端)

全局配置

Vue 全局配置 旧版 V3 说明
Vue.config.silent 支持 支持 -
Vue.config.optionMergeStrategies 支持 支持 -
Vue.config.devtools 不支持 不支持 只在Web环境下支持
Vue.config.errorHandler 支持 支持 -
Vue.config.warnHandler 支持 支持 -
Vue.config.ignoredElements 支持 支持 强烈不推荐,会覆盖uni-app框架配置的内置组件
Vue.config.keyCodes 不支持 不支持 -
Vue.config.performance 不支持 不支持 只在Web环境下支持
Vue.config.productionTip 支持 支持 -

全局 API

Vue 全局 API 旧版 V3 说明
Vue.extend 不支持 支持 不可作为组件使用
Vue.nextTick 不支持 不支持 -
Vue.set 支持 支持 -
Vue.delete 支持 支持 -
Vue.directive 不支持 支持 -
Vue.filter 支持 支持 旧版不可以在class中使用
Vue.component 支持 支持 -
Vue.use 支持 支持 -
Vue.mixin 支持 支持 -
Vue.version 支持 支持 -
Vue.compile 不支持 不支持 uni-app使用的vue只包含运行时的版本

选项

Vue 选项 旧版 V3 说明
data 支持 支持 -
props 支持 支持 旧版不可以传递函数
propsData 支持 支持 -
computed 支持 支持 -
methods 支持 支持 -
watch 支持 支持 -
el 不支持 不支持
template 不支持 不支持 uni-app使用的vue是只包含运行时的版本
render 不支持 不支持 -
renderError 不支持 不支持 -
directives 不支持 支持 -
filters 支持 支持 旧版不可以在class中使用
components 支持 支持 -
parent 支持 支持 不推荐
mixins 支持 支持 -
extends 支持 支持 -
provide/inject 支持 支持 旧版部分支持
name 支持 支持 旧版不支持递归组件
delimiters 不支持 不支持 -
functional 不支持 不支持 -
model 不支持 支持 -
inheritAttrs 不支持 支持 -
comments 不支持 不支持 -

生命周期钩子

Vue 生命周期钩子 旧版 V3 说明
beforeCreate 支持 支持 -
created 支持 支持 -
beforeMount 支持 支持 -
mounted 支持 支持 -
beforeUpdate 支持 支持 -
updated 支持 支持 -
activated 不支持 支持 -
deactivated 不支持 支持 -
beforeDestroy 支持 支持 -
destroyed 支持 支持 -
errorCaptured 支持 支持 -

实例属性

Vue 实例属性 旧版 V3 说明
vm.$data 支持 支持 -
vm.$props 支持 支持 -
vm.$el 不支持 不支持 -
vm.$options 支持 支持 -
vm.$parent 支持 支持 uni-app里面view等内置标签是以组件方式实现,$parent会获取这些内置组件
vm.$root 支持 支持 -
vm.$children 支持 支持 -
vm.$slots 支持 不支持 旧版获取值为{'slotName':true/false}比如:{"footer":true}
vm.$scopedSlots 支持 支持 旧版获取值为{'slotName':true/false}比如:{"footer":true}
vm.$refs 支持 支持 -
vm.$isServer 不支持 支持 V3总是返回false
vm.$attrs 不支持 支持 -
vm.$listeners 不支持 支持 -

实例方法

Vue 实例方法 旧版 V3 说明
vm.$watch() 支持 支持 -
vm.$set() 支持 支持 -
vm.$delete() 支持 支持 -
vm.$on() 支持 支持 -
vm.$once() 支持 支持 -
vm.$off() 支持 支持 -
vm.$emit() 支持 支持 -
vm.$mount() 不支持 不支持 -
vm.$forceUpdate() 支持 支持 -
vm.$nextTick() 支持 支持 -
vm.$destroy() 支持 支持 -

模板指令

Vue 指令 旧版 V3 说明
v-text 支持 支持 -
v-html 不支持 支持 -
v-show 支持 支持 -
v-if 支持 支持 -
v-else 支持 支持 -
v-else-if 支持 支持 -
v-for 支持 支持 -
v-on 支持 支持 -
v-bind 支持 支持 旧版不支持v-bind="{who:me}"类似用法
v-model 支持 支持 -
v-pre 不支持 支持 -
v-cloak 不支持 不支持 -
v-once 不支持 支持 -

特殊属性

Vue 特殊属性 旧版 V3 说明
key 支持 支持 旧版不支持表达式
ref 支持 支持 -
is 不支持 支持 -

内置组件

Vue 内置组件 旧版 V3 说明
component 不支持 支持 -
transition 不支持 不支持 -
transition-group 不支持 不支持 -
keep-alive 不支持 不支持 -
slot 支持 支持 -
继续阅读 »

目前v3版本已经经过非常稳定,uni-app也已移除非v3版本支持,此文档不再更新维护。

公告1:App老版“自定义组件编译模式”将于2020年4月发布的HBuilderX 2.7版本下线,详见

公告2:v3是一个性能更高且更为稳定的版本,大家可以放心使用。后续新增功能仅支持v3版本,非v3版本将不再维护。如果您坚持使用老的编译器,有两个方案:1. 离线打包;2. 使用HBuilderX 2.6.16 版(参考https://ask.dcloud.net.cn/article/37302下载历史版本),该版本将继续支持云端打包(iOS 由于 xcode 版本过老已不支持提交到 AppStore),其它老的HBuilderX版本将不再支持云端打包。

遇到问题在本贴下留言建议同时发一个报Bug的帖子,这样点头像就能看到,让问题排查更有效率。

uni-app的App端,历经了最初的模板编译模式、自定义组件编译模式,如今迎来了第三次重大突破。这个版本,被命名为V3。

v3解决了App端的7个问题:

  • 运行更快
  • 框架体积更小
  • 开发编译更快
  • 提供视图层调试方案
  • 支持更多vue语法和指令(比如v-html)
  • 解开小程序的限制,提供更灵活的能力(比如视图层通过wxs可操作dom,支持renderjs)
  • 规整源码结构,为更大规模的开源共研做准备

如何启用V3版本编译器

  1. 确保HBuilderX 2.5.1以上版本

  2. manifest.json可视化视图-App其他常用设置里勾选v3编译器,或者源码视图里的app-plus节点下添加"compilerVersion": 3即可开启V3,体验畅爽的App端开发。

注意:开启成功之后,编译App时控制台会输出编译器版本:*.*.*(v3)

v3的优势详述

1. 启动速度

以hello uni-app为例,在一款2015年出厂的安卓低端机测试多次

  • 旧版本启动耗时均值: (7493+7261+7343+7151+7313)/5 = 7312
  • v3 版本启动耗时均值:(2499+2371+2385+2487+2356)/5 = 2419
    以上单位为毫秒。

hello uni-app的首页是nvue。如果你的App首页是vue,优化幅度没这么大,但也有明显提升。

欢迎开发者使用v3,并将首页改为nvue以提升启动速度。

2. 框架体积

v3版的App端前端框架体积减少了0.8M。

3. 开发编译速度

  1. 初次点击运行到App,耗时减少58.27%。
  2. 支持二次运行diff更新
  3. 支持保存后diff同步手机

初次点击运行到App耗时测试结果

  • 所用电脑为17款MacBook
  • 所用项目为首页调整为vue后的Hello uni-app
  • 测试时间为从开始编译到应用启动(单位:毫秒)
手机型号:小米2s 第一次 第二次 第三次 第四次 第五次 平均
旧版本 12095 12256 12027 12118 12033 12105.8
v3版本 4341 4518 4243 4275 4229 4321.2
手机型号:红米1 第一次 第二次 第三次 第四次 第五次 平均
旧版本 13726 14809 14606 14146 14761 14409.6
v3版本 8385 9371 8238 8471 9284 8749.8
手机型号:Nexus 5 第一次 第二次 第三次 第四次 第五次 平均
旧版本 11735 11696 11809 11835 11809 11776.8
v3新版本 4859 4617 4713 4963 4950 4820.4
手机型号:一加3T 第一次 第二次 第三次 第四次 第五次 平均
旧版本 9028 9049 9265 9150 9035 9105.4
v3新版本 3455 3319 3281 3436 3415 3381.2

4. 视图层通过webview调试

老版uni-app一直无法方便的调试视图元素,v3支持webkit remote debug,在视图菜单打开webview调试控制,手机端运行可调试的基座,打开vue页面,即可在控制台看到该页面。点击“Inspect(调试)”。

注意:目前仅支持安卓调试

注意:

  • uni-app 只有v3模式下的vue页面支持webview调试。nvue不支持,原生的tabbar、navigationbar、video、map、subnvue、cover-view等也均无法审查界面
  • webview调试只能调试视图层的dom,方便布局排版。但不能debug js,因为js不运行在webview里。debug js仍然使用之前控制台右上角的debug虫子图标
  • iOS包必须使用自己的测试开发证书打自定义基座包,然后在mac电脑上的safari里才能调试。

5. 更全的vue语法支持

uni-app虽然相较于市面其他多端框架,是对vue支持最全面的。但仍然有部分vue语法不支持。本次在App端拉齐了支持度(小程序端暂未变化)

尤其是很多开发者喜欢的 v-html 指令,终于可以在App端正常运行了。

以下为新增支持vue语法:

全局 API

全局 API 说明
Vue.extend 不可作为组件使用
Vue.directive -
Vue.filter 旧版不可以在class中使用

选项

选项 说明
props 旧版不可以传递函数
directives -
filters 旧版不可以在class中使用
provide/inject 旧版部分支持
name 旧版不支持递归组件
model -
inheritAttrs -

生命周期钩子

生命周期钩子 说明
activated -
deactivated -

实例属性

实例属性 说明
vm.$isServer V3总是返回false
vm.$attrs -
vm.$listeners -

模板指令

模板指令 说明
v-html -
v-bind 旧版不支持v-bind="{who:me}"类似用法
v-pre -
v-once -

特殊属性

特殊属性 说明
is -

内置组件

内置组件 说明
component -

目前仍有少部分vue语法未支持。具体见附录。

6. 解禁的视图层js,推出renderjs

  • 大幅降低逻辑层和视图层的通讯损耗,提供高性能视图交互能力
    逻辑层和视图层分离有很多好处,但也有一个副作用是在造成了两层之间通信阻塞。尤其是小程序和App的Android端阻塞问题影响了高性能应用的制作。
    微信小程序推出了wxs缓解此问题。
    uni-app兼容wxs,并且在App和H5端也实现了wxs。但微信定义的wxs限制太多,还是有很多高性能需求无法满足。
    于是renderjs诞生。
    renderjs只有App和H5支持,但它可以极大的提升通信效率。
    来看个基于renderjs的示例,App端流畅的canvas动画,超过了微信小程序的性能。

hello uni-app示例中可真实体验,对比App端和小程序端的性能差异。下图是App端录屏gif。

  • 在视图层操作dom,运行for web的js库
    官方不建议在uni-app里操作dom,但如果你不开发小程序,想使用一些操作了dom、window的库,其实可以使用renderjs来解决。
    在app-vue环境下,视图层由webview渲染,而renderjs运行在视图层,自然可以操作dom和window。
    这是一个基于renderjs运行echart完整版的示例:renderjs版echart
    同理,f2、threejs等库都可以用了。

戳此查看renderjs的文档

范围注意

  • v3是针对App的改进,尤其是vue页面的改进。与其他平台无关。
  • app-nvue下,仍然无法支持v-html和wxs/renderjs等技术
  • v3模式加速了首页 nvue 的启动速度,当在首页 nvue 中访问 getApp 不一定可以获取真正的 App 对象。对此v3版本提供了const app = getApp({allowDefault: true})用来获取原始的app对象,可以用来在首页对globalData等初始化
  • 同样是由于加速了首页 nvue 的启动速度,视图层启动速度可能快于逻辑层,v3版本在nvue首页使用vuex时也可能遇到不可使用的问题,后续会对此进行优化
  • v3模式下无法使用wgt热更新的问题,已经在2.6.4修复。

附:Vue特性支持表(App端)

全局配置

Vue 全局配置 旧版 V3 说明
Vue.config.silent 支持 支持 -
Vue.config.optionMergeStrategies 支持 支持 -
Vue.config.devtools 不支持 不支持 只在Web环境下支持
Vue.config.errorHandler 支持 支持 -
Vue.config.warnHandler 支持 支持 -
Vue.config.ignoredElements 支持 支持 强烈不推荐,会覆盖uni-app框架配置的内置组件
Vue.config.keyCodes 不支持 不支持 -
Vue.config.performance 不支持 不支持 只在Web环境下支持
Vue.config.productionTip 支持 支持 -

全局 API

Vue 全局 API 旧版 V3 说明
Vue.extend 不支持 支持 不可作为组件使用
Vue.nextTick 不支持 不支持 -
Vue.set 支持 支持 -
Vue.delete 支持 支持 -
Vue.directive 不支持 支持 -
Vue.filter 支持 支持 旧版不可以在class中使用
Vue.component 支持 支持 -
Vue.use 支持 支持 -
Vue.mixin 支持 支持 -
Vue.version 支持 支持 -
Vue.compile 不支持 不支持 uni-app使用的vue只包含运行时的版本

选项

Vue 选项 旧版 V3 说明
data 支持 支持 -
props 支持 支持 旧版不可以传递函数
propsData 支持 支持 -
computed 支持 支持 -
methods 支持 支持 -
watch 支持 支持 -
el 不支持 不支持
template 不支持 不支持 uni-app使用的vue是只包含运行时的版本
render 不支持 不支持 -
renderError 不支持 不支持 -
directives 不支持 支持 -
filters 支持 支持 旧版不可以在class中使用
components 支持 支持 -
parent 支持 支持 不推荐
mixins 支持 支持 -
extends 支持 支持 -
provide/inject 支持 支持 旧版部分支持
name 支持 支持 旧版不支持递归组件
delimiters 不支持 不支持 -
functional 不支持 不支持 -
model 不支持 支持 -
inheritAttrs 不支持 支持 -
comments 不支持 不支持 -

生命周期钩子

Vue 生命周期钩子 旧版 V3 说明
beforeCreate 支持 支持 -
created 支持 支持 -
beforeMount 支持 支持 -
mounted 支持 支持 -
beforeUpdate 支持 支持 -
updated 支持 支持 -
activated 不支持 支持 -
deactivated 不支持 支持 -
beforeDestroy 支持 支持 -
destroyed 支持 支持 -
errorCaptured 支持 支持 -

实例属性

Vue 实例属性 旧版 V3 说明
vm.$data 支持 支持 -
vm.$props 支持 支持 -
vm.$el 不支持 不支持 -
vm.$options 支持 支持 -
vm.$parent 支持 支持 uni-app里面view等内置标签是以组件方式实现,$parent会获取这些内置组件
vm.$root 支持 支持 -
vm.$children 支持 支持 -
vm.$slots 支持 不支持 旧版获取值为{'slotName':true/false}比如:{"footer":true}
vm.$scopedSlots 支持 支持 旧版获取值为{'slotName':true/false}比如:{"footer":true}
vm.$refs 支持 支持 -
vm.$isServer 不支持 支持 V3总是返回false
vm.$attrs 不支持 支持 -
vm.$listeners 不支持 支持 -

实例方法

Vue 实例方法 旧版 V3 说明
vm.$watch() 支持 支持 -
vm.$set() 支持 支持 -
vm.$delete() 支持 支持 -
vm.$on() 支持 支持 -
vm.$once() 支持 支持 -
vm.$off() 支持 支持 -
vm.$emit() 支持 支持 -
vm.$mount() 不支持 不支持 -
vm.$forceUpdate() 支持 支持 -
vm.$nextTick() 支持 支持 -
vm.$destroy() 支持 支持 -

模板指令

Vue 指令 旧版 V3 说明
v-text 支持 支持 -
v-html 不支持 支持 -
v-show 支持 支持 -
v-if 支持 支持 -
v-else 支持 支持 -
v-else-if 支持 支持 -
v-for 支持 支持 -
v-on 支持 支持 -
v-bind 支持 支持 旧版不支持v-bind="{who:me}"类似用法
v-model 支持 支持 -
v-pre 不支持 支持 -
v-cloak 不支持 不支持 -
v-once 不支持 支持 -

特殊属性

Vue 特殊属性 旧版 V3 说明
key 支持 支持 旧版不支持表达式
ref 支持 支持 -
is 不支持 支持 -

内置组件

Vue 内置组件 旧版 V3 说明
component 不支持 支持 -
transition 不支持 不支持 -
transition-group 不支持 不支持 -
keep-alive 不支持 不支持 -
slot 支持 支持 -
收起阅读 »

uniapp开发微信公众号苹果手机路径不变的问题

微信浏览器对history模式支持不太友好导致, 它只会记住你第一次进来的地址。
解决方法:
onLoad() {
let _href = window.location.href // 获取当前地址
if(_href.indexOf('&replace=1') <= -1){ // 若没有replace参数,则添加进去
window.location.replace(_href+'&replace=1')
}
}

继续阅读 »

微信浏览器对history模式支持不太友好导致, 它只会记住你第一次进来的地址。
解决方法:
onLoad() {
let _href = window.location.href // 获取当前地址
if(_href.indexOf('&replace=1') <= -1){ // 若没有replace参数,则添加进去
window.location.replace(_href+'&replace=1')
}
}

收起阅读 »

关于1.9版本SDK,安卓本地离线打包的问题。

昨天本地打包后,只是模糊测了下是否能打开,但是今天让测试的小伙伴使用的时候,才发现。弹出框(plus.nativeUI)都不起作用。不管是更换版本还是重新安装环境都不行。后来才发现。官方demo中一个被划掉的权限。如下图,添加到我的项目中,打包后,完美解决- -被搞的一脸蒙逼

继续阅读 »

昨天本地打包后,只是模糊测了下是否能打开,但是今天让测试的小伙伴使用的时候,才发现。弹出框(plus.nativeUI)都不起作用。不管是更换版本还是重新安装环境都不行。后来才发现。官方demo中一个被划掉的权限。如下图,添加到我的项目中,打包后,完美解决- -被搞的一脸蒙逼

收起阅读 »

uniapp h5上传图片对图片进行压缩旋转处理

csdn博客地址:uniapp h5上传图片对图片进行旋转处理

场景:uniapp开发的h5项目,需要内嵌在app中运行,在项目首页有一块是自定义上传日历背景图,并且需要进行裁剪。
最开始直接使用的插件市场的插件,但是由于webview的原因,该项目内嵌app后在ios上出现了无法解决的bug。故弃用了插件,并且由于需求调整目前只进行图片的上传旋转处理。(下面着重旋转的处理)

思路:

1、参考vue的处理方法,需要exif.js 获取到图片meta信息中的旋转角度,故首先需要引入exif.js,(本人直接从bootcdn上搜索下载的exif.min.js )(使用import引入本地文件的方式尝试了下没有成功,放弃了。由于项目本身需要存在了引入第三方的js方法所以exifjs是通过动态添加js的方式全局引入的)

2、通过uni.chooseImage 获取到图片的临时路径,并且将blob临时路径转化为 file文件用于exif获取图片的旋转值

3、根据获取到旋转值(有:1 3 6 8),如下:

                        //如果方向角不为1,都需要进行旋转  
                        switch (Orientation) {  
                            case 6: //需要顺时针(向右)90度旋转  
                                console.log('(向右)90度旋转');  
                                break;  
                            case 8: //需要逆时针(向左)90度旋转  
                                console.log('向左)90度旋转');  
                                break;  

                            case 3: //需要180度旋转 转两次  
                                console.log('需要180度旋转');  
                                break;  
                            default:  
                                break;  
                        }  

4、根据网上搜索的处理图片旋转方法或者从往期vue的上传图博客中提到的,对图片进行旋转处理,最终拿到base64的图片信息然后对图片进行上传。(1.直接上传base64 ;2.将base64转化为blob文件后再传后台)

具体代码如下:

1、
choiceImg(){
var that = this;
let maxWidth = 500; //压缩图片最大宽度
let Orientation = 1;
uni.chooseImage({
count: 1, // 能够选择的图片数量
sizeType: ['original', 'compressed'], // original: 原图, compressed: 压缩图, 默认二者都有
sourceType: ['album'], // album: 从相册选择 camera: 相机拍照
success: res => {
let imgArr = res.tempFilePaths; // 所选择图片的临时路径数组
//BlobUrl转blob数据

                uni.showToast({  
                    icon: "none",  
                    title: "图片处理中..."  
                })  
                //blob数据转file  
                this.objectURLToBlob(imgArr[0], function(blob) {  
                    let files = new window.File([blob], 'file.name', { type: 'file.type' });  
                    console.log('获取图片文件', files);  
                    EXIF.getData(files, async function() {  
                        let or = EXIF.getTag(this, 'Orientation'); //这个Orientation 就是我们判断需不需要旋转的值了,有1、3、6、8  
                        console.log(or);  
                        Orientation = or;  
                        var img = null;  
                        var canvas = null;  
                        await that.comprossImage(imgArr[0], maxWidth, function(e) {  
                            img = e.img;  
                            canvas = e.canvas;  
                        });  
                        let baseStr = '';  
                        //如果方向角不为1,都需要进行旋转  
                        switch (Orientation) {  
                            case 6: //需要顺时针(向右)90度旋转  
                                console.log('(向右)90度旋转');  
                                baseStr = that.rotateImg(img, 'right', canvas);  
                                break;  
                            case 8: //需要逆时针(向左)90度旋转  
                                console.log('向左)90度旋转');  
                                baseStr = rotateImg(img, 'left', canvas);  
                                break;  

                            case 3: //需要180度旋转 转两次  
                                console.log('需要180度旋转');  
                                baseStr = that.rotateImg(img, 'right', canvas, 2);  
                                break;  
                            default:  
                                baseStr = that.rotateImg(img, '', canvas);  
                                break;  
                        }  
                    });  
                });  
            }  
        });  

}
2、1中使用到的将blob转化为file方法 和图片的压缩方法
objectURLToBlob(url, callback) {
var http = new XMLHttpRequest();
http.open('GET', url, true);
http.responseType = 'blob';
http.onload = function(e) {
if (this.status == 200 || this.status === 0) {
callback(this.response);
}
};
http.send();
},
async comprossImage(imgSrc, maxWidth, func) {
if (!imgSrc) return 0;
return new Promise((resolve, reject) => {
uni.getImageInfo({
src: imgSrc,
success(res) {
let img = new Image();
img.src = res.path;
console.log(img);

                    let canvas = document.createElement('canvas');  

                    let obj = new Object();  
                    obj.img = img;  
                    obj.canvas = canvas;  
                    resolve(func(obj));  
                }  
            });  
        });  
    },  

3、图片的旋转处理
rotateImg(img, direction, canvas, times = 1) {
console.log('开始旋转');
//最小与最大旋转方向,图片旋转4次后回到原方向
var min_step = 0;
var max_step = 3;
if (img == null) return;

        //img的高度和宽度不能在img元素隐藏后获取,否则会出错  
        var height = img.height;  
        var width = img.width;  
        let maxWidth = 500;  
        let canvasWidth = width; //图片原始长宽  
        let canvasHeight = height;  
        let base = canvasWidth / canvasHeight;  
        console.log(maxWidth);  
        if (canvasWidth > maxWidth) {  
            canvasWidth = maxWidth;  
            canvasHeight = Math.floor(canvasWidth / base);  
        }  
        width = canvasWidth;  
        height = canvasHeight;  
        var step = 0;  

        if (step == null) {  
            step = min_step;  
        }  

        if (direction == 'right') {  
            step += times;  
            //旋转到原位置,即超过最大值  
            step > max_step && (step = min_step);  
        } else if (direction == 'left') {  
            step -= times;  
            step < min_step && (step = max_step);  
        } else {  
            //不旋转  
            step = 0;  
        }  

        //旋转角度以弧度值为参数  
        var degree = (step * 90 * Math.PI) / 180;  
        var ctx = canvas.getContext('2d');  
        // console.log(degree)  
        // console.log(step)  
        switch (step) {  
            case 1:  
                console.log('右旋转 90度');  
                canvas.width = height;  
                canvas.height = width;  
                ctx.rotate(degree);  
                ctx.drawImage(img, 0, -height, width, height);  
                break;  
            case 2:  
                //console.log('旋转 180度')  
                canvas.width = width;  
                canvas.height = height;  
                ctx.rotate(degree);  
                ctx.drawImage(img, -width, -height, width, height);  
                break;  
            case 3:  
                console.log('左旋转 90度');  
                canvas.width = height;  
                canvas.height = width;  
                ctx.rotate(degree);  
                ctx.drawImage(img, -width, 0, width, height);  
                break;  
            default:  
                //不旋转  
                canvas.width = width;  
                canvas.height = height;  
                ctx.drawImage(img, 0, 0, width, height);  
                break;  
        }  

        let baseStr = canvas.toDataURL('image/jpeg', 1);  
        // console.log(baseStr)  
        // return baseStr;  
        // replace("data:image/jpeg;base64,", "")  
        // 将base64转化为blob文件进行图片上传,(考虑到转化后再上传耗费时间暂时没有使用,如果需要base64ToPath 方法可百度或者私信我)  
        // base64ToPath(baseStr).then(tempPath => {  
        //  this.uploadBgImg(tempPath)  
        // });  
        // 自定义上传请求  
        this.uploadBaseImg(baseStr);  
    },  
继续阅读 »

csdn博客地址:uniapp h5上传图片对图片进行旋转处理

场景:uniapp开发的h5项目,需要内嵌在app中运行,在项目首页有一块是自定义上传日历背景图,并且需要进行裁剪。
最开始直接使用的插件市场的插件,但是由于webview的原因,该项目内嵌app后在ios上出现了无法解决的bug。故弃用了插件,并且由于需求调整目前只进行图片的上传旋转处理。(下面着重旋转的处理)

思路:

1、参考vue的处理方法,需要exif.js 获取到图片meta信息中的旋转角度,故首先需要引入exif.js,(本人直接从bootcdn上搜索下载的exif.min.js )(使用import引入本地文件的方式尝试了下没有成功,放弃了。由于项目本身需要存在了引入第三方的js方法所以exifjs是通过动态添加js的方式全局引入的)

2、通过uni.chooseImage 获取到图片的临时路径,并且将blob临时路径转化为 file文件用于exif获取图片的旋转值

3、根据获取到旋转值(有:1 3 6 8),如下:

                        //如果方向角不为1,都需要进行旋转  
                        switch (Orientation) {  
                            case 6: //需要顺时针(向右)90度旋转  
                                console.log('(向右)90度旋转');  
                                break;  
                            case 8: //需要逆时针(向左)90度旋转  
                                console.log('向左)90度旋转');  
                                break;  

                            case 3: //需要180度旋转 转两次  
                                console.log('需要180度旋转');  
                                break;  
                            default:  
                                break;  
                        }  

4、根据网上搜索的处理图片旋转方法或者从往期vue的上传图博客中提到的,对图片进行旋转处理,最终拿到base64的图片信息然后对图片进行上传。(1.直接上传base64 ;2.将base64转化为blob文件后再传后台)

具体代码如下:

1、
choiceImg(){
var that = this;
let maxWidth = 500; //压缩图片最大宽度
let Orientation = 1;
uni.chooseImage({
count: 1, // 能够选择的图片数量
sizeType: ['original', 'compressed'], // original: 原图, compressed: 压缩图, 默认二者都有
sourceType: ['album'], // album: 从相册选择 camera: 相机拍照
success: res => {
let imgArr = res.tempFilePaths; // 所选择图片的临时路径数组
//BlobUrl转blob数据

                uni.showToast({  
                    icon: "none",  
                    title: "图片处理中..."  
                })  
                //blob数据转file  
                this.objectURLToBlob(imgArr[0], function(blob) {  
                    let files = new window.File([blob], 'file.name', { type: 'file.type' });  
                    console.log('获取图片文件', files);  
                    EXIF.getData(files, async function() {  
                        let or = EXIF.getTag(this, 'Orientation'); //这个Orientation 就是我们判断需不需要旋转的值了,有1、3、6、8  
                        console.log(or);  
                        Orientation = or;  
                        var img = null;  
                        var canvas = null;  
                        await that.comprossImage(imgArr[0], maxWidth, function(e) {  
                            img = e.img;  
                            canvas = e.canvas;  
                        });  
                        let baseStr = '';  
                        //如果方向角不为1,都需要进行旋转  
                        switch (Orientation) {  
                            case 6: //需要顺时针(向右)90度旋转  
                                console.log('(向右)90度旋转');  
                                baseStr = that.rotateImg(img, 'right', canvas);  
                                break;  
                            case 8: //需要逆时针(向左)90度旋转  
                                console.log('向左)90度旋转');  
                                baseStr = rotateImg(img, 'left', canvas);  
                                break;  

                            case 3: //需要180度旋转 转两次  
                                console.log('需要180度旋转');  
                                baseStr = that.rotateImg(img, 'right', canvas, 2);  
                                break;  
                            default:  
                                baseStr = that.rotateImg(img, '', canvas);  
                                break;  
                        }  
                    });  
                });  
            }  
        });  

}
2、1中使用到的将blob转化为file方法 和图片的压缩方法
objectURLToBlob(url, callback) {
var http = new XMLHttpRequest();
http.open('GET', url, true);
http.responseType = 'blob';
http.onload = function(e) {
if (this.status == 200 || this.status === 0) {
callback(this.response);
}
};
http.send();
},
async comprossImage(imgSrc, maxWidth, func) {
if (!imgSrc) return 0;
return new Promise((resolve, reject) => {
uni.getImageInfo({
src: imgSrc,
success(res) {
let img = new Image();
img.src = res.path;
console.log(img);

                    let canvas = document.createElement('canvas');  

                    let obj = new Object();  
                    obj.img = img;  
                    obj.canvas = canvas;  
                    resolve(func(obj));  
                }  
            });  
        });  
    },  

3、图片的旋转处理
rotateImg(img, direction, canvas, times = 1) {
console.log('开始旋转');
//最小与最大旋转方向,图片旋转4次后回到原方向
var min_step = 0;
var max_step = 3;
if (img == null) return;

        //img的高度和宽度不能在img元素隐藏后获取,否则会出错  
        var height = img.height;  
        var width = img.width;  
        let maxWidth = 500;  
        let canvasWidth = width; //图片原始长宽  
        let canvasHeight = height;  
        let base = canvasWidth / canvasHeight;  
        console.log(maxWidth);  
        if (canvasWidth > maxWidth) {  
            canvasWidth = maxWidth;  
            canvasHeight = Math.floor(canvasWidth / base);  
        }  
        width = canvasWidth;  
        height = canvasHeight;  
        var step = 0;  

        if (step == null) {  
            step = min_step;  
        }  

        if (direction == 'right') {  
            step += times;  
            //旋转到原位置,即超过最大值  
            step > max_step && (step = min_step);  
        } else if (direction == 'left') {  
            step -= times;  
            step < min_step && (step = max_step);  
        } else {  
            //不旋转  
            step = 0;  
        }  

        //旋转角度以弧度值为参数  
        var degree = (step * 90 * Math.PI) / 180;  
        var ctx = canvas.getContext('2d');  
        // console.log(degree)  
        // console.log(step)  
        switch (step) {  
            case 1:  
                console.log('右旋转 90度');  
                canvas.width = height;  
                canvas.height = width;  
                ctx.rotate(degree);  
                ctx.drawImage(img, 0, -height, width, height);  
                break;  
            case 2:  
                //console.log('旋转 180度')  
                canvas.width = width;  
                canvas.height = height;  
                ctx.rotate(degree);  
                ctx.drawImage(img, -width, -height, width, height);  
                break;  
            case 3:  
                console.log('左旋转 90度');  
                canvas.width = height;  
                canvas.height = width;  
                ctx.rotate(degree);  
                ctx.drawImage(img, -width, 0, width, height);  
                break;  
            default:  
                //不旋转  
                canvas.width = width;  
                canvas.height = height;  
                ctx.drawImage(img, 0, 0, width, height);  
                break;  
        }  

        let baseStr = canvas.toDataURL('image/jpeg', 1);  
        // console.log(baseStr)  
        // return baseStr;  
        // replace("data:image/jpeg;base64,", "")  
        // 将base64转化为blob文件进行图片上传,(考虑到转化后再上传耗费时间暂时没有使用,如果需要base64ToPath 方法可百度或者私信我)  
        // base64ToPath(baseStr).then(tempPath => {  
        //  this.uploadBgImg(tempPath)  
        // });  
        // 自定义上传请求  
        this.uploadBaseImg(baseStr);  
    },  
收起阅读 »

uniapp开发的 淘宝、京东、拼多多 三合一APP已上线

uniapp开发的 淘宝、京东、拼多多 三合一APP
需要的加QQ:676133829

uniapp开发的 淘宝、京东、拼多多 三合一APP
需要的加QQ:676133829

map地图组件在app上不显示的一个原因

地图 map

经纬度写反了,宽高可以用100%

经纬度写反了,宽高可以用100%

调用蓝牙打印机打印一维码

if(bluetoothSocket.isConnected()) {  
            var outputStream = bluetoothSocket.getOutputStream();  
            plus.android.importClass(outputStream);  

            var bytes = plus.android.invoke(string, 'getBytes', 'gbk');  //其它内容  

            var bar = plus.android.invoke(billcode, 'getBytes', 'gbk');  

                outputStream.write(bytes);  
                outputStream.flush();  
                outputStream.write(29);  
                outputStream.write(72);  
                outputStream.write(2);  

                outputStream.flush();    //hri字符打印位置  
                outputStream.write(29);  
                outputStream.write(119);  
                outputStream.write(2);  

                outputStream.flush();    //条码宽度  
                outputStream.write(29);  
                outputStream.write(104);  
                outputStream.write(81);  

                outputStream.flush();  //条码高度  

                outputStream.write(29);  
                outputStream.write(107);   //打印条码  
                outputStream.write(73);   // 条码类型   code128  
                outputStream.write(15);   //  条码位数  

                outputStream.write(123);        
                outputStream.write(66);    //code128 的子类型,有128a,128b,128c  
                outputStream.write(bar);  
                outputStream.flush();  

            outputStream.flush();  
            device = null //这里关键  
            bluetoothSocket.close(); //必须关闭蓝牙连接否则意外断开的话打印错误
    }
继续阅读 »
if(bluetoothSocket.isConnected()) {  
            var outputStream = bluetoothSocket.getOutputStream();  
            plus.android.importClass(outputStream);  

            var bytes = plus.android.invoke(string, 'getBytes', 'gbk');  //其它内容  

            var bar = plus.android.invoke(billcode, 'getBytes', 'gbk');  

                outputStream.write(bytes);  
                outputStream.flush();  
                outputStream.write(29);  
                outputStream.write(72);  
                outputStream.write(2);  

                outputStream.flush();    //hri字符打印位置  
                outputStream.write(29);  
                outputStream.write(119);  
                outputStream.write(2);  

                outputStream.flush();    //条码宽度  
                outputStream.write(29);  
                outputStream.write(104);  
                outputStream.write(81);  

                outputStream.flush();  //条码高度  

                outputStream.write(29);  
                outputStream.write(107);   //打印条码  
                outputStream.write(73);   // 条码类型   code128  
                outputStream.write(15);   //  条码位数  

                outputStream.write(123);        
                outputStream.write(66);    //code128 的子类型,有128a,128b,128c  
                outputStream.write(bar);  
                outputStream.flush();  

            outputStream.flush();  
            device = null //这里关键  
            bluetoothSocket.close(); //必须关闭蓝牙连接否则意外断开的话打印错误
    }
收起阅读 »

关于安卓离线本地打包。本人使用的android studio,

因为要将app转化为桌面app,所以打包的时候要加几个属性。没办法,只能本地打包。
我之前用的是线上最新2.4的版本SDK,之后学着百度到的博客去创建本地打包。一直出现io.dcloud.PandoraEntry为空的问题,后来试了好几遍。才发现是版本问题。换成了之前的1.9。然后才算是成功了的。
分享几个前辈的博客文章以及用到的代码,都可以尝试下。:
https://blog.csdn.net/yafo00/article/details/98844535
https://ask.dcloud.net.cn/article/216

继续阅读 »

因为要将app转化为桌面app,所以打包的时候要加几个属性。没办法,只能本地打包。
我之前用的是线上最新2.4的版本SDK,之后学着百度到的博客去创建本地打包。一直出现io.dcloud.PandoraEntry为空的问题,后来试了好几遍。才发现是版本问题。换成了之前的1.9。然后才算是成功了的。
分享几个前辈的博客文章以及用到的代码,都可以尝试下。:
https://blog.csdn.net/yafo00/article/details/98844535
https://ask.dcloud.net.cn/article/216

收起阅读 »

多年MUI开发经验,精通5+app 开发,有任何问题可以QQ我

mui

多年MUI开发经验,精通5+app 开发,有任何问题可以QQ我,有偿解决各种疑难BUG 419761282

多年MUI开发经验,精通5+app 开发,有任何问题可以QQ我,有偿解决各种疑难BUG 419761282

Monokai Dimmed ——Hbuilder X主题

主题 json

1、设置主题为雅兰,配置设置代码、保存后,重启Huilder X


"workbench.colorCustomizations" : {  
        "[Atom One Dark]" : {  
            "ab.unfocusedHoverBackground" : "#272727",  
            "button.background" : "#0381ff",  
            "button.foreground" : "#CCCCCC",  
            "button.hoverBackground" : "#0381ff",  
            "console.background" : "#252525",  
            "crollbarSlider.hoverBackground" : "#8c8c8c",  
            "debug.foreground" : "#CCCCCC",  
            "editor.background" : "#252525",  
            "editor.foreground" : "#CCCCCC",  
            "editorGroupHeader.tabsBackground" : "#282828",  
            "editorSuggestWidget.background" : "#252525",  
            "editorSuggestWidget.border" : "#444444",  
            "editorSuggestWidget.link" : "#0381ff",  
            "editorSuggestWidget.selectedBackground" : "#707070",  
            "extensionButton.border" : "#454545",  
            "extensionButton.checkColor" : "#CCCCCC",  
            "extensionButton.prominentBackground" : "#454545",  
            "extensionButton.prominentForeground" : "#CCCCCC",  
            "extensionButton.prominentHoverBackground" : "#454545",  
            "focusBorder" : "#CCCCCC",  
            "input.background" : "#454545",  
            "input.border" : "#CCCCCC",  
            "input.foreground" : "#CCCCCC",  
            "inputList.border" : "#505050",  
            "inputList.foreground" : "#a49f9f",  
            "inputList.hoverBackground" : "#707070",  
            "inputList.titleColor" : "#CCCCCC",  
            "inputOption.activeBorder" : "#505050",  
            "inputValidation.infoBackground" : "#505050",  
            "list.activeSelectionBackground" : "#505050",  
            "list.activeSelectionForeground" : "#CCCCCC",  
            "list.foreground" : "#CCCCCC",  
            "list.highlightForeground" : "#CCCCCC",  
            "list.hoverBackground" : "#414040",  
            "list.inactiveSelectionBackground" : "#272727",  
            "list.inactiveSelectionForeground" : "#CCCCCC",  
            "minimap.handle.background" : "#707070",  
            "notification.buttonBackground" : "#252525",  
            "notification.buttonBorder" : "#707070",  
            "notification.buttonForeground" : "#707070",  
            "notification.buttonPressedBackground" : "#707070",  
            "notification.buttonPressedForeground" : "#252525",  
            "notificationLink.foreground" : "#707070",  
            "notifications.background" : "#252525",  
            "notifications.border" : "#707070",  
            "notifications.foreground" : "#CCCCCC",  
            "outlineBackground" : "#252525",  
            "panelTitle.activeForeground" : "#CCCCCC",  
            "scrollbarSlider.background" : "#424242",  
            "settings.dropdownBackground" : "#1e1e1e",  
            "settings.dropdownBorder" : "#707070",  
            "settings.dropdownListBorder" : "#1e1e1e",  
            "settings.textInputBackground" : "#1e1e1e",  
            "settings.textInputBorder" : "#1e1e1e",  
            "settings.textInputDisableBackground" : "#252525",  
            "sideBar.background" : "#272727",  
            "sideBar.border" : "#272727",  
            "statusBar.background" : "#505050",  
            "statusBar.foreground" : "#CCCCCC",  
            "tab.activeBackground" : "#1e1e1e",  
            "tab.activeBorder" : "#1e1e1e",  
            "tab.activeForeground" : "#CCCCCC",  
            "tab.border" : "#282828",  
            "tab.hoverBackground" : "#1e1e1e",  
            "tab.inactiveBackground" : "#404040",  
            "tab.inactiveForeground" : "#CCCCCC",  
            "tab.unfocusedActiveForeground" : "#CCCCCC",  
            "tab.unfocusedInactiveForeground" : "#CCCCCC",  
            "terminal.background" : "#252525",  
            "titleBar.activeBackground" : "#641f22",  
            "titleBar.activeForeground" : "#CCCCCC",  
            "toolBar.background" : "#454545",  
            "toolBar.border" : "#454545",  
            "toolBar.hoverBackground" : "#454545"  
        }  
    }

2、效果如图

继续阅读 »

1、设置主题为雅兰,配置设置代码、保存后,重启Huilder X


"workbench.colorCustomizations" : {  
        "[Atom One Dark]" : {  
            "ab.unfocusedHoverBackground" : "#272727",  
            "button.background" : "#0381ff",  
            "button.foreground" : "#CCCCCC",  
            "button.hoverBackground" : "#0381ff",  
            "console.background" : "#252525",  
            "crollbarSlider.hoverBackground" : "#8c8c8c",  
            "debug.foreground" : "#CCCCCC",  
            "editor.background" : "#252525",  
            "editor.foreground" : "#CCCCCC",  
            "editorGroupHeader.tabsBackground" : "#282828",  
            "editorSuggestWidget.background" : "#252525",  
            "editorSuggestWidget.border" : "#444444",  
            "editorSuggestWidget.link" : "#0381ff",  
            "editorSuggestWidget.selectedBackground" : "#707070",  
            "extensionButton.border" : "#454545",  
            "extensionButton.checkColor" : "#CCCCCC",  
            "extensionButton.prominentBackground" : "#454545",  
            "extensionButton.prominentForeground" : "#CCCCCC",  
            "extensionButton.prominentHoverBackground" : "#454545",  
            "focusBorder" : "#CCCCCC",  
            "input.background" : "#454545",  
            "input.border" : "#CCCCCC",  
            "input.foreground" : "#CCCCCC",  
            "inputList.border" : "#505050",  
            "inputList.foreground" : "#a49f9f",  
            "inputList.hoverBackground" : "#707070",  
            "inputList.titleColor" : "#CCCCCC",  
            "inputOption.activeBorder" : "#505050",  
            "inputValidation.infoBackground" : "#505050",  
            "list.activeSelectionBackground" : "#505050",  
            "list.activeSelectionForeground" : "#CCCCCC",  
            "list.foreground" : "#CCCCCC",  
            "list.highlightForeground" : "#CCCCCC",  
            "list.hoverBackground" : "#414040",  
            "list.inactiveSelectionBackground" : "#272727",  
            "list.inactiveSelectionForeground" : "#CCCCCC",  
            "minimap.handle.background" : "#707070",  
            "notification.buttonBackground" : "#252525",  
            "notification.buttonBorder" : "#707070",  
            "notification.buttonForeground" : "#707070",  
            "notification.buttonPressedBackground" : "#707070",  
            "notification.buttonPressedForeground" : "#252525",  
            "notificationLink.foreground" : "#707070",  
            "notifications.background" : "#252525",  
            "notifications.border" : "#707070",  
            "notifications.foreground" : "#CCCCCC",  
            "outlineBackground" : "#252525",  
            "panelTitle.activeForeground" : "#CCCCCC",  
            "scrollbarSlider.background" : "#424242",  
            "settings.dropdownBackground" : "#1e1e1e",  
            "settings.dropdownBorder" : "#707070",  
            "settings.dropdownListBorder" : "#1e1e1e",  
            "settings.textInputBackground" : "#1e1e1e",  
            "settings.textInputBorder" : "#1e1e1e",  
            "settings.textInputDisableBackground" : "#252525",  
            "sideBar.background" : "#272727",  
            "sideBar.border" : "#272727",  
            "statusBar.background" : "#505050",  
            "statusBar.foreground" : "#CCCCCC",  
            "tab.activeBackground" : "#1e1e1e",  
            "tab.activeBorder" : "#1e1e1e",  
            "tab.activeForeground" : "#CCCCCC",  
            "tab.border" : "#282828",  
            "tab.hoverBackground" : "#1e1e1e",  
            "tab.inactiveBackground" : "#404040",  
            "tab.inactiveForeground" : "#CCCCCC",  
            "tab.unfocusedActiveForeground" : "#CCCCCC",  
            "tab.unfocusedInactiveForeground" : "#CCCCCC",  
            "terminal.background" : "#252525",  
            "titleBar.activeBackground" : "#641f22",  
            "titleBar.activeForeground" : "#CCCCCC",  
            "toolBar.background" : "#454545",  
            "toolBar.border" : "#454545",  
            "toolBar.hoverBackground" : "#454545"  
        }  
    }

2、效果如图

收起阅读 »

share 分享遇到的坑

系统分享 Share uniapp

注意type值, qq仅支持音频分享 type值必须为3

注意type值, qq仅支持音频分享 type值必须为3

iOS平台打包提交AppStore报WARNING ITMS-90703错误的解决方法

Appstore iOS

部分开发者反馈提交AppStore可能会报以下错误:

WARNING ITMS-90703: "Deprecated Xcode Build. Due to resolved app archives issues, we have deprecated Xcode 11.2 on November 5, 2019. Download Xcode 11.2.1 or newer, rebuild your app and resubmit."  

ERROR ITMS-90534: "Invalid Toolchain. Your app was built with an unsupported SDK or version of Xcode. If you plan to submit this build to the App Store, make sure you are using the versions listed in https://help.apple.com/xcode/mac/current/#/devf16aefe3b or later."

这是由于使用XCode11.2版本打包生成ipa导致的问题,苹果已紧急发布了XCode11.2.1,需要更新XCode版本

HBuilderX云端打包

2019年11月17日至2019年11月18日,HBuilderX(alpha)版本对应的云端打包机使用XCode版本为11.2,此时间段云端打包提交AppStore会报上述问题。
2019年11月19日开始,HBuilderX(alpha)版对应的云端已更新XCode为11.2.1。
使用HBuilderX(alpha)的开发者请更新到最新版本(2.4.2),重新提交云端打包即可。

使用HBuilderX正式版提交云端打包生成的ipa不受影响

本地离线打包

更新XCode到11.2.1版本重新打包,再提交AppStore。

继续阅读 »

部分开发者反馈提交AppStore可能会报以下错误:

WARNING ITMS-90703: "Deprecated Xcode Build. Due to resolved app archives issues, we have deprecated Xcode 11.2 on November 5, 2019. Download Xcode 11.2.1 or newer, rebuild your app and resubmit."  

ERROR ITMS-90534: "Invalid Toolchain. Your app was built with an unsupported SDK or version of Xcode. If you plan to submit this build to the App Store, make sure you are using the versions listed in https://help.apple.com/xcode/mac/current/#/devf16aefe3b or later."

这是由于使用XCode11.2版本打包生成ipa导致的问题,苹果已紧急发布了XCode11.2.1,需要更新XCode版本

HBuilderX云端打包

2019年11月17日至2019年11月18日,HBuilderX(alpha)版本对应的云端打包机使用XCode版本为11.2,此时间段云端打包提交AppStore会报上述问题。
2019年11月19日开始,HBuilderX(alpha)版对应的云端已更新XCode为11.2.1。
使用HBuilderX(alpha)的开发者请更新到最新版本(2.4.2),重新提交云端打包即可。

使用HBuilderX正式版提交云端打包生成的ipa不受影响

本地离线打包

更新XCode到11.2.1版本重新打包,再提交AppStore。

收起阅读 »