在微信公众平台找到小程序前往注册
注:注册个人版与企业版区别是个人版权限较低,无法使用微信支付和物流管理,注册企业版需要营业执照
在首页的开发设置中查看自己的AppID
使用测试号或者注册之后的个人AppID进行项目创建,选择不使用云服务
pages文件夹中是小程序中的每个页面
app.json文件中pages数组里包含各个页面的路由,数组的第一项是小程序首页
一个小程序页面由四个文件组成
文件类型 | 必需 | 作用 |
---|---|---|
js | 是 | 页面逻辑 |
wxml | 是 | 页面结构 |
json | 否 | 页面配置 |
wxss | 否 | 页面样式表 |
用于设置小程序的状态栏、导航条、标题、窗口背景色。
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
navigationBarBackgroundColor | HexColor | #000000 | 导航栏背景颜色,如#000000 |
navigationBarTextStyle | string | white | 导航栏标题颜色,仅支持black/white |
navigationBarTitleText | string | 导航栏标题文字内容 | |
backgroundTextStyle | string | dark | 下拉loading的样式,仅支持dark/light |
enablePullDownRefresh | boolean | false | 是否开启全局的下拉刷新。 详见 Page.onPullDownRefresh |
更多属性请查看官方文档
如果小程序是一个多 tab 应用(客户端窗口的底部或顶部有 tab 栏可以切换页面),可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页面。
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
list | Array | 是 | tab 的列表,详见 list 属性说明,最少 2 个、最多 5 个 tab | |
selectedColor | HexColor | 是 | tab 上的文字选中时的颜色,仅支持十六进制颜色 | |
backgroundColor | HexColor | 是 | tab 的背景色,仅支持十六进制颜色 | |
borderStyle | string | 否 | black | tabbar 上边框的颜色, 仅支持 black / white |
position | string | 否 | bottom | tabBar 的位置,仅支持 bottom / top |
更多属性请查看官方文档
其中 list 接受一个数组,只能配置最少 2 个、最多 5 个 tab。tab 按数组的顺序排序,每个项都是一个对象,其属性值如下:
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
pagePath | string | 是 | 页面路径,必须在 pages 中先定义 |
text | string | 是 | tab 上按钮文字 |
iconPath | string | 否 | 图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。 当 position 为 top 时,不显示 icon。 |
selectedIconPath | string | 否 | 选中时的图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。 当 position 为 top 时,不显示 icon。 |
app.json 中的部分配置,也支持对单个页面进行配置,可以在页面对应的 .json 文件来对本页面的表现进行配置。
页面中配置项在当前页面会覆盖 app.json 中相同的配置项(样式相关的配置项属于 app.json 中的 window 属性,但这里不需要额外指定 window 字段),具体的取值和含义可参考全局配置文档中说明。
文件内容为一个 JSON 对象,有以下属性:
属性 | 类型 | 默认值 | 描述 | 最低版本 |
---|---|---|---|---|
navigationBarTitleText | string | 导航栏标题文字内容 | ||
enablePullDownRefresh | boolean | false | 是否开启当前页面下拉刷新。 详见 Page.onPullDownRefresh |
|
usingComponents | Object | 否 | 页面自定义组件配置 | 1.6.3 |
更多属性请查看官方文档
sitemap配置
类似于vue、react,小程序使用{{}}进行数据绑定,双大括号内支持表达式语法。遇到变量需要在页面js文件中注册页面的方法里的data对象中写入。
组件的属性中也可以用{{}}。
初始化数据
数据绑定
在组件的属性使用 wx:for 实现变量的循环遍历,在内容中使用临时变量{{item}}获取遍历的内容,使用{{index}}获取遍历的索引。
使用 wx:for-item , wx:for-index 修改在内容中的临时变量。
建议在用wx:for时添加wx:key。
wx:key , wx:for-item , wx:for-index 后面的值不需要加{{}}
data: {
myname:"zimin",
ids:["aaa","bbb","ccc"],
list:["zimin","mjh","fx","lc"]
}
<view wx:for="{{list}}" wx:key="index">
{{item}}---{{index}}
</view>
<view wx:for="{{list}}" wx:for-item="ziminitem" wx:for-index="ziminindex"
wx:key="ziminindex">
{{ziminitem}}---{{ziminindex}}
</view>
wx:if和wx:else控制节点的动态删除和创建
hidden控制节点的动态隐藏和显示
data: {
isCreated:true,
isHidden:false
}//状态
<view wx:if="{{isCreated}}">我是动态创建和删除---1</view>
<view wx:else>我是动态创建和删除---2</view>
<view hidden="{{isHidden}}">我是动态隐藏和显示</view>
类型 | 触发条件 |
---|---|
tap | 手指触摸后马上离开 |
更多属性请查看官方文档
事件分为冒泡事件和非冒泡事件:
bind普通事件绑定
catch绑定并阻止事件冒泡
capture-bind、capture-catch事件的捕获阶段
绑定的方法不可以加括号
<button type="primary" bindtap="handleTap">click1</button>
<button type="primary" catchtap="handleTap">click2</button>
方法写在对应的js文件中
this指向小程序实例
小程序中改变状态的唯一方法是setData
详细内容请查看官方文档
WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。
WXSS 用来决定 WXML 的组件应该怎么显示。
为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。
与 CSS 相比,WXSS 扩展的特性有:
设备 | rpx换算px(屏幕宽度/750) | px换算rpx(750/屏幕宽度) |
---|---|---|
iPhone5 | 1rpx=0.42px | 1px=2.34rpx |
iPhone6 | 1rpx=0.5px | 1px=2rpx |
iPhone6 Plus | 1rpx=0.552px | 1px=1.81rpx |
建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。
注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况。
目前支持的选择器请查看官方文档
定义在 app.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。
WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。
注意事项
更多内容请查看官方文档
WXS语法参考
handleAjax(){
//数据
//1-没有跨域限制
//2-安全域名添加
wx.request({
url:'https://i.maoyan.com/api/mmdb/movie/v3/list/hot.json?ct=%E5%8D%97%E4%BA%AC&ci=55&channelId=4',
method:"get",
data:{
},
success:(res)=>{
console.log(res)
this.setData({
datalist:res.data.data.hot
})
},
fail:()=>{
}
})
}
安全域名的添加在自己的小程序后台中
首先找到开发管理
然后找到开发设置
在服务器域名中添加修改
<image src="https://res.wx.qq.com/wxdoc/dist/assets/img/0.4cb08bb4.jpg" mode="bottom"/>
属性内容信息请查看官方文档
<swiper indicator-dots="{{true}}" circular="{{true}}" autoplay="{{true}}" interval="3000">
<swiper-item wx:for="{{datalist}}" wx:key="index">
<image src="{{item.image_url}}" mode="widthFix" style="width: 100%;"/>
</swiper-item>
</swiper>
属性内容信息请查看官方文档
<view>水平方向</view>
<scroll-view class="box_horizontal" enable-flex="{{true}}" scroll-x="{{true}}"
bindscrolltolower="handleRight">
<view class="item_horizontal">aaaaa</view>
<view class="item_horizontal">bbbbb</view>
<view class="item_horizontal">ccccc</view>
<view class="item_horizontal">ddddd</view>
</scroll-view>
<view>垂直方向</view>
<scroll-view class="box" scroll-y="{{true}}" bindscrolltolower="handlescrolltolower"
refresher-enabled="{{true}}" bindrefresherrefresh="handleRefresh" refresher-triggered="{{isRefresh}}">
<view class="item">1111111111111</view>
<view class="item">2222222222222</view>
<view class="item">3333333333333</view>
</scroll-view>
属性内容信息请查看官方文档
例:多选框及图标组件
<icon class="icon-box-img" type="success_no_circle" size="20" color="#C9C9C9"></icon>
<view wx:for="{{checkList}}" wx:key="index"
style="display: flex;justify-content: space-around;padding: 10px;">
<checkbox bindtap="handleTap" data-index="{{index}}" checked="{{item.isChecked}}"></checkbox>
<view>
<view>{{item.name}}</view>
<view>价格:¥{{item.price}}</view>
</view>
<view>{{item.number}}</view>
</view>
更多组件请查看官方文档
新建一个放置全部组件的文件夹,创建单个组件文件夹,右键新建Component即可创建一个新的组件
在每个页面的json文件中引入组件,即可在该页面的wxml文件里使用
{
"usingComponents": {
"navbar":"../../components/navbar/navbar"
}
}
在父组件中给子组件附上属性
<navbar list="{{cateItems}}" current="{{current}}"></navbar>
在子组件的js文件中的properties中添加相同的属性名即可实现父传子
properties: {
list:{
type:Array,//接收类别
value:["正在热映","即将上映"]//默认值
},
current:{
type:Number,
value:0
}
}
在父组件中给子组件绑定一个自定义事件
<navbar list="{{cateItems}}" current="{{current}}"
bindParentEvent="handleEvent"></navbar>
handleEvent(evt){
console.log("父组件定义,执行",evt.detail)
this.setData({
current:evt.detail
})
}
在子组件的js文件中可以通过this.triggerEvent触发在父组件中的自定义事件并传值,即可实现子传父
handleClick(evt){
/* this.setData({
current:evt.currentTarget.dataset.index
}) */
this.triggerEvent("ParentEvent",evt.currentTarget.dataset.index)
}
在子组件中使用slot插槽
使用多插槽时需要在子组件页面的js文件中加入以下内容
options:{
multipleSlots:true//在组建定义时的选项中启用多slot支持
}
<top-header>
<button slot="left" bindtap="handleTap">返回</button>
<button slot="right">首页</button>
</top-header>
<view class="box">
<slot name="left"></slot>
<text>topheader</text>
<slot name="right"></slot>
</view>
slot插槽可以简化组件通信问题
在组件的js文件中lifetimes属性是组件的生命周期
lifetimes:{
attached: function() {
//console.log("attached")
// 在组件实例进入页面节点树时执行
this.intervalId=setInterval(()=>{
console.log("11")
if(this.data.count===0){
//通知父组件移除自己
this.triggerEvent("event")
return
}
this.setData({
count:this.data.count-1
})
},1000)
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
//console.log("detached")
clearInterval(this.intervalId)
}
}
生命周期 | 参数 | 描述 | 最低版本 |
---|---|---|---|
attached | 无 | 在组件实例进入页面节点树时执行 | 1.6.3 |
detached | 无 | 在组件实例被从页面节点树移除时执行 | 1.6.3 |
更多内容请查看官方文档
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
this.handleAjax()
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
console.log("show")
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
console.log("hide")
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
详细内容请查看官方文档
更多属性及内容请查看官方文档
显示消息提示框
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|---|
title | string | 是 | 提示的内容 | ||
icon | string | success | 否 | 图标 | |
image | string | 否 | 自定义图标的本地路径,image的优先级高于icon | 1.1.0 | |
duration | number | 1500 | 否 | 提示的延迟时间 | |
mask | boolean | false | 否 | 是否显示透明蒙层,防止触摸穿透 | |
success | function | 否 | 接口调用成功的回调函数 |
clickBtn(){
wx.showToast({
title: '加载中加载中加载中加载中加载中加载中加载中加载中加载中加载中加载中加载中加载中加载中加载中',
icon:"success",
duration:1500,
mask:true,
success:res=>{
console.log(res)
}
})
}
showModal显示模态对话框
更多属性及内容请查看官方文档
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|---|
title | string | 否 | 提示的标题 | ||
content | string | 否 | 提示的内容 | ||
showCancel | boolean | true | 否 | 是否显示取消按钮 | |
cancelColor | string | #000000 | 否 | 取消按钮的文字颜色,必须是16进制格式的颜色字符串 | |
editable | boolean | false | 否 | 是否显示输入框 | 2.17.1 |
placeholderText | string | 否 | 显示输入框时的提示文本 | 2.17.1 | |
success | function | 否 | 接口调用成功的回调函数 |
wx.showModal({
title: '请输入验证码',
//content: '删除之后不可恢复,请谨慎删除',
placeholderText:"请输入...",
editable:true,
success:res=>{
console.log(res)
}
})
showLoading显示 loading 提示框。需主动调用 wx.hideLoading 才能关闭提示框
更多内容请查看官方文档
onLoad(options) {
wx.showLoading({
title: '加载中...',
mask:true
})
setTimeout(()=>{
wx.hideLoading()
},2000)
}
更多属性及内容请查看官方文档
显示操作菜单
onLoad(options) {
wx.showActionSheet({
itemList: this.data.listArr,
success :res=> {
console.log(this.data.listArr[res.tapIndex])
},
fail: (res) =>{
console.log(res.errMsg)
}
})
}
setNavigationBarTitle动态设置当前页面的标题
标题设置配置项权重不如js设置高
更多属性内容请查看官方文档
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
title | string | 是 | 页面标题 |
wx.setNavigationBarTitle({
title: 'onload中修改的标题'
})
setNavigationBarColor设置页面导航条颜色
更多属性内容请查看官方文档
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
frontColor | string | 是 | 前景颜色值,包括按钮、标题、状态栏的颜色,仅支持#ffffff和#000000 |
backgroundColor | string | 是 | 背景颜色值,有效值为十六进制颜色 |
wx.setNavigationBarColor({
frontColor:"#000000",
backgroundColor:"#eee"
})
showNavigationBarLoading在当前页面显示导航条加载动画
hideNavigationBarLoading在当前页面隐藏导航条加载动画
wx.showNavigationBarLoading()
setTimeout(()=>{
wx.hideNavigationBarLoading()
},2000)
hideHomeButton()隐藏返回首页按钮。
微信7.0.7版本起,当用户打开的小程序最底层页面是非首页时,默认展示“返回首页”按钮,开发者可在页面 onShow 中调用 hideHomeButton 进行隐藏。
wx.hideHomeButton()
微信小程序提供了自己的组件库
在app.json文件中添加以下内容即可开启使用WeUI组件库
"useExtendedLib": {
"weui": true
}
然后在 page.json 中引入组件
{
"usingComponents": {
"mp-****": "weui-miniprogram/****/****"
}
}
WeUI组件库文档
扩展组件是对小程序内置组件能力的补充,包括一些常见的功能组件,持续补充中。
找到想要插入的组件,在项目目录下打开powershell通过npm安装(一个项目第一次使用扩展组件需要进行npm init初始化)
npm i @miniprogram-component-plus/******
最后在page.json文件中引入组件
"mp-****":"@miniprogram-component-plus/****"
查看官方文档
微信小程序基础实战练习——手机购买
使用个人AppID进行项目创建,选择微信云服务
点击云开发开启云服务(新用户一个月免费试用时间),右键cloudfunctions文件,显示当前环境
如果开启了云服务却不显示当前环境,选择左上角项目找到重新打开此项目,点击后即可出现
在云控制台中找到数据库可对数据库进行一些操作
集合名称右边加号可添加新的集合
在一个集合里点击添加记录可添加新的记录
每个记录可点击添加字段来添加新的字段
在数据库中的数据权限中可调整用户对数据的权限
更多内容请查看官方文档
详细内容请查看官方文档
引入数据库
const db=wx.cloud.database()
通过get方法获取数据库列表中的内容
//查询记录
getData(){
db.collection("demolist").get({
success:res=>{
console.log(res)
this.setData({
dataObj:res.data
})
}
})
}
也可以通过Promise形式获取
db.collection("demolist").get().then(res=>{
this.setData({
dataObj:res.data
})
})
使用数据库 API 提供的 where 方法我们可以构造复杂的查询条件完成复杂的查询任务。
db.collection("demolist").where({
author:"vcc"
}).get().then(res=>{
console.log(res)
})
使用add方法可以添加内容到数据库
add方法和get类似
//添加数据
addData(){
wx.showLoading({
title: '数据加载中...',
mask:true
})
db.collection("demolist").add({
data:{
title:"测试标题2",
author:"李四",
content:"测试的内容部分测试的内容部分测试的内容部分测试的内容部分测试的内容部分"
}
}).then(res=>{
console.log(res)
wx.hideLoading()
})
}
更多内容请查看官方文档
API | 说明 |
---|---|
update | 局部更新一个或多个记录 |
set | 替换更新一个记录 |
db.collection("demolist").doc("34a6377a649d6ae20009118d0dc3fba3").update({
data:{
author:"王进",
posttime:"2020-10-10"
}
}).then(res=>{
console.log(res)
})
db.collection("demolist").doc("34a6377a649d6ae20009118d0dc3fba3").set({
data:{
title:"新视觉新闻标题"
}
}).then(res=>{
console.log(res)
})
正常小程序更改数据库记录需要记录中有_openid字段,没有则无法修改,如需修改可在数据库中的数据权限中可调整用户对数据的权限,选择自定义安全规则
将里面内容修改为如下内容
{
"read": true,
"write": true
}
更多内容请查看官方文档
删除一条记录
对记录使用 remove 方法可以删除该条记录
//删除记录
delData(){
db.collection("demolist")
.doc(myVlu)
.remove()
.then(res=>{
console.log(res)
})
}
删除多条记录
如果需要更新多个数据,需在 Server 端进行操作(云函数)。可通过 where 语句选取多条记录执行删除,只有有权限删除的记录会被删除。
更多内容请查看官方文档
count
//获取记录个数
btnNum(){
/* db.collection("demolist").get().then(res=>{
console.log(res)
}) */
db.collection("demolist").count().then(res=>{
console.log(res)
})
}
watch
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
onChange | function | 是 | 成功回调,回调传入的参数snapshot是变更快照 |
onError | function | 是 | 失败回调 |
snapshot说明
字段 | 类型 | 说明 |
---|---|---|
docChanges | ChangeEvent[] | 更新事件数组 |
docs | object[] | 数据快照,表示此更新事件发生后查询语句对应的查询结果 |
type | string | 快照类型,仅在第一次初始化数据时有值为init |
id | number | 变更事件id |
实现页面动态更新数据
db.collection("demolist").watch({
onChange:res=>{
console.log(res.docs)
this.setData({
dataArr:res.docs
})
},
onError:err=>{
console.log(err)
}
})
更多内容请查看官方文档
where
指定查询条件,返回带新查询条件的新的集合引用
limit
指定查询结果集数量上限
limit 在小程序端默认及最大上限为 20,在云函数端默认及最大上限为 1000
getData(){
db.collection("demolist").limit(3).get()
.then(res=>{
console.log(res)
})
}
orderBy
指定查询排序条件
getData(){
db.collection("demolist").limit(3).orderBy("time","desc").get()
.then(res=>{
console.log(res)
})
}
asc正序
desc倒序
skip
指定查询返回结果时从指定序列后的结果开始返回,常用于分页
getData(){
db.collection("demolist").limit(3).skip(5).orderBy("time","desc").get()
.then(res=>{
console.log(res)
})
}
field
指定返回结果中记录需返回的字段
getData(){
db.collection("demolist").limit(3).skip(3).field({
title:true,
author:true
}).orderBy("time","desc").get()
.then(res=>{
console.log(res)
})
}
更多内容请查看官方文档
数据库操作符,通过 db.command 获取
const db=wx.cloud.database()
const _=db.command
使用(***处是要使用的操作符)
_.***()
查询·比较操作符
eq 等于
neq 不等于
lt 小于
lte 小于等于
gt 大于
gte 大于等于
in 表示要求值在给定的数组内。
查询·逻辑操作符
and 用于表示逻辑 “与” 的关系,表示需同时满足多个查询筛选条件
//and的两种用法
_.and(_.gt(0),_.lt(100))
//_.gte(0).and(_.lte(111))
or 于表示逻辑 “或” 的关系,表示需同时满足多个查询筛选条件。或指令有两种用法,一是可以进行字段值的 “或” 操作,二是也可以进行跨字段的 “或” 操作。
对多个字段操作
db.collection("demolist")
.where(_.or([
{
hits:_.gt(300)
},
{
author:_.eq("李四")
}
]))
.get()
.then(res=>{
this.setData({
dataList:res.data
})
})
查询·字段操作符
exists 判断字段是否存在
查询·数组操作符
size 用于数组字段的查询筛选条件,要求数组长度为给定值
all 用于数组字段的查询筛选条件,要求数组字段中包含给定数组的所有元素
elemMatch 用于设定字段等于指定值
更新·字段操作符
inc 原子操作,用于指示字段自增
remove 用于表示删除某个字段
set 用于设定字段等于指定值
更新·数组操作符
push 对一个值为数组的字段,往数组添加一个或多个值。或字段原为空,则创建该字段并设数组为传入值
pop 对一个值为数组的字段,将数组尾部元素删除
unshift 对一个值为数组的字段,往数组头部添加一个或多个值。或字段原为空,则创建该字段并设数组为传入值
shift 对一个值为数组的字段,将数组头部元素删除
pull 给定一个值或一个查询条件,将数组中所有匹配给定值或查询条件的元素都移除掉
详细内容请查看官方文档
环境存在时,右键cloudfunctions,选择新建Node.js云函数
将数据库引入写在创建的云函数文件夹下的index.js中的init下面
将想要实现的功能return出去
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境
const db=cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
return await db.collection("demolist").get()
}
写完或更新完云函数后右键该云函数文件夹选择上传并部署,否则云函数不更新
或者只有单个文件改变时右键那个文件上传
在想要使用云函数的page.js文件里通过wx.cloud.callFunction使用
wx.cloud.callFunction({
name:"getData"
}).then(res=>{
console.log(res)
})
通过data给云函数传值
wx.cloud.callFunction({
name:"getData",
data:{
num:5
}
}).then(res=>{
console.log(res)
})
// 云函数入口函数
exports.main = async (event, context) => {
var num=event.num
return await db.collection("demolist").limit(num).get()
}
详细内容请查看官方文档
通过wx.cloud.uploadFile()上传文件
将本地资源上传至云存储空间,如果上传至同一路径则是覆盖写
filePath为临时路径
cloudPath为上传到云端路径
clickBtn(){
wx.chooseImage({
success:res=>{
var filePath=res.tempFilePaths[0]
this.cloudFile(filePath)
}
})
},
cloudFile(path){
wx.cloud.uploadFile({
cloudPath:Date.now()+".jpg",
filePath:path
}).then(res=>{
console.log(res)
})
}
clickBtn(){
wx.chooseImage({
success:res=>{
filePath=res.tempFilePaths
filePath.forEach((item,idx)=>{
var fileName=Date.now()+"_"+idx
this.cloudFile(fileName,item)
})
newArr=[]
}
})
},
cloudFile(filename,path){
wx.showLoading({
title: '上传中'
})
wx.cloud.uploadFile({
cloudPath:filename+".jpg",
filePath:path
}).then(res=>{
urlArr.push(res.fileID)
newArr.push(res.fileID)
if(filePath.length==newArr.length){
this.setData({
urlArr
})
wx.hideLoading()
}
})
}