HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

iOS云打包如何设置通用链接等Capabilities配置

universallink iOS Capabilities capabilitie

HBuilderX2.3.0开始云端打包支持配置XCode中的Capabilities
如下XCode配置

打开项目的manifest.json文件,在源码视图中进行配置

  • 5 APP项目
    在"plus" -> "distribute" -> "apple"添加"capabilities"节点
  • uni-app项目
    在"app-plus" -> "distribute" -> "ios"添加"capabilities"节点
        "capabilities": {  
            "entitlements": {   // 合并到工程entitlements文件的数据(json格式)  
            },  
            "plists": {         // 合并到工程Info.plist文件的数据(json格式)  
            }  
        },

其中entitlements数据(json)将转换成XCode工程中entitlements文件的数据(字典格式)
plists节点数据将转换成XCode工程中Info.plist文件的数据(字典格式)

<a id="unilink"/>

通用链接(Universal Link)

以下文档已过期,适用于:本地离线打包或者由于某种原因你需要用传统的方式:私有化部署服务器来托管apple-app-site-association文件创建通用链接。

推荐使用:一键生成iOS通用链接

Universal Link是苹果在WWDC 2015上提出的iOS 9的新特性之一。此特性类似于深层链接,并能够方便地通过打开一个Https链接来直接启动您的客户端应用(手机有安装App)。对比起以往所使用的URL Sheme, 这种新特性在实现web-app的无缝链接时能够提供极佳的用户体验。
使用前请阅读苹果官方文档
使用通用链接(Universal Link)必须要有域名,下的配置中将要用到

第一步:开启Associated Domains服务

登录苹果开发者网站,在“Certificates, Identifiers & Profiles”页面选择“Identifiers”中选择对应的App ID,确保开启Associated Domains服务


开启Associated Domains服务后需要重新生成profile文件,提交云端打包时使用

第二步:配置Associated Domains(域名)

原生XCode环境配置通用链接域名(本地离线打包配置,使用HBuilderX云端打包跳过)


使用HBuilderX云端打包时在manifest.json中配置域名
在"plus" -> "distribute" -> "apple" -> "capabilities" -> "entitlements"节点(uni-app项目在"app-plus" -> "distribute" -> "ios" -> "capabilities" -> "entitlements")下添加"com.apple.developer.associated-domains"字段,字段值为字符串数组,每个字符串为要关联的域名

    "capabilities": {  
        "entitlements": {  
            "com.apple.developer.associated-domains": [  
                "applinks:demo.dcloud.net.cn"  
            ]  
        }  
    }

其中demo.dcloud.net.cn是应用通用链接的域名(这里不要包含path),请修改为自己应用要使用的域名
保存后提交云端打包生效。

HBuilderX中自带的默认真机运行基座HBuilderX注册的通用链接为:https://demo.dcloud.net.cn/ulink/

第三步:服务器配置apple-app-site-association文件

需要在上面域名对应的服务器上放apple-app-site-association文件。
apple-app-site-association文件配置如下:

{  
    "applinks": {  
        "apps": [],  
        "details": [  
            {  
                "appID": "G56NU654TV.io.dcloud.HBuilder",  
                "paths": [ "/ulink/*"]  
            }  
        ]  
    }  
}
  • apps
    必须对应一个空的数组
  • appID
    由前缀和ID两部分组成,可以登录苹果开发者网站,在“Certificates, Identifiers & Profiles”页面选择“Identifiers”中选择对应的App ID查看
  • paths
    对应域名中的path,用于过滤可以跳转到App的链接,支持通配符*,?以及NOT进行匹配,匹配的优先级是从左至右依次降低

注意:不要直接拷贝使用上面的示例,必须根据自己应用的配置修改
把配置好的apple-app-site-association文件上传到你自己的服务器,确保通过https://demo.dcloud.net.cn/.well-known/apple-app-site-association可访问。
其中demo.dcloud.net.cn为上面配置的域名
应用安装后会通过访问上面的url向系统注册应用的通用链接。

推荐方案:将apple-app-site-association文件部署到,免费的阿里云版unicloud的 前端网页托管

客户端处理通用链接

可通过5+ API的plus.runtime.launcher判断应用启动来源,如果其值为"uniLink"则表示通过通用链接启动应。
这时可通过5+ API的plus.runtime.arguments获取启动参数,通用链接启动的情况将返回完整的通用链接地址。

注意事项

  • apple-app-site-association文件不需要.json后缀
  • 对apple-app-site-association文件的请求仅在App第一次启动时进行,如果此时网络连接出了问题apple会缓存请求,等有网的时候再去请求,如果没有请求此文件通用连接会失效
  • iOS 9.2开始,在相同的domain内Universal Links不生效,必须要跨域才生效

微信配置通用链接参考:https://ask.dcloud.net.cn/article/36445

继续阅读 »

HBuilderX2.3.0开始云端打包支持配置XCode中的Capabilities
如下XCode配置

打开项目的manifest.json文件,在源码视图中进行配置

  • 5 APP项目
    在"plus" -> "distribute" -> "apple"添加"capabilities"节点
  • uni-app项目
    在"app-plus" -> "distribute" -> "ios"添加"capabilities"节点
        "capabilities": {  
            "entitlements": {   // 合并到工程entitlements文件的数据(json格式)  
            },  
            "plists": {         // 合并到工程Info.plist文件的数据(json格式)  
            }  
        },

其中entitlements数据(json)将转换成XCode工程中entitlements文件的数据(字典格式)
plists节点数据将转换成XCode工程中Info.plist文件的数据(字典格式)

<a id="unilink"/>

通用链接(Universal Link)

以下文档已过期,适用于:本地离线打包或者由于某种原因你需要用传统的方式:私有化部署服务器来托管apple-app-site-association文件创建通用链接。

推荐使用:一键生成iOS通用链接

Universal Link是苹果在WWDC 2015上提出的iOS 9的新特性之一。此特性类似于深层链接,并能够方便地通过打开一个Https链接来直接启动您的客户端应用(手机有安装App)。对比起以往所使用的URL Sheme, 这种新特性在实现web-app的无缝链接时能够提供极佳的用户体验。
使用前请阅读苹果官方文档
使用通用链接(Universal Link)必须要有域名,下的配置中将要用到

第一步:开启Associated Domains服务

登录苹果开发者网站,在“Certificates, Identifiers & Profiles”页面选择“Identifiers”中选择对应的App ID,确保开启Associated Domains服务


开启Associated Domains服务后需要重新生成profile文件,提交云端打包时使用

第二步:配置Associated Domains(域名)

原生XCode环境配置通用链接域名(本地离线打包配置,使用HBuilderX云端打包跳过)


使用HBuilderX云端打包时在manifest.json中配置域名
在"plus" -> "distribute" -> "apple" -> "capabilities" -> "entitlements"节点(uni-app项目在"app-plus" -> "distribute" -> "ios" -> "capabilities" -> "entitlements")下添加"com.apple.developer.associated-domains"字段,字段值为字符串数组,每个字符串为要关联的域名

    "capabilities": {  
        "entitlements": {  
            "com.apple.developer.associated-domains": [  
                "applinks:demo.dcloud.net.cn"  
            ]  
        }  
    }

其中demo.dcloud.net.cn是应用通用链接的域名(这里不要包含path),请修改为自己应用要使用的域名
保存后提交云端打包生效。

HBuilderX中自带的默认真机运行基座HBuilderX注册的通用链接为:https://demo.dcloud.net.cn/ulink/

第三步:服务器配置apple-app-site-association文件

需要在上面域名对应的服务器上放apple-app-site-association文件。
apple-app-site-association文件配置如下:

{  
    "applinks": {  
        "apps": [],  
        "details": [  
            {  
                "appID": "G56NU654TV.io.dcloud.HBuilder",  
                "paths": [ "/ulink/*"]  
            }  
        ]  
    }  
}
  • apps
    必须对应一个空的数组
  • appID
    由前缀和ID两部分组成,可以登录苹果开发者网站,在“Certificates, Identifiers & Profiles”页面选择“Identifiers”中选择对应的App ID查看
  • paths
    对应域名中的path,用于过滤可以跳转到App的链接,支持通配符*,?以及NOT进行匹配,匹配的优先级是从左至右依次降低

注意:不要直接拷贝使用上面的示例,必须根据自己应用的配置修改
把配置好的apple-app-site-association文件上传到你自己的服务器,确保通过https://demo.dcloud.net.cn/.well-known/apple-app-site-association可访问。
其中demo.dcloud.net.cn为上面配置的域名
应用安装后会通过访问上面的url向系统注册应用的通用链接。

推荐方案:将apple-app-site-association文件部署到,免费的阿里云版unicloud的 前端网页托管

客户端处理通用链接

可通过5+ API的plus.runtime.launcher判断应用启动来源,如果其值为"uniLink"则表示通过通用链接启动应。
这时可通过5+ API的plus.runtime.arguments获取启动参数,通用链接启动的情况将返回完整的通用链接地址。

注意事项

  • apple-app-site-association文件不需要.json后缀
  • 对apple-app-site-association文件的请求仅在App第一次启动时进行,如果此时网络连接出了问题apple会缓存请求,等有网的时候再去请求,如果没有请求此文件通用连接会失效
  • iOS 9.2开始,在相同的domain内Universal Links不生效,必须要跨域才生效

微信配置通用链接参考:https://ask.dcloud.net.cn/article/36445

收起阅读 »

web-view直接返回父页面的解决方案

经验分享

在有web-view的页面,如果点击左上角的后退按钮,会返回到web-view中url的上一个页面,而不是回到APP的父页面
采用如下代码,点击左上角后退按钮就可以回到父页面。
onBackPress(options) {
const currentWebview = this.$mp.page.$getAppWebview();
if(currentWebview){
let child=currentWebview.children();
for(let i=0;i<child.length;i++){
currentWebview.remove(child[i]);
}
}
return false;
}

PS:不要采用currentWebview.close(),uniapp下不好用,各种出错

继续阅读 »

在有web-view的页面,如果点击左上角的后退按钮,会返回到web-view中url的上一个页面,而不是回到APP的父页面
采用如下代码,点击左上角后退按钮就可以回到父页面。
onBackPress(options) {
const currentWebview = this.$mp.page.$getAppWebview();
if(currentWebview){
let child=currentWebview.children();
for(let i=0;i<child.length;i++){
currentWebview.remove(child[i]);
}
}
return false;
}

PS:不要采用currentWebview.close(),uniapp下不好用,各种出错

收起阅读 »

从微信小程序转为uniapp开发注意事项

1、wx:for 改为 v-for (记得标记 :key )
2、wx:key="{{xxx}}" 改为 :key="xxx"
3、class="tab-item {{xx1==index?'aa1':''}}" 改为 :class="[xx1==index?'tab-item aa1':'tab-item']"
4、src="{{xxx}}" 改为 :src= "xxx"
5、src="{{xxx1}}/{{xxx2}}" 改为 :src= "xxx1+xxx2"
6、src="{{xxx1}}/xxx2.png" 改为 :src="xxx1 +'xxx2.png'"
7、scroll-left="{{xxx}}" 改为 :scroll-left="xxx"
8、id="{{index}}" 改为 :id="index"
9、bindtap 改为 @click
10、bind:submit 改为 @submit
11、style="{{xxx:aaa}}" 改为 :style="{xxx:aaa}" 注意xxx是驼峰式命名法
12、lazy-load="{{true}}" 改为 lazy-load="true"
13、this.data.xxx 改为 this.xxx
14、that.setData({ xxx: vvv }) 改为 this.xxx = vvv

继续阅读 »

1、wx:for 改为 v-for (记得标记 :key )
2、wx:key="{{xxx}}" 改为 :key="xxx"
3、class="tab-item {{xx1==index?'aa1':''}}" 改为 :class="[xx1==index?'tab-item aa1':'tab-item']"
4、src="{{xxx}}" 改为 :src= "xxx"
5、src="{{xxx1}}/{{xxx2}}" 改为 :src= "xxx1+xxx2"
6、src="{{xxx1}}/xxx2.png" 改为 :src="xxx1 +'xxx2.png'"
7、scroll-left="{{xxx}}" 改为 :scroll-left="xxx"
8、id="{{index}}" 改为 :id="index"
9、bindtap 改为 @click
10、bind:submit 改为 @submit
11、style="{{xxx:aaa}}" 改为 :style="{xxx:aaa}" 注意xxx是驼峰式命名法
12、lazy-load="{{true}}" 改为 lazy-load="true"
13、this.data.xxx 改为 this.xxx
14、that.setData({ xxx: vvv }) 改为 this.xxx = vvv

收起阅读 »

iOS上架被拒 Guideline 3.1.1问题解释

iOS iOS打包

Guideline 3.1.1 - Business - Payments - In-App PurchaseWe noticed that your app uses in-app purchase products to purchase credits or currencies that are not consumed within the app, which is not appropriate for the App Store.

3.1.1问题就是支付方面没有做好。

因为苹果要求虚拟商品必须走IAP也就是苹果支付方式,不能使用支付宝微信支付。

当然实物商品是可以使用支付宝或者微信支付

所以如果遇到这种问题,确实是虚拟类商品比如说游戏的金币,道具等,还是要按规矩走苹果支付,通过隐藏第三方支付,来绕过审核这种方式也不怎么管用,苹果审核会扫代码!

有时可能没有做支付,但使用了支付宝SDK,微信和QQ SDK等,也可能反馈这个问题。

要把含有微信支付或者支付宝支付的注释或者方法名都删掉,耐心跟苹果回复沟通问题!

iOS APP上架被拒重新提交审核教程

继续阅读 »

Guideline 3.1.1 - Business - Payments - In-App PurchaseWe noticed that your app uses in-app purchase products to purchase credits or currencies that are not consumed within the app, which is not appropriate for the App Store.

3.1.1问题就是支付方面没有做好。

因为苹果要求虚拟商品必须走IAP也就是苹果支付方式,不能使用支付宝微信支付。

当然实物商品是可以使用支付宝或者微信支付

所以如果遇到这种问题,确实是虚拟类商品比如说游戏的金币,道具等,还是要按规矩走苹果支付,通过隐藏第三方支付,来绕过审核这种方式也不怎么管用,苹果审核会扫代码!

有时可能没有做支付,但使用了支付宝SDK,微信和QQ SDK等,也可能反馈这个问题。

要把含有微信支付或者支付宝支付的注释或者方法名都删掉,耐心跟苹果回复沟通问题!

iOS APP上架被拒重新提交审核教程

收起阅读 »

uni-app自定义导航栏|顶部导航按钮+搜索+圆点

uniapp模板 uniapp

基于uni-app自定义实现导航栏,类似微信、京东、淘宝顶部导航条,支持背景渐变、标题居左/居中、搜索条,圆点提示,按钮可自定义传入文字/字体图标/图片

uniapp原生导航

uni-app原生导航栏也能实现一些顶部自定义按钮+搜索框,只需在page.json里面做一些配置即可。设置app-plus,dcloud平台对app-plus做了详细说明:app-plus配置,不过目前暂支持H5、App端,不支持小程序。


需在项目page.json里面配置app-plus

{  
    "path": "pages/ucenter/index",  
    "style": {  
        "navigationBarTitleText": "我的",  
        "app-plus": {  
            "titleNView": {  
                "buttons": [  
                    {  
                        "text": "\ue670",  
                        "fontSrc": "/static/iconfont.ttf",  
                        "fontSize": "22px",  
                        "float": "left"  
                    },  
                    {  
                        "text": "\ue62c",  
                        "fontSrc": "/static/iconfont.ttf",  
                        "fontSize": "22px"  

                    }  
                ],  
                "searchInput":{  
                    ...  
                }  
            }  
        }  
    }  
},

uniapp自定义导航栏

如何实现像微信、京东顶部导航栏,支持标题居左、居中、搜索条、按钮自定义。。。
将navigationStyle设为custom或titleNView设为false时,原生导航栏不显示,这时就能自定义导航栏 
"globalStyle": { "navigationStyle": "custom" } 

效果如下:


不过在 H5、小程序、App端状态栏需重新计算处理,下面为大家提供一种处理方法,在App.vue里面设置即可

onLaunch: function() {  
    uni.getSystemInfo({  
        success:function(e){  
            Vue.prototype.statusBar = e.statusBarHeight  
            // #ifndef MP  
            if(e.platform == 'android') {  
                Vue.prototype.customBar = e.statusBarHeight + 50  
            }else {  
                Vue.prototype.customBar = e.statusBarHeight + 45  
            }  
            // #endif  

            // #ifdef MP-WEIXIN  
            let custom = wx.getMenuButtonBoundingClientRect()  
            Vue.prototype.customBar = custom.bottom + custom.top - e.statusBarHeight  
            // #endif  

            // #ifdef MP-ALIPAY  
            Vue.prototype.customBar = e.statusBarHeight + e.titleBarHeight  
            // #endif  
        }  
    })  
},

<header-bar :isBack="false" title="标题信息" titleTintColor="#fff">  
    <text slot="back" class="uni_btnIco iconfont icon-arrL"></text>  
    <text slot="iconfont" class="uni_btnIco iconfont icon-search" @tap="aaa"></text>  
    <text slot="iconfont" class="uni_btnIco iconfont icon-tianjia" @tap="bbb"></text>  
    <!-- <text slot="string" class="uni_btnString" @tap="ccc">添加好友</text> -->  
    <image slot="image" class="uni_btnImage" src="../../static/logo.png" mode="widthFix" @tap="ddd"></image>  
</header-bar>



<header-bar :isBack="true" titleTintColor="#fff" :bgColor="{'background-image': 'linear-gradient(45deg, #007AFF 10%, #005cbf)'}" search>  
    <text slot="back" class="uni_btnIco iconfont icon-arrL"></text>  
    <text slot="iconfont" class="uni_btnIco iconfont icon-choose03" @tap="aaa"></text>  
    <image slot="image" class="uni_btnImage" src="../../static/logo.png" mode="widthFix" @tap="ddd"></image>  
</header-bar>


<header-bar :isBack="true" title="我的" titleTintColor="#fff" :bgColor="{background: '#353535'}">  
    <text slot="back" class="uni_btnIco iconfont icon-close"></text>  
    <text slot="iconfont" class="uni_btnIco iconfont icon-search"></text>  
    <text slot="string" class="uni_btnString" style="color: #2B9939;">添加好友</text>  
</header-bar>

/**  
 * @tpl 顶部导航模板(自定义) by andy  Q:282310962  
 */  
<template>  
    <view class="uni_topbar" :style="style">  
        <view class="inner flexbox flex_alignc" :class="[fixed ? 'fixed' : '']" :style="[{'height': customBarH + 'px', 'padding-top': statusBarH + 'px', 'color': titleTintColor}, bgColor]">  
            <!-- 返回 -->  
            <!-- <text class="uni_icoBack iconfont icon-arrL" v-if="isBack" @tap="goBack"></text> -->  
            <view v-if="isBack" @tap="goBack">  
                <slot name="back"></slot>  
            </view>  
            <slot name="headerL"></slot>  
            <!-- 标题 -->  
            <!-- #ifndef MP -->  
            <view class="flex1" v-if="!search && center"></view>  
            <!-- #endif -->  
            <view class="uni_title flex1" :class="[center ? 'uni_titleCenter' : '']" :style="[isBack ? {'font-size': '32upx', 'padding-left': '0'} : '']" v-if="!search && title">  
                {{title}}  
            </view>  
            <view class="uni_search flex1" :class="[searchRadius ? 'uni_searchRadius' : '']" v-if="search"> />  
                <input class="uni_searchIpt flex1" type="text" placeholder="搜索" placeholder-style="color: rgba(255,255,255,.5);" />  
            </view>  
            <!-- 右侧 -->  
            <view class="uni_headerRight flexbox flex_row flex_alignc">  
                <slot name="iconfont"></slot>  
                <slot name="string"></slot>  
                <slot name="image"></slot>  
            </view>  
        </view>  
    </view>  
</template>  

<script>  
    export default {  
        data() {  
            return {  
                statusBarH: this.statusBar,  
                customBarH: this.customBar  
            }  
        },  
        props: {  
            isBack: { type: [Boolean, String], default: true },  
            title: { type: String, default: '' },  
            titleTintColor: { type: String, default: '#fff' },  
            bgColor: Object,  
            center: { type: [Boolean, String], default: false },  
            search: { type: [Boolean, String], default: false },  
            searchRadius: { type: [Boolean, String], default: false },  
            fixed: { type: [Boolean, String], default: false },  
        },  
        computed: {  
            style() {  
                let _style = `height: ${this.customBarH}px;`  
                return _style  
            }  
        },  
        methods: {  
            goBack() {  
                uni.navigateBack()  
            }  
        }  
    }  
</script>

今天的分享就到这里啦。
附上之前开发的RN项目,里面也含有自定义导航条,喜欢能喜欢
ReactNative聊天室项目实例

继续阅读 »

基于uni-app自定义实现导航栏,类似微信、京东、淘宝顶部导航条,支持背景渐变、标题居左/居中、搜索条,圆点提示,按钮可自定义传入文字/字体图标/图片

uniapp原生导航

uni-app原生导航栏也能实现一些顶部自定义按钮+搜索框,只需在page.json里面做一些配置即可。设置app-plus,dcloud平台对app-plus做了详细说明:app-plus配置,不过目前暂支持H5、App端,不支持小程序。


需在项目page.json里面配置app-plus

{  
    "path": "pages/ucenter/index",  
    "style": {  
        "navigationBarTitleText": "我的",  
        "app-plus": {  
            "titleNView": {  
                "buttons": [  
                    {  
                        "text": "\ue670",  
                        "fontSrc": "/static/iconfont.ttf",  
                        "fontSize": "22px",  
                        "float": "left"  
                    },  
                    {  
                        "text": "\ue62c",  
                        "fontSrc": "/static/iconfont.ttf",  
                        "fontSize": "22px"  

                    }  
                ],  
                "searchInput":{  
                    ...  
                }  
            }  
        }  
    }  
},

uniapp自定义导航栏

如何实现像微信、京东顶部导航栏,支持标题居左、居中、搜索条、按钮自定义。。。
将navigationStyle设为custom或titleNView设为false时,原生导航栏不显示,这时就能自定义导航栏 
"globalStyle": { "navigationStyle": "custom" } 

效果如下:


不过在 H5、小程序、App端状态栏需重新计算处理,下面为大家提供一种处理方法,在App.vue里面设置即可

onLaunch: function() {  
    uni.getSystemInfo({  
        success:function(e){  
            Vue.prototype.statusBar = e.statusBarHeight  
            // #ifndef MP  
            if(e.platform == 'android') {  
                Vue.prototype.customBar = e.statusBarHeight + 50  
            }else {  
                Vue.prototype.customBar = e.statusBarHeight + 45  
            }  
            // #endif  

            // #ifdef MP-WEIXIN  
            let custom = wx.getMenuButtonBoundingClientRect()  
            Vue.prototype.customBar = custom.bottom + custom.top - e.statusBarHeight  
            // #endif  

            // #ifdef MP-ALIPAY  
            Vue.prototype.customBar = e.statusBarHeight + e.titleBarHeight  
            // #endif  
        }  
    })  
},

<header-bar :isBack="false" title="标题信息" titleTintColor="#fff">  
    <text slot="back" class="uni_btnIco iconfont icon-arrL"></text>  
    <text slot="iconfont" class="uni_btnIco iconfont icon-search" @tap="aaa"></text>  
    <text slot="iconfont" class="uni_btnIco iconfont icon-tianjia" @tap="bbb"></text>  
    <!-- <text slot="string" class="uni_btnString" @tap="ccc">添加好友</text> -->  
    <image slot="image" class="uni_btnImage" src="../../static/logo.png" mode="widthFix" @tap="ddd"></image>  
</header-bar>



<header-bar :isBack="true" titleTintColor="#fff" :bgColor="{'background-image': 'linear-gradient(45deg, #007AFF 10%, #005cbf)'}" search>  
    <text slot="back" class="uni_btnIco iconfont icon-arrL"></text>  
    <text slot="iconfont" class="uni_btnIco iconfont icon-choose03" @tap="aaa"></text>  
    <image slot="image" class="uni_btnImage" src="../../static/logo.png" mode="widthFix" @tap="ddd"></image>  
</header-bar>


<header-bar :isBack="true" title="我的" titleTintColor="#fff" :bgColor="{background: '#353535'}">  
    <text slot="back" class="uni_btnIco iconfont icon-close"></text>  
    <text slot="iconfont" class="uni_btnIco iconfont icon-search"></text>  
    <text slot="string" class="uni_btnString" style="color: #2B9939;">添加好友</text>  
</header-bar>

/**  
 * @tpl 顶部导航模板(自定义) by andy  Q:282310962  
 */  
<template>  
    <view class="uni_topbar" :style="style">  
        <view class="inner flexbox flex_alignc" :class="[fixed ? 'fixed' : '']" :style="[{'height': customBarH + 'px', 'padding-top': statusBarH + 'px', 'color': titleTintColor}, bgColor]">  
            <!-- 返回 -->  
            <!-- <text class="uni_icoBack iconfont icon-arrL" v-if="isBack" @tap="goBack"></text> -->  
            <view v-if="isBack" @tap="goBack">  
                <slot name="back"></slot>  
            </view>  
            <slot name="headerL"></slot>  
            <!-- 标题 -->  
            <!-- #ifndef MP -->  
            <view class="flex1" v-if="!search && center"></view>  
            <!-- #endif -->  
            <view class="uni_title flex1" :class="[center ? 'uni_titleCenter' : '']" :style="[isBack ? {'font-size': '32upx', 'padding-left': '0'} : '']" v-if="!search && title">  
                {{title}}  
            </view>  
            <view class="uni_search flex1" :class="[searchRadius ? 'uni_searchRadius' : '']" v-if="search"> />  
                <input class="uni_searchIpt flex1" type="text" placeholder="搜索" placeholder-style="color: rgba(255,255,255,.5);" />  
            </view>  
            <!-- 右侧 -->  
            <view class="uni_headerRight flexbox flex_row flex_alignc">  
                <slot name="iconfont"></slot>  
                <slot name="string"></slot>  
                <slot name="image"></slot>  
            </view>  
        </view>  
    </view>  
</template>  

<script>  
    export default {  
        data() {  
            return {  
                statusBarH: this.statusBar,  
                customBarH: this.customBar  
            }  
        },  
        props: {  
            isBack: { type: [Boolean, String], default: true },  
            title: { type: String, default: '' },  
            titleTintColor: { type: String, default: '#fff' },  
            bgColor: Object,  
            center: { type: [Boolean, String], default: false },  
            search: { type: [Boolean, String], default: false },  
            searchRadius: { type: [Boolean, String], default: false },  
            fixed: { type: [Boolean, String], default: false },  
        },  
        computed: {  
            style() {  
                let _style = `height: ${this.customBarH}px;`  
                return _style  
            }  
        },  
        methods: {  
            goBack() {  
                uni.navigateBack()  
            }  
        }  
    }  
</script>

今天的分享就到这里啦。
附上之前开发的RN项目,里面也含有自定义导航条,喜欢能喜欢
ReactNative聊天室项目实例

收起阅读 »

uni-app 打包成正式app安装包后,请求获取不到最新数据

5+App开发 uniapp

请检查你的nginx缓存设置

请求缓存问题

请求缓存问题

请求缓存问题

重要的事说三次

我被这个小问题整整坑了一天!!!

请检查你的nginx缓存设置

请求缓存问题

请求缓存问题

请求缓存问题

重要的事说三次

我被这个小问题整整坑了一天!!!

谜之wxs,uni-app如何用它大幅提升性能

过滤器 卡顿 跟手动画 性能 wxs

小程序技术领域,有几个谜一样的存在:微信的WXS、支付宝的SJS、百度的Filter

很多开发者都不明白为什么要造这种语言脚本的轮子出来,甚至很多开发者根本不知道它们的存在。

其实几大小程序平台创造它们,都是为了解决性能问题,但不得不吐槽下,设计的实在是很难用,文档也语焉不详。

uni-app支持将WXSSJSFilter编译到这3家小程序平台,同时还在App和H5实现了WXS的解析。为什么做这些事?也是为了性能。

比如uni-ui组件库中的swiperaction组件,就是列表项向左滑动时拉出几个挤压式联动的菜单按钮,这种流畅的跟手动画,正是借助于WXS机制实现的。

微信为何要创造WXS

WXS(WeiXin Script)是微信创造的一套脚本语言,它的官方说法是:“WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致”。

那微信为何要脱离 JavaScript ,单独创造一套语言呢?这要从微信小程序的底层逻辑(运行环境)讲起。

小程序的运行环境分为逻辑层和视图层,分别由2个线程管理,其中:

  • WXML 模板和 WXSS 样式工作在视图层,界面使用 WebView 进行渲染
  • JavaScript代码工作在逻辑层,运行在JsCore或v8里

小程序在视图层与逻辑层两个线程间提供了数据传输和事件系统。这样的分离设计,带来了显而易见的好处:

  • 逻辑和视图分离,即使业务逻辑计算非常繁忙,也不会阻塞渲染和用户在视图层上的交互

但同时也带来了明显的坏处:

  • 视图层(webview)中不能运行JS,而逻辑层JS又无法直接修改页面DOM,数据更新及事件系统只能靠线程间通讯,但跨线程通信的成本极高,特别是需要频繁通信的场景

什么是需要频繁通讯的场景?最典型的例子就是用户持续交互的情况,比如触摸、滚动等。我们以侧滑菜单为例,假设在页面上滑动A元素,要求B元素跟随移动,一次滑动操作(touchmove)的响应过程如下:

  1. touchmove 事件从视图层(Webview)传递到逻辑层,中间会由微信客户端(Native)做中转
  2. 逻辑层处理 touchmove 事件,计算需移动的位置,然后再通过 setData 传递到视图层,中间同样会由微信客户端(Native)做中转

一次 touchmove 的响应需要经过 视图层、Native、逻辑层三者之间2个完整来回的通信,通信的耗时开销较大,用户的交互就会出现延时卡顿的情况。

除了滚动、拖动交互外,在for循环里对数据做格式修改,也会造成逻辑层和视图层频繁通讯。

其实这类通信损耗问题,在业内由来已久,react native和weex都有类似问题,weex提供了bindingx来解决。

但对于小程序来讲,这类问题解决起来更容易。因为其实视图层的webview,是有js环境的,只不过过去不给开发者开放。

如果在视图层的js直接处理滚动或拖动交互、直接处理数据格式,就能避免大量通信损耗。

但对于小程序平台而言,大量开放webview里的js编写,违反了它的初衷,比如开发者会直接操作dom,影响性能体验。所以小程序平台提出一种新规范,限制webview里可运行的js的能力。这就是wxs、sjs、filter的由来。

从本质来讲,wxs、sjs、filter是一种被限制过的、运行在视图层webview里的js。它并不是真的发明了一种新语言。

WXS特征及适用场景

WXS具备如下特征:

  • WXS是可以在视图层(webview)中运行的JS
  • WXS无法直接修改业务数据,仅能设置当前组件的classstyle,或者对数据进行格式化。要修改逻辑层的数据,需要通过 callMethod,传递参数给逻辑层
  • WXS是被限制过的JavaScript,可以进行一些简单的逻辑运算
  • WXS可以监听touch事件,处理滚动、拖动交互

故可以得出WXS的适用场景,主要包括:

  • 用户交互频繁、仅需改动组件样式(比如布局位置),无需改动数据内容的场景,比如侧滑菜单、索引列表、滚动渐变等
  • 数据格式处理,比如文本、日期格式化,或者国际化。通过WXS可以模拟实现Vue框架的过滤器,如下是一个通过wxs实现首字母大写的示例:
<wxs module="m1">  
  //首字母大写  
  var capitalize = function(value) {  
    if (!value) return ''  
    value = value.toString()  
    return value.charAt(0).toUpperCase() + value.slice(1)  
  }  
  module.exports = {  
    capitalize: capitalize  
  }  
</wxs>  
<view class="content">  
  <view class="text-area">  
    <!-- title 为当前页面 data 中定义的初始数据 -->  
    <text class="title">{{m1.capitalize(title)}}</text>  
  </view>  
</view>

uni-app如何支持WXS

uni-app遵循Vue单文件组件(SFC)规范,组件/样式/脚本是写在一个.vue文件中的,但微信小程序是多文件分离(wxml/wxss/js/json)的,所以在微信端的主要工作是扩展vue-template-compiler,解析template/style/script节点,并正确生成到对应的wxml/wxss/js文件中,具体编译工作如下图:

Tips-1:关于<wxs>标签重构为<script lang="wxs">的说明:

.vue文件中的<wxs>标签及内嵌WXS代码,在主流前端开发工具(vscode/HBuilderX等)中,均无法实现语法提示、代码高亮及格式化,故uni-app<wxs module="m1">重构为<script module="m1" lang="wxs">,便捷实现了语法提示、代码高亮等,如下为vscode/HBuilderX中对于<wxs>标签重构前后的代码高亮对比,明显重构为<script lang="wxs">后,开发体验更佳:

Tips-2:鉴于Vue的自定义标签规范,我们建议将<wxs><script lang="wxs">)和template平级编写

编译器的具体解析扩展工作,这里不详述,仅给出wxs生成的示例代码,让大家有个直观理解:

createFilterTag (filterTag, {  
    content,  
    attrs  
  }) {  
    content = content.trim()  
    if (content) { //<wxs>标签内直接编写 wxs 代码  
      return `<${filterTag} module="${attrs.module}">  
        ${content}  
        </${filterTag}>`  
    } else if (attrs.src) { //外联 .wxs 文件  
      return `<${filterTag} src="${attrs.src}" module="${attrs.module}"></${filterTag}>`  
    }  
  }

在保证编译正确的情况下,微信小程序运行时会正确解析并执行WXS脚本,框架runtime无需干预。

基于 WXS 提升性能体验的实现示例

下面的gif显示的内容,是借助 WXS 实现的一个swipeaction组件示例,列表项向左滑动时拉出几个挤压式联动的菜单按钮,跟手动画、回弹动画都很自然流畅。

这里简单给出主要实现思路:

  1. 在 vue 中引用 wxs 文件,并绑定 touch 事件

    <template>  
    <view class="uni-swipe_content">  
      <!-- 可滑动的菜单项容器,绑定touch事件 -->  
    <view :data-position="pos" class="move-hock"  
      @touchstart="swipe.touchstart" @touchmove="swipe.touchmove" @touchend="swipe.touchend" @change="change">  
      <view class="uni-swipe_box">  
        <slot />  
      </view>  
      <view class="uni-swipe_button-group move-hock">  
          <!-- 滑动后,右侧挤压式的联动菜单按钮-->  
        <view v-for="(item,index) in options" :data-button="btn" :key="index"  class="button-hock">  
        {{ item.text }}  
        </view>  
      </view>  
    </view>  
    </view>  
    </template>  
    <script module="swipe" lang="wxs" src="./index.wxs"></script>
  2. 在 wxs 文件中,处理 touch 事件逻辑,通过 translateX 移动元素位置

function touchstart(e, ins) {  
    //记录开始位置及动画状态  
  var pageX = e.touches[0].pageX;  
  ....  
}  

function touchmove(e, ownerInstance) {  
  var instance = e.instance;  
  var pageX = e.touches[0].pageX;//获取当前移动位置  
  //计算偏移位置  
  var x = Math.max(-instance.getState().position[1].width, Math.min((value), 0));  
  //设置左侧元素移动位置  
  instance.setStyle({transform: 'translateX(' + x + 'px)'})   

  //循环右侧挤压式联动菜单  
  var btnIns = ownerInstance.selectAllComponents('.button-hock');  
  for (var i = 0; i < btnIns.length; i++) {  
    ...  
    //设置每个联动菜单的移动位置  
    btnIns[i].setStyle({transform: 'translateX(' + (arr[i - 1] + value * (arr[i - 1] / position[1].width)) + 'px)'})  
    ...  
  }  
}  

function touchend(e, ownerInstance) {  
  var instance = e.instance;  
  var state = instance.getState()  
  //根据当前移动位置,实现菜单项的自动展开或回弹  
  move(state.left, -40, instance, ownerInstance)  
}

该示例的完整源码参考github

在这段代码中,响应手势并移动菜单,是在视图层直接完成的。而不用wxs的传统写法,实现这个功能就会很卡。首先是视图层接收到touch事件,然后传递给逻辑层,逻辑层的js响应touch事件,判断移动距离,再通知视图层更新界面元素的位置。在持续的拖动过程中,视图层和逻辑层不停交互通信,无法做到跟手的顺滑。

虽然我们了解了wxs的原理,但老实讲,wxs挺难用的,直到现在,大多数开发者仍然不会用它。比较合适的做法,还是一些框架的作者对它进行封装。uni-app提供的uni-ui组件库,就是这样做的,开发者只需要按标准vue组件的方式去引用uni uiswiperaction组件,就能得到流畅的滑动跟手菜单。

更多平台的兼容性

uni-app的App端也是一个小程序引擎,为了在App端实现流畅的跟手拖动,也实现和兼容了wxs。

其实H5平台倒不存在逻辑层和视图层通讯折损的问题,但为了平台兼容性拉齐,uni-app在H5端也实现了wxs机制。

这样编写wxs代码,在uni-app中可同时运行在App端、H5端、微信小程序端。

百度小程序的Filter过滤器和支付宝小程序的SJS,成熟度还比较低,目前只能处理基本的数据格式过滤,还不能响应touch等交互事件。

至于头条和QQ小程序,还不支持类WXS机制。

期待其他小程序平台尽快补齐这个重要功能,实现体验的提升。

uni-app目前也支持单独编写百度小程序的Filter过滤器和支付宝小程序的SJS,这两种脚本无法跨多端,仅支持自有平台。开发者若需使用,可分别编写wxs/filter/sjs脚本,然后依次通过script引用,uni-app编译器会根据目标平台,分别编译发行,如下为示例代码:
示例代码要有条件编译

<!-- App/H5/微信小程序平台调用wxs脚本 -->  
<script module="utils" lang="wxs" src="./utils.wxs"></script>  
<!-- 百度小程序平台调用filter.js脚本 -->  
<script module="utils" lang="filter" src="./utils.filter.js"></script>  
<!-- 支付宝小程序平台调用sjs脚本 -->  
<script module="utils" lang="sjs" src="./utils.sjs"></script>

后续

用运行在视图层的js解决通讯阻塞,可能很多人都没意识到。希望本文能给大家解惑,解开WXS之谜。

其实小程序的性能体验优化,仍然有大量空间。DCloud团队在这个领域研究了6年,清楚小程序技术架构的优势,也清楚当前的问题。我们会继续分享这些问题及对应的解决方案,为小程序产业发展贡献力量。

本文涉及的uni-uiswiperaction组件,代码开源在https://github.com/dcloudio/uni-uiuni-app框架代码开源在 https://github.com/dcloudio/uni-app,欢迎大家 star 或提交 pr。

继续阅读 »

小程序技术领域,有几个谜一样的存在:微信的WXS、支付宝的SJS、百度的Filter

很多开发者都不明白为什么要造这种语言脚本的轮子出来,甚至很多开发者根本不知道它们的存在。

其实几大小程序平台创造它们,都是为了解决性能问题,但不得不吐槽下,设计的实在是很难用,文档也语焉不详。

uni-app支持将WXSSJSFilter编译到这3家小程序平台,同时还在App和H5实现了WXS的解析。为什么做这些事?也是为了性能。

比如uni-ui组件库中的swiperaction组件,就是列表项向左滑动时拉出几个挤压式联动的菜单按钮,这种流畅的跟手动画,正是借助于WXS机制实现的。

微信为何要创造WXS

WXS(WeiXin Script)是微信创造的一套脚本语言,它的官方说法是:“WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致”。

那微信为何要脱离 JavaScript ,单独创造一套语言呢?这要从微信小程序的底层逻辑(运行环境)讲起。

小程序的运行环境分为逻辑层和视图层,分别由2个线程管理,其中:

  • WXML 模板和 WXSS 样式工作在视图层,界面使用 WebView 进行渲染
  • JavaScript代码工作在逻辑层,运行在JsCore或v8里

小程序在视图层与逻辑层两个线程间提供了数据传输和事件系统。这样的分离设计,带来了显而易见的好处:

  • 逻辑和视图分离,即使业务逻辑计算非常繁忙,也不会阻塞渲染和用户在视图层上的交互

但同时也带来了明显的坏处:

  • 视图层(webview)中不能运行JS,而逻辑层JS又无法直接修改页面DOM,数据更新及事件系统只能靠线程间通讯,但跨线程通信的成本极高,特别是需要频繁通信的场景

什么是需要频繁通讯的场景?最典型的例子就是用户持续交互的情况,比如触摸、滚动等。我们以侧滑菜单为例,假设在页面上滑动A元素,要求B元素跟随移动,一次滑动操作(touchmove)的响应过程如下:

  1. touchmove 事件从视图层(Webview)传递到逻辑层,中间会由微信客户端(Native)做中转
  2. 逻辑层处理 touchmove 事件,计算需移动的位置,然后再通过 setData 传递到视图层,中间同样会由微信客户端(Native)做中转

一次 touchmove 的响应需要经过 视图层、Native、逻辑层三者之间2个完整来回的通信,通信的耗时开销较大,用户的交互就会出现延时卡顿的情况。

除了滚动、拖动交互外,在for循环里对数据做格式修改,也会造成逻辑层和视图层频繁通讯。

其实这类通信损耗问题,在业内由来已久,react native和weex都有类似问题,weex提供了bindingx来解决。

但对于小程序来讲,这类问题解决起来更容易。因为其实视图层的webview,是有js环境的,只不过过去不给开发者开放。

如果在视图层的js直接处理滚动或拖动交互、直接处理数据格式,就能避免大量通信损耗。

但对于小程序平台而言,大量开放webview里的js编写,违反了它的初衷,比如开发者会直接操作dom,影响性能体验。所以小程序平台提出一种新规范,限制webview里可运行的js的能力。这就是wxs、sjs、filter的由来。

从本质来讲,wxs、sjs、filter是一种被限制过的、运行在视图层webview里的js。它并不是真的发明了一种新语言。

WXS特征及适用场景

WXS具备如下特征:

  • WXS是可以在视图层(webview)中运行的JS
  • WXS无法直接修改业务数据,仅能设置当前组件的classstyle,或者对数据进行格式化。要修改逻辑层的数据,需要通过 callMethod,传递参数给逻辑层
  • WXS是被限制过的JavaScript,可以进行一些简单的逻辑运算
  • WXS可以监听touch事件,处理滚动、拖动交互

故可以得出WXS的适用场景,主要包括:

  • 用户交互频繁、仅需改动组件样式(比如布局位置),无需改动数据内容的场景,比如侧滑菜单、索引列表、滚动渐变等
  • 数据格式处理,比如文本、日期格式化,或者国际化。通过WXS可以模拟实现Vue框架的过滤器,如下是一个通过wxs实现首字母大写的示例:
<wxs module="m1">  
  //首字母大写  
  var capitalize = function(value) {  
    if (!value) return ''  
    value = value.toString()  
    return value.charAt(0).toUpperCase() + value.slice(1)  
  }  
  module.exports = {  
    capitalize: capitalize  
  }  
</wxs>  
<view class="content">  
  <view class="text-area">  
    <!-- title 为当前页面 data 中定义的初始数据 -->  
    <text class="title">{{m1.capitalize(title)}}</text>  
  </view>  
</view>

uni-app如何支持WXS

uni-app遵循Vue单文件组件(SFC)规范,组件/样式/脚本是写在一个.vue文件中的,但微信小程序是多文件分离(wxml/wxss/js/json)的,所以在微信端的主要工作是扩展vue-template-compiler,解析template/style/script节点,并正确生成到对应的wxml/wxss/js文件中,具体编译工作如下图:

Tips-1:关于<wxs>标签重构为<script lang="wxs">的说明:

.vue文件中的<wxs>标签及内嵌WXS代码,在主流前端开发工具(vscode/HBuilderX等)中,均无法实现语法提示、代码高亮及格式化,故uni-app<wxs module="m1">重构为<script module="m1" lang="wxs">,便捷实现了语法提示、代码高亮等,如下为vscode/HBuilderX中对于<wxs>标签重构前后的代码高亮对比,明显重构为<script lang="wxs">后,开发体验更佳:

Tips-2:鉴于Vue的自定义标签规范,我们建议将<wxs><script lang="wxs">)和template平级编写

编译器的具体解析扩展工作,这里不详述,仅给出wxs生成的示例代码,让大家有个直观理解:

createFilterTag (filterTag, {  
    content,  
    attrs  
  }) {  
    content = content.trim()  
    if (content) { //<wxs>标签内直接编写 wxs 代码  
      return `<${filterTag} module="${attrs.module}">  
        ${content}  
        </${filterTag}>`  
    } else if (attrs.src) { //外联 .wxs 文件  
      return `<${filterTag} src="${attrs.src}" module="${attrs.module}"></${filterTag}>`  
    }  
  }

在保证编译正确的情况下,微信小程序运行时会正确解析并执行WXS脚本,框架runtime无需干预。

基于 WXS 提升性能体验的实现示例

下面的gif显示的内容,是借助 WXS 实现的一个swipeaction组件示例,列表项向左滑动时拉出几个挤压式联动的菜单按钮,跟手动画、回弹动画都很自然流畅。

这里简单给出主要实现思路:

  1. 在 vue 中引用 wxs 文件,并绑定 touch 事件

    <template>  
    <view class="uni-swipe_content">  
      <!-- 可滑动的菜单项容器,绑定touch事件 -->  
    <view :data-position="pos" class="move-hock"  
      @touchstart="swipe.touchstart" @touchmove="swipe.touchmove" @touchend="swipe.touchend" @change="change">  
      <view class="uni-swipe_box">  
        <slot />  
      </view>  
      <view class="uni-swipe_button-group move-hock">  
          <!-- 滑动后,右侧挤压式的联动菜单按钮-->  
        <view v-for="(item,index) in options" :data-button="btn" :key="index"  class="button-hock">  
        {{ item.text }}  
        </view>  
      </view>  
    </view>  
    </view>  
    </template>  
    <script module="swipe" lang="wxs" src="./index.wxs"></script>
  2. 在 wxs 文件中,处理 touch 事件逻辑,通过 translateX 移动元素位置

function touchstart(e, ins) {  
    //记录开始位置及动画状态  
  var pageX = e.touches[0].pageX;  
  ....  
}  

function touchmove(e, ownerInstance) {  
  var instance = e.instance;  
  var pageX = e.touches[0].pageX;//获取当前移动位置  
  //计算偏移位置  
  var x = Math.max(-instance.getState().position[1].width, Math.min((value), 0));  
  //设置左侧元素移动位置  
  instance.setStyle({transform: 'translateX(' + x + 'px)'})   

  //循环右侧挤压式联动菜单  
  var btnIns = ownerInstance.selectAllComponents('.button-hock');  
  for (var i = 0; i < btnIns.length; i++) {  
    ...  
    //设置每个联动菜单的移动位置  
    btnIns[i].setStyle({transform: 'translateX(' + (arr[i - 1] + value * (arr[i - 1] / position[1].width)) + 'px)'})  
    ...  
  }  
}  

function touchend(e, ownerInstance) {  
  var instance = e.instance;  
  var state = instance.getState()  
  //根据当前移动位置,实现菜单项的自动展开或回弹  
  move(state.left, -40, instance, ownerInstance)  
}

该示例的完整源码参考github

在这段代码中,响应手势并移动菜单,是在视图层直接完成的。而不用wxs的传统写法,实现这个功能就会很卡。首先是视图层接收到touch事件,然后传递给逻辑层,逻辑层的js响应touch事件,判断移动距离,再通知视图层更新界面元素的位置。在持续的拖动过程中,视图层和逻辑层不停交互通信,无法做到跟手的顺滑。

虽然我们了解了wxs的原理,但老实讲,wxs挺难用的,直到现在,大多数开发者仍然不会用它。比较合适的做法,还是一些框架的作者对它进行封装。uni-app提供的uni-ui组件库,就是这样做的,开发者只需要按标准vue组件的方式去引用uni uiswiperaction组件,就能得到流畅的滑动跟手菜单。

更多平台的兼容性

uni-app的App端也是一个小程序引擎,为了在App端实现流畅的跟手拖动,也实现和兼容了wxs。

其实H5平台倒不存在逻辑层和视图层通讯折损的问题,但为了平台兼容性拉齐,uni-app在H5端也实现了wxs机制。

这样编写wxs代码,在uni-app中可同时运行在App端、H5端、微信小程序端。

百度小程序的Filter过滤器和支付宝小程序的SJS,成熟度还比较低,目前只能处理基本的数据格式过滤,还不能响应touch等交互事件。

至于头条和QQ小程序,还不支持类WXS机制。

期待其他小程序平台尽快补齐这个重要功能,实现体验的提升。

uni-app目前也支持单独编写百度小程序的Filter过滤器和支付宝小程序的SJS,这两种脚本无法跨多端,仅支持自有平台。开发者若需使用,可分别编写wxs/filter/sjs脚本,然后依次通过script引用,uni-app编译器会根据目标平台,分别编译发行,如下为示例代码:
示例代码要有条件编译

<!-- App/H5/微信小程序平台调用wxs脚本 -->  
<script module="utils" lang="wxs" src="./utils.wxs"></script>  
<!-- 百度小程序平台调用filter.js脚本 -->  
<script module="utils" lang="filter" src="./utils.filter.js"></script>  
<!-- 支付宝小程序平台调用sjs脚本 -->  
<script module="utils" lang="sjs" src="./utils.sjs"></script>

后续

用运行在视图层的js解决通讯阻塞,可能很多人都没意识到。希望本文能给大家解惑,解开WXS之谜。

其实小程序的性能体验优化,仍然有大量空间。DCloud团队在这个领域研究了6年,清楚小程序技术架构的优势,也清楚当前的问题。我们会继续分享这些问题及对应的解决方案,为小程序产业发展贡献力量。

本文涉及的uni-uiswiperaction组件,代码开源在https://github.com/dcloudio/uni-uiuni-app框架代码开源在 https://github.com/dcloudio/uni-app,欢迎大家 star 或提交 pr。

收起阅读 »

公告:uni-app将于2019年11月1日起停止支持非自定义组件模式

非自定义组件

公告:uni-app将于2019年11月1日起停止支持非自定义组件模式

非自定义组件作为一种被淘汰的技术,为了向下兼容,一直保留在uni-app的核心代码中。

目前uni-app的编译模式过多:有非自定义组件模式、自定义组件模式;有nvue、有vue;nvue有weex编译模式、有uni-app编译模式;还支持纯nvue编译模式。

太多历史兼容,导致编译器复杂度太高,代码冗余很多。

目前在App、微信小程序、百度小程序、支付宝小程序、头条小程序上,仍然有部分开发者一直未升级到自定义组件模式。请开发者快速升级。

uni-app将于2019年11月1日起停止支持非自定义组件模式,届时,新版HBuilderX真机运行和云打包,都不再支持非自定义组件模式。HBuilderX的云打包,只向下保留2个版本。再升级1个版本后,老版打包机也不再支持非自定义组件模式。

升级自定义组件模式,开发者将得到更好的应用性能、更便利的调试体验。

升级方式

在manifest.json可配置编译模式。

  • 方式1. 可视化界面
    在App、微信、百度、支付宝、头条小程序配置界面,勾上自定义组件编译模式

  • 方式2. 源码视图
    如下:
    {  
    "name" : "",  
    "appid" : "",  
    "app-plus" : {  
        "usingComponents" : true  
    },  
    "mp-weixin" : {  
        "appid" : "",  
        "usingComponents" : true  
    },  
    "mp-alipay" : {  
        "usingComponents" : true  
    },  
    "mp-baidu" : {  
        "usingComponents" : true  
    },  
    "mp-toutiao" : {  
        "usingComponents" : true  
    }  
    }

升级后,如代码运行异常,参考下文调整

https://ask.dcloud.net.cn/article/35851

如果你不知道自己是什么编译模式,通过以下方式查看:
打开manifest源码视图里,看每个平台下是否有 "usingComponents" : true。
如果值为true就是自定义组件模式。
如果值为false或没有该键名则为非自定义组件模式。

在HBuilderX 1.9.0.20190412以后新建的项目,默认都会添加自定义组件模式标记,之前的版本新建的项目,默认都是非自定义组件的。

继续阅读 »

公告:uni-app将于2019年11月1日起停止支持非自定义组件模式

非自定义组件作为一种被淘汰的技术,为了向下兼容,一直保留在uni-app的核心代码中。

目前uni-app的编译模式过多:有非自定义组件模式、自定义组件模式;有nvue、有vue;nvue有weex编译模式、有uni-app编译模式;还支持纯nvue编译模式。

太多历史兼容,导致编译器复杂度太高,代码冗余很多。

目前在App、微信小程序、百度小程序、支付宝小程序、头条小程序上,仍然有部分开发者一直未升级到自定义组件模式。请开发者快速升级。

uni-app将于2019年11月1日起停止支持非自定义组件模式,届时,新版HBuilderX真机运行和云打包,都不再支持非自定义组件模式。HBuilderX的云打包,只向下保留2个版本。再升级1个版本后,老版打包机也不再支持非自定义组件模式。

升级自定义组件模式,开发者将得到更好的应用性能、更便利的调试体验。

升级方式

在manifest.json可配置编译模式。

  • 方式1. 可视化界面
    在App、微信、百度、支付宝、头条小程序配置界面,勾上自定义组件编译模式

  • 方式2. 源码视图
    如下:
    {  
    "name" : "",  
    "appid" : "",  
    "app-plus" : {  
        "usingComponents" : true  
    },  
    "mp-weixin" : {  
        "appid" : "",  
        "usingComponents" : true  
    },  
    "mp-alipay" : {  
        "usingComponents" : true  
    },  
    "mp-baidu" : {  
        "usingComponents" : true  
    },  
    "mp-toutiao" : {  
        "usingComponents" : true  
    }  
    }

升级后,如代码运行异常,参考下文调整

https://ask.dcloud.net.cn/article/35851

如果你不知道自己是什么编译模式,通过以下方式查看:
打开manifest源码视图里,看每个平台下是否有 "usingComponents" : true。
如果值为true就是自定义组件模式。
如果值为false或没有该键名则为非自定义组件模式。

在HBuilderX 1.9.0.20190412以后新建的项目,默认都会添加自定义组件模式标记,之前的版本新建的项目,默认都是非自定义组件的。

收起阅读 »

如何获取微信红包金额(500元 有偿)

微信

如果用h5+获取微信金额
有偿 100 给demo 感谢

如果用h5+获取微信金额
有偿 100 给demo 感谢

HBuilderX之无法在小程序开发工具中启动uniapp

HBuilderX

除了在小程序开发工具中“安全”中开启服务端口外,还需要先打开小程序开发工具,然后在HBuilderX中启动uniapp项目,启动uniapp期间确保小程序开发工具始终在最前端显示...

除了在小程序开发工具中“安全”中开启服务端口外,还需要先打开小程序开发工具,然后在HBuilderX中启动uniapp项目,启动uniapp期间确保小程序开发工具始终在最前端显示...

垃圾分类小程序关于支付宝平台base64问题

base64 支付宝小程序
        ```javascript  

uni.request({
url: aaa,
method: 'GET',
dataType: 'base64',
success: function(res) {
var base64 = res.data.slice(23);

                                                    // that.dataList.picList.push(base64);  
                                                    console.log(base64);  
                                                that.getTextFromImage(base64);  

                                                }  

                });

在支付宝编辑器中模拟器可以正常转换   base64但是真机就会没有反应
继续阅读 »
        ```javascript  

uni.request({
url: aaa,
method: 'GET',
dataType: 'base64',
success: function(res) {
var base64 = res.data.slice(23);

                                                    // that.dataList.picList.push(base64);  
                                                    console.log(base64);  
                                                that.getTextFromImage(base64);  

                                                }  

                });

在支付宝编辑器中模拟器可以正常转换   base64但是真机就会没有反应
收起阅读 »