предисловие
Недавно компания собиралась разработать апплет электронной коммерции, и он начал работать после прочтения документа в спешке. Общий опыт разработки лично для меня не очень хорош, особенно если вы привыкли к разработке Vue раньше и вдруг разрабатываете небольшие программы, это кажется очень безвкусным. Ниже приводится сводка некоторых проблем и решений, с которыми я столкнулся при разработке, только для справки.
Внедрить иконочный шрифт
Вводить значки шрифтов в апплет сложнее, чем в веб, короче говоря, это занимает три шага:
-
Загрузите iconfont, скопируйте iconfont.css в iconfont.wxss и импортируйте его в app.wxss.
-
Просмотрите онлайн-ссылку на iconfont в режиме юникода, замените ссылку в iconfont.wxss на удаленную ссылку
- Введите соответствующий класс значков в файл wxml.
<icon class="iconfont icon-pay"></icon>
бесполезный
VSCode имеет легкий менее плагин, который является самым простым способом для меня использовать меньше
-
vscode установить проще без плагина
-
Создайте каталог less для хранения меньшего количества файлов
-
Добавить комментарии компиляции в заголовок файла
// out: ../pages/index/index.wxss, compress: true, sourceMap: false
-
ctrl+s автоматически компилируется после сохранения
скомпилированный результат
кнопка сброса
Кнопки в апплете мощные, и кнопки должны использоваться для многих функций, таких как всплывающее окно авторизации пользователя и вызов функций обслуживания клиентов. Стиль по умолчанию, как правило, не может удовлетворить потребности, вы можете сбросить стиль кнопки единообразно, а затем написать свой собственный стиль.
button {
padding: 0;
background: #fff;
line-height: 0;
&::after {
border-color: transparent;
}
}
.button-hover {
background: #fff;
}
Поддержка асинхронного ожидания
async-await — это синтаксис ECMA2017 (ES8), на момент написания этой статьи апплет все еще не поддерживает синтаксис async-await, поэтому необходимо использовать библиотеку регенератора.
- Загрузите regenerator и поместите regenerator-runtime в каталог utils.
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
})
})
}
})
После инкапсуляции все равно очень интересно, еще и расширение удобное
Динамически установить значение в данных
Сценарий приложения: циклический список должен динамически изменять данные, соответствующие идентификатору в списке, в соответствии с выбранным элементом.
// 动态传递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
})
}
})
гибкий макет, многоточие переполнения не работает
Список заказов обычно представляет собой изображение слева и название или описание справа. В это время ширина изображения фиксирована, а длина заголовка является адаптивной.
.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
})
}
Парсинг HTML с помощью wxParse
- скачать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 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()
wx.stopPullDownRefresh()
},
// 上拉
onReachBottom: function () {
if(this.data.list.length >= this.data.count) {
return false
}
this.setData({
page: this.data.page + 1
})
this.getData()
},
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) =>{
resolve(res.data)
},
fail:(err) => {
reject(err)
}
})
})
}
})
динамический заголовок
Динамически установить заголовок при загрузке
wx.setNavigationBarTitle({
title: '新标题'
})
Эпилог
Выше перечислены лишь некоторые проблемы, с которыми я столкнулся в процессе разработки.Если есть какие-либо ошибки, прошу покритиковать и исправить их.Спасибо за прочтение.