最近公司要开发一款电商小程序,匆忙看了一遍文档就开始干活了。整体开发体验个人感觉不太好,特别是如果之前习惯了Vue开发,突然去开发小程序,感觉很鸡肋。以下是我在开发中遇到的一些问题以及解决方法的总结,仅供参考
引入iconfont
在小程序中引入字体图标要比web麻烦一些,简单说需要三步:
下载iconfont,把iconfont.css复制到iconfont.wxss,在app.wxss中引入
查看iconfont在unicode模式下的在线链接,替换iconfont.wxss中的链接为远程链接
在wxml文件中引入对应的icon class
<icon class="iconfont icon-pay"></icon>复制代码
使用less
vscode有一个easy less插件,是我感觉使用less最简单的方式
vscode安装easy less插件
创建一个less目录,用于存放less文件
文件头部添加编译注释
// out: ../pages/index/index.wxss, compress: true, sourceMap: falsectrl + s保存后自动编译
编译后的结果
按钮重置
小程序中的按钮功能强大,很多功能必须要用按钮,比如弹出用户授权,调用客服功能。默认的样式一般无法满足需求,可以把按钮样式统一重置,然后自己写样式
button { padding: 0; background: #fff; line-height: 0;
&::after { border-color: transparent;
}
}.button-hover { background: #fff;
}
复制代码支持async-await
async-await是ES7的语法,截止我写这篇文章为止,小程序还是不支持async-await语法的,所以需要使用regenerator这个库
下载regenerator,并把regenerator-runtime并放到utils目录下
2. 在util.js引入 import regeneratorRuntime from './regenerator-runtime/runtime-module'
封装wxRequest,让它支持async-await
const wxRequest = async (url, params = {}) => { Object.assign(params, { token: wx.getStorageSync('token')
}) // 所有的请求,header默认携带token
let header = params.header || { 'Content-Type': 'application/json', 'token': params.token || ''
} let data = params.data || {} let method = params.method || 'GET'
// hideLoading可以控制是否显示加载状态
if (!params.hideLoading) {
wx.showLoading({ title: '加载中...',
})
} let res = await new Promise((resolve, reject) => {
wx.request({ url: url, method: method, data: data, header: header, success: (res) => { if (res && res.statusCode == 200) {
resolve(res.data)
} else {
reject(res)
}
}, fail: (err) => {
reject(err)
}, complete: (e) => {
wx.hideLoading()
}
})
}) return res
}export {
wxRequest
}
复制代码使用方法:
import regeneratorRuntime from '../../utils/regenerator-runtime/runtime-module.js'import {
wxRequest
} from '../../utils/util.js'Page({ data: { list:[], count: 0, page: 1, limit: 10
}, onLoad: function() { this.getList() // 请求已经结束 做其他事
}, getList: async function() { await wxRequest(app.globalData.baseUrl + '/test',{ hideLoading: true, data: { limit: this.data.limit, page: this.data.page
}
}).then((ret) => { this.setData({ list: ret.data.data, count: ret.data.num
})
})
}
})
复制代码封装之后用起来还是很爽的,扩展起来也方便
动态设置data中某个值
应用场景:循环出来的列表,需要根据点击项,动态改变列表中对应id的数据
// 动态传递id<block wx:for="{{list}}" wx:key="{{index}}">
<view catch:tap="onChangeName" data-id="{{item.id}}"></view>
</block>
Page({ data: {
list:[{
id: 0,
name: 'wang'
},{
id: 1,
name: 'li'
}]
},
onChangeName: function(event){ // 拿到id
let id = event.target.dataset.id
let key = `list[${id}].name`, val = 'zhang'
// 设置值
this.setData({
[key]: val
})
}
})
复制代码flex布局,溢出省略号无效
订单列表一般都是左边一个图片,右边是标题或描述。这时候图片宽度是固定的,标题长度自适应
.wrap { display: flex;
}
.sub { flex: 1;
width: 0; // 宽度设为0}
.sub text { display: block; // 一定要设置成block}
<view calss="wrap"> <image src="i.png"/>
<view class="sub">
<text>一段文本一段文本一段文本一段文本一段文本一段文本</text>
<view>其他</view>
</view></view>复制代码组件事件传递
任务:父组件向子组件传递初始数据,当子组件点击以后可以triggerEvent自定义事件,父组件执行自定义事件,重新请求数据并传给子组件
/* 子组件 */<view>
<view bind:tap="setId" data-id="1"></view>
</view>
properties: {
list: { type: Array,
default: []
}
},
methods: {
setId(e) { let id = e.currentTarget.dataset.id
this.triggerEvent('deleteFav', id)
}
}
/* 父页面 */
<child bind:customEvent="deleteFav"></child>
data: {
list: []
},
deleteFav(e) { let id = e.detail // 获取传递过来的数据
// 根据id请求数据,然后重新setData let newData = [1,2,3]
this.setData({
list: newData
})
}
复制代码使用wxParse解析HTML
下载 wxParse ,放到utils目录下
在JS页面引入:
import WxParse from '../../utils/wxParse/wxParse'
Page({ data:{ contentHTML:'' // 解析后的HTML
}, onLoad: function() { // 请求到的HTML数据
let content = '<div>我是HTML代码</div>', that = this;
WxParse.wxParse('contentHTML', 'html', content, that, 0);
}
})
复制代码显示解析内容
<import src="../../utils/wxParse/wxParse.wxml"/><view>
<!-- 显示内容 -->
<template is="wxParse" data="{{wxParseData:contentHTML.nodes}}" /></view>复制代码图片等比例
image标签有个mode属性,可以设置图片如何显示,如果文档看的不仔细还真容易发现
<image src="test.png" mode="widthFix"/>复制代码
上拉加载和下拉刷新
{ "onReachBottomDistance": 0, "enablePullDownRefresh": true}
复制代码data: {
limit: 30,
page: 1,
list:[],
count:0},// 下拉onPullDownRefresh: function () { this.setData({
page: 1,
list:[]
}) this.getData()
},// 上拉onReachBottom: function () { if(this.data.list.length >= this.data.count) { return false
} this.setData({
page: this.data.page + 1
}) this.getData()
wx.stopPullDownRefresh()
},
getData: async function () {
await wxRequest(app.globalData.baseUrl + '/test', { data: {
page: this.data.page,
limit: this.data.limit,
}
}).then((ret) => {
let list = this.data.list.concat(ret.data.list) this.setData({
list: list,
count: ret.data.count
})
})
}
复制代码上传图片
任务:小程序上传图片到服务器,最多上传三张,前端可以删除图片
效果图如下
使用到的API有两个:wx.uploadFile wx.chooseImage
示例WXML:
<view class="sale after-pic">
<block wx:for="{{imgList}}" wx:key="{{index}}">
<view class="pic">
<image src="{{item}}" />
<icon type="clear" size="20" catchtap="clearImg" data-id="{{index}}"/>
</view>
</block>
<image src="../../images/upload.png" catchtap="chooseImage" /></view><button catchtap="onSub">提交</button>复制代码imgList是wx.chooseImage成功后返回的图片临时地址
示例JS
Page({ data: { imgList:[]
}, // 使用async await是因为图片上传是异步的
onSub: async function() { // 点击提交后,开始上传图片
let imgUrls = [] for (let index = 0; index < this.data.imgList.length; index++) { await this.uploadFile(this.data.imgList[index]).then((res) => { // 这里要注意把res.data parse一下,默认是字符串
let parseData = JSON.parse(res.data)
imgUrls.push(parseData.data) // 图片地址
})
} console.log(imgUrls) // 3张图片上传成功后,执行其他操作
}, // 删除某张图片
clearImg: function (params) { let imgList = this.data.imgList let id = params.currentTarget.dataset.id // 图片索引
imgList.splice(id, 1) // 删除
this.setData({ imgList: imgList
})
}, chooseImage: function (params) {
wx.chooseImage({ count: 3, // 做多3张
sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: (res) => { // 存储临时地址
this.setData({ imgList: res.tempFilePaths
})
}
})
}, uploadFile: function (filePath) { // 返回Promise是为了解决图片上传的异步问题
return new Promise( (resolve, reject) => {
wx.uploadFile({ url: app.globalData.baseUrl + '/file/upload', // 上传地址
filePath: filePath, name: 'file', // 这里的具体值,问后端人员
formData: {}, header: { "Content-Type": "multipart/form-data"
}, success: (res) =>{ // 图片上传成功后,后端会返回一个地址,可以把它存到imgUrls
this.imgUrls.push(res.data.data)
}, fail:(err) => { console.log(err)
}
})
})
}
})
复制代码动态标题
onLoad的时候动态设置标题
wx.setNavigationBarTitle({ title: '新标题'})
复制代码 



