uni-app
支持在 App 和 小程序 中使用小程序自定义组件,从HBuilderX2.4.7起,H5端也可以运行微信小程序组件。
小程序组件不是vue组件,并且每家小程序都有自己的组件规范,比如微信小程序的组件是wxml格式。
平台差异说明
平台 | 支持情况 | 小程序组件存放目录 |
---|---|---|
H5 | 支持微信小程序组件(2.4.7+) | wxcomponents |
App(不含nvue) | 支持微信小程序组件 | wxcomponents |
微信小程序 | 支持微信小程序组件 | wxcomponents |
支付宝小程序 | 支持支付宝小程序组件 | mycomponents |
百度小程序 | 支持百度小程序组件 | swancomponents |
字节跳动小程序、飞书小程序 | 支持字节跳动小程序、飞书小程序组件 | ttcomponents |
QQ小程序 | 支持QQ小程序组件 | wxcomponents |
快手小程序 | 支持快手小程序组件 | kscomponents |
京东小程序 | 支持京东小程序组件 | jdcomponents |
此文档要求开发者对各端小程序的自定义组件有一定了解,没接触过小程序自定义组件的可以参考:
目录结构
┌─wxcomponents 微信小程序自定义组件存放目录
│ └──custom 微信小程序自定义组件
│ ├─index.js
│ ├─index.wxml
│ ├─index.json
│ └─index.wxss
├─mycomponents 支付宝小程序自定义组件存放目录
│ └──custom 支付宝小程序自定义组件
│ ├─index.js
│ ├─index.axml
│ ├─index.json
│ └─index.acss
├─swancomponents 百度小程序自定义组件存放目录
│ └──custom 百度小程序自定义组件
│ ├─index.js
│ ├─index.swan
│ ├─index.json
│ └─index.css
├─pages
│ └─index
│ └─index.vue
│
├─static
├─main.js
├─App.vue
├─manifest.json
└─pages.json
使用方式
在 pages.json
对应页面的 style -> usingComponents 引入组件:
{
"pages": [{
"path": "index/index",
"style": {
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-QQ
"usingComponents": {
"custom": "/wxcomponents/custom/index"
},
// #endif
// #ifdef MP-BAIDU
"usingComponents": {
"custom": "/swancomponents/custom/index"
},
// #endif
// #ifdef MP-ALIPAY
"usingComponents": {
"custom": "/mycomponents/custom/index"
},
// #endif
"navigationBarTitleText": "uni-app"
}
}]
}
在页面中使用
<!-- 页面模板 (index.vue) -->
<view>
<!-- 在页面中对自定义组件进行引用 -->
<custom name="uni-app"></custom>
</view>
代码示例
下面以微信小程序官方自定义组件示例 miniprogram-slide-view (opens new window) 为例演示小程序自定义组件的使用方式。
其他组件使用示例见GitHub:wxcomponents-template (opens new window)。
插件市场有一个完整的vant weapp
引用好的示例工程,详见https://ext.dcloud.net.cn/plugin?id=302 (opens new window)。
目录结构
┌─components
├─wxcomponents
│ └──miniprogram-slide-view
│ ├─index.js
│ ├─index.wxml
│ ├─index.json
│ └─index.wxss
│
├─pages
│ └─slide-view
│ └─slide-view.vue
│
├─static
├─main.js
├─App.vue
├─manifest.json
└─pages.json
pages.json {
"pages": [
{
"path": "slide-view/slide-view",
"style": {
"navigationBarTitleText": "slide-view",
"usingComponents": {
"slide-view": "/wxcomponents/miniprogram-slide-view/index"
}
}
}
]
}
slide-view.vue
<template>
<view class='slide'>
<slide-view width="750" height="110" slide-width="500">
<view slot="left" class="l">
<image src="/static/file_transfer.jpg" class="img"></image>
<view class='text'>
<view class='title'>文件传输助手</view>
<view class='time'>7:00 PM</view>
</view>
</view>
<view slot="right" class="r">
<view class='read'>标为已读</view>
<view class='delete'>删除</view>
</view>
</slide-view>
</view>
</template>
<script>
export default {}
</script>
<style>
.slide {
border-bottom: 1px solid #DEDEDE;
}
.l {
background-color: white;
height: 110rpx;
width: 750rpx;
display: flex;
flex-direction: row;
}
.r {
height: 110rpx;
display: flex;
direction: row;
text-align: center;
vertical-align: middle;
line-height: 110rpx;
}
.read {
background-color: #ccc;
color: #fff;
width: 350rpx;
}
.delete {
background-color: red;
color: #fff;
width: 150rpx;
}
.img {
width: 90rpx;
height: 90rpx;
border-radius: 10rpx;
margin: 10rpx 15rpx;
}
.text {
display: flex;
flex-direction: row;
}
.title {
margin-top: 15rpx;
font-size: 33rpx;
}
.time {
margin-top: 15rpx;
color: #ccc;
font-size: 25rpx;
margin-left: 330rpx;
}
</style>
注意事项
wxcomponents
(或 mycomponents、swancomponents)。HBuilderX 建立的工程 wxcomponents
文件夹在 项目根目录下。vue-cli 建立的工程 wxcomponents
文件夹在 src
目录下。可以在 vue.config.js 中自定义其他目录vue
组件中使用小程序组件时,注意在 pages.json
的 globalStyle
中配置 usingComponents
,而不是页面级配置。vue
的数据和事件绑定方式
attr=""
,改为 :attr="a"
;从 title="复选框"
改为 :title="'复选框' + item"
bind:click="toggleActionSheet1"
改为 @click="toggleActionSheet1"
,目前支付宝小程序不支持 vue
的事件绑定方式,具体参考:支付宝小程序组件事件监听示例 (opens new window)catch:tap="xx"
改为 @tap.native.stop="xx"
wx:if
改为 v-if
wx:for="" wx:key=""
改为v-for="(item,index) in list"
详细的小程序转uni-app语法差异可参考文档https://ask.dcloud.net.cn/article/35786 (opens new window)。
WXS是一套运行在视图层的脚本语言,微信端的规范详见 (opens new window)。
它的特点是运行在视图层。当需要避免逻辑层和渲染层交互通信折损时,可采用wxs。
uni-app可以将wxs代码编译到微信小程序、QQ小程序、app-vue、H5上(uni-app 2.2.5
及以上版本)
与wxs类似,百度小程序提供了Filter、阿里小程序提供了SJS,uni-app也支持使用这些功能,并将它们编译到百度和阿里的小程序端。不过它们的功能还不如wxs强大。此外头条系小程序自身不支持类似功能。
平台差异说明
App | H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 字节跳动小程序、飞书小程序 | QQ小程序 |
---|---|---|---|---|---|---|
√(不支持nvue) | √ | √ | SJS | Filter | x | √ |
App端nvue解决此类需求,不应该使用wxs,而是使用bindingx。
wxs示例
以下是一些使用 WXS 的简单示例,要完整了解 WXS 语法,请参考WXS 语法参考 (opens new window)。本示例使用wxs响应touchmove
事件,减少视图层与逻辑层通信,使滑动更加丝滑。
<template>
<view>
<view class="area">
<view @touchstart="test.touchstart" @touchmove="test.touchmove" class="movable">{{test.msg}}</view>
</view>
</view>
</template>
<script module="test" lang="wxs">
var startX = 0
var startY = 0
var lastLeft = 50; var lastTop = 50
function touchstart(event, ins) {
console.log("touchstart")
var touch = event.touches[0] || event.changedTouches[0]
startX = touch.pageX
startY = touch.pageY
}
function touchmove(event, ins) {
var touch = event.touches[0] || event.changedTouches[0]
var pageX = touch.pageX
var pageY = touch.pageY
var left = pageX - startX + lastLeft
var top = pageY - startY + lastTop
startX = pageX
startY = pageY
lastLeft = left
lastTop = top
ins.selectComponent('.movable').setStyle({
left: left + 'px',
top: top + 'px'
})
return false
}
module.exports = {
msg: 'Hello',
touchstart: touchstart,
touchmove: touchmove
}
</script>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style>
.area{
position: absolute;
width: 100%;
height: 100%;
}
.movable{
position: absolute;
width: 100px;
height: 100px;
left: 50px;
top: 50px;
color: white;
text-align: center;
line-height: 100px;
background-color: red;
}
</style>
支付宝小程序,百度小程序官方暂未支持事件响应,不过也可以使用对应的SJS、Filter过滤器实现一些数据处理的操作,以下代码展示了一个时间格式化的小功能
index.vue
<template>
<view>
<view>
{{timestr}} 是
</view>
<view>
{{utils.friendlyDate(timestamp)}}
</view>
</view>
</template>
<script module="utils" lang="filter" src="./utils.filter.js"></script>
<script module="utils" lang="sjs" src="./utils.sjs"></script>
<script>
export default {
data() {
return {
timestr: '2019/08/22 10:10:10',
timestamp: 0
}
},
created() {
this.timestamp = new Date(this.timestr).getTime()
},
methods: {
}
}
</script>
utils.sjs
与 utils.filter.js
内容一致
export default {
friendlyDate: (timestamp) => {
var formats = {
'year': '%n% 年前',
'month': '%n% 月前',
'day': '%n% 天前',
'hour': '%n% 小时前',
'minute': '%n% 分钟前',
'second': '%n% 秒前',
};
var now = Date.now();
var seconds = Math.floor((now - parseInt(timestamp)) / 1000);
var minutes = Math.floor(seconds / 60);
var hours = Math.floor(minutes / 60);
var days = Math.floor(hours / 24);
var months = Math.floor(days / 30);
var years = Math.floor(months / 12);
var diffType = '';
var diffValue = 0;
if (years > 0) {
diffType = 'year';
diffValue = years;
} else {
if (months > 0) {
diffType = 'month';
diffValue = months;
} else {
if (days > 0) {
diffType = 'day';
diffValue = days;
} else {
if (hours > 0) {
diffType = 'hour';
diffValue = hours;
} else {
if (minutes > 0) {
diffType = 'minute';
diffValue = minutes;
} else {
diffType = 'second';
diffValue = seconds === 0 ? (seconds = 1) : seconds;
}
}
}
}
}
return formats[diffType].replace('%n%', diffValue);
}
}
注意
引入方式
<!-- 内联 -->
<script module="test" lang="wxs">
//...code
</script>
<script module="utils" lang="filter">
//...code
</script>
<!-- 外部引入 -->
<script module="utils" lang="wxs" src="./utils.wxs"></script>
<script module="utils" lang="filter" src="./utils.filter.js"></script>
<script module="utils" lang="sjs" src="./utils.sjs"></script>
module
所指定的模块名不可与data
、methods
、computed
内的属性重名<script>
标签引入script
的标签属性name
、from
被统一为了module
、src
以便后续实现多平台统一写法function
函数wxcomponents
也可以使用wxsnvue
页面暂不支持wxs、sjs、filter.jsscript
标签会分别被打包至对应支持平台,不需要额外写条件编译HBuilderX 2.2.5
开始,不推荐使用各个小程序自有的引入方式,推荐使用script
标签引入