Рука об руку для реализации апплета WeChat для электронной коммерции (часть 1)
предисловие
Основанная на собственной структуре апплета WeChat, небольшая программная версия электронной коммерции, реализованная с помощью широко используемых собственных компонентов и официальных API-интерфейсов, поможет вам шаг за шагом перейти от 0 к 1, чтобы по-настоящему реализовать апплет WeChat.Исходный код: https://github.com/panzekun/wx_procedure
1. Создайте небольшой программный проект
Откройте инструмент разработчика WeChat, нажмите «Новый проект», выберите апплет, AppId использует тестовый идентификатор при разработке и должен быть зарегистрирован при публикации и производстве.
2, проект инициализации
3. Реализовать заголовок и нижнюю навигацию TabBar
app.json
{
"pages": [
"pages/home/index",
"pages/category/index",
"pages/cart/index",
"pages/user/index",
"pages/search/index"
],
"window": {
"navigationBarTitleText": "从0到1实战微信小程序",
"navigationBarBackgroundColor": "#eb4450",
"navigationBarTextStyle": "black",
"backgroundColorTop": "#ffffff",
"backgroundColorBottom": "#ffffff",
"backgroundColor": "#ffffff"
},
"tabBar": {
"color": "#333333",
"selectedColor": "#f06c7a",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/home/index",
"iconPath": "static/tabBar/home.png",
"selectedIconPath": "static/tabBar/home-on.png",
"text": "首页"
},
{
"pagePath": "pages/category/index",
"iconPath": "static/tabBar/category.png",
"selectedIconPath": "static/tabBar/category-on.png",
"text": "分类"
},
{
"pagePath": "pages/cart/index",
"iconPath": "static/tabBar/cart.png",
"selectedIconPath": "static/tabBar/cart-on.png",
"text": "购物车"
},
{
"pagePath": "pages/user/index",
"iconPath": "static/tabBar/user.png",
"selectedIconPath": "static/tabBar/user-on.png",
"text": "我的"
}
]
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
Удобное управление
Сохраните его в пути записи страницы и автоматически создайте соответствующую папку и соответствующий js json wxml wxss.
4. Создайте домашнюю страницу
Сначала эффект изображения
4.1 Анализ функций главной страницы
код
<!--pages/home/index.wxml-->
<page class="home">
<!-- 搜索 -->
<view class="shop-input">
<search-input></search-input>
</view>
<!-- 轮播图 -->
<view class="shop-swiper">
<swiper class="" indicator-dots autoplay interval="5000">
<block wx:for="{{swiperList}}" wx:key="{{item}}">
<swiper-item class="" item-id="">
<image class="" src="{{item.url}}" mode="widthFix" />
</swiper-item>
</block>
</swiper>
</view>
<!-- 分类数据 -->
<view class="category-list">
<block wx:for="{{categoryList}}" wx:key="{{item.name}}">
<view class="category" bindtap="hancleClickItem" data-itemList="{{item}}">
<view class="img">
<image src="{{item.image_src}}" mode="widthFix" />
</view>
<view>
<view class="text">{{item.name}}</view>
</view>
</view>
</block>
</view>
<!-- 广告图 -->
<view class="banner">
<MarqueeUp />
<view class="img-box">
<image src="https://ae01.alicdn.com/kf/H5470c644e6454719a610620f1e6f67d9y.jpg" />
</view>
</view>
<!-- 楼层数据 -->
<view class="goods-list">
<view class="title">
<image src="https://ae01.alicdn.com/kf/H551edcdd154a4936a5762971504fb3e2r.jpg"></image>
猜你喜欢
<image src="https://ae01.alicdn.com/kf/H551edcdd154a4936a5762971504fb3e2r.jpg"></image>
</view>
<view class="product-list">
<block wx:for="{{productList}}" wx:key="{{item}}">
<view class="product">
<image src="{{item.img_url}}" />
<view class="name ellipsis">{{ item.name }}</view>
<view class="info">
<view class="price">{{ item.price }}</view>
<view class="slogan">{{ item.slogan }}</view>
</view>
</view>
</block>
</view>
</view>
</page>
4.2. Внедрение пользовательских компонентов поиска
1. Инструменты разработчика WeChat для создания пользовательских компонентов
создание корневого каталогаcomponents/SearchInput
документ,SearchInput
Щелкните правой кнопкой мыши и выберите «Новый компонент», чтобы сгенерировать js json wxss wxml самостоятельно.
2. Реализация кода
SearchInput.wxml
<view class="search_row">
<navigator class="search_input" target="" url="../search/index" hover-class="navigator-hover" open-type="navigate">
搜索
</navigator>
</view>
SearchInput.wxss
.search_row {
height: 90rpx;
padding: 15rpx;
background-color: #eb4450;
}
.search_row .search_input {
border-radius: 10rpx;
background-color: #fff;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
Внедрение пользовательских компонентов
первый на странице
json
Справочная выписка делается в файле. Также укажите соответствующее имя компонента и путь к компоненту.
{
"usingComponents": {
"search-input":"/components/SearchInput/SearchInput"
}
}
- Объявление ссылки usingComponents
- имя компонента поискового ввода (
SearchInput
) - Путь компонента "/components/SearchInput/SearchInput"
используется на странице
<!--pages/home/index.wxml-->
<page class="home">
<!-- 搜索 -->
<view class="shop-input">
<search-input></search-input>
</view>
</page>
navigator
Компоненты навигации, похожие на метки гиперссылок
Имя свойства | Типы | По умолчанию | иллюстрировать |
---|---|---|---|
target | String | self | На какую цель происходит переход, текущий апплет по умолчанию, необязательное значение self (текущий апплет)/miniProgram (другой апплет) |
url | String | Перейти по ссылкам в текущем апплете | |
open-type | String | navigate | Метод прыжка |
Допустимые значения для открытого типа:
стоимость | иллюстрировать |
---|---|
navigate | Сохранить текущую страницу и перейти на страницу в приложении, но не может перейти на страницу панели вкладок |
redirect | Закройте текущую страницу и перейдите на страницу в приложении, но переход на страницу панели вкладок невозможен. |
switchTab | Перейдите на страницу панели вкладок и закройте все остальные страницы без панели вкладок. |
reLaunch | Закрыть все страницы, открыть страницу в приложении |
navigateBack | Закрыть текущую страницу и вернуться на предыдущую страницу или многоуровневую страницу. доступныйgetCurrentPages Получите текущий стек страниц и решите, сколько слоев нужно вернуть |
exit | Выйдите из мини-программы, она вступит в силу, когда target="miniProgram" |
4.3. Внедрить карусель (swiper)
Используйте встроенный WeChat
swiper
Реализация компонента
swiper
- Слайдер просмотра контейнера,
- Ширина по умолчанию 100%, высота 150 пикселей;
Общие свойства
Имя свойства | Типы | По умолчанию | иллюстрировать |
---|---|---|---|
indicator-dots | Boolean | false | Отображать ли точки индикатора панели |
indicator-color | Color | rgba(0, 0, 0, .3) | Цвет точки индикации |
indicator-active-color | Color | #000000 | Цвет текущей выбранной точки индикатора |
autoplay | Boolean | false | Переключаться ли автоматически |
interval | Number | 5000 | Интервал времени автоматического переключения |
circular | Boolean | false | Вращается ли s в цикле |
swiper-item
- можно разместить только в
swiper
В компоненте ширина и высота автоматически устанавливаются на 100%.
image
Встроенный компонент изображения WeChat, ширина по умолчанию 320 пикселей, высота 240 пикселей, поддержка отложенной загрузки
Общие свойства:
Имя свойства | Типы | По умолчанию | иллюстрировать |
---|---|---|---|
src | String | Адрес ресурса изображения | |
mode | String | 'scaleToFill' | Обрезка изображения и режим масштабирования |
lazy-load | Boolean | false | Ленивая загрузка изображения |
допустимые значения для режима
Всего 13 режимов, 9 режимов обрезки, 4 режима масштабирования, часто используемые.
widthFix
стоимость | иллюстрировать |
---|---|
scaleToFill | Режим масштабирования, который масштабирует изображение без сохранения соотношения сторон, так что ширина и высота изображения полностью растягиваются, чтобы заполнить элемент изображения. |
aspectFit | Режим масштабирования, в котором сохраняется соотношение сторон и масштабируется изображение таким образом, что длинная сторона изображения отображается полностью. То есть картинка может отображаться полностью. |
aspectFill | Режим масштабирования, который поддерживает соотношение сторон и масштабирует изображение, гарантируя, что короткая сторона изображения может быть полностью отображена. То есть картинка обычно полная только в горизонтальном или вертикальном направлении, в другом направлении будет кадрирование. |
widthFix | В режиме масштабирования ширина остается неизменной, высота изменяется автоматически, а соотношение сторон исходного изображения остается неизменным |
heightFix | Режим масштабирования, высота не меняется, ширина меняется автоматически, а соотношение сторон исходного изображения остается неизменным |
top | Режим обрезки, не масштабировать изображение, показывать только верхнюю часть изображения. |
bottom | Режим обрезки, не масштабировать изображение, показывать только нижнюю часть изображения |
center | Режим обрезки, не масштабировать изображение, показывать только среднюю часть изображения. |
left | Режим обрезки, не масштабировать картинку, отображать только левую часть картинки |
right | Режим обрезки, не масштабировать изображение, отображать только правую часть изображения |
top left | Режим обрезки, не масштабировать изображение, отображать только верхнюю левую часть изображения. |
top right | Режим обрезки, не масштабировать изображение, отображать только верхнюю правую часть изображения. |
bottom left | Режим кадрирования, не масштабировать изображение, отображать только нижнюю левую часть изображения. |
bottom right | Режим обрезки, не масштабировать изображение, отображать только нижнюю правую часть изображения |
Код
<!-- 轮播图 -->
<view class="shop-swiper">
<swiper class="" indicator-dots autoplay interval="5000">
<block wx:for="{{swiperList}}" wx:key="{{item}}">
<swiper-item class="" item-id="">
<image src="{{item.url}}" mode="widthFix" />
</swiper-item>
</block>
</swiper>
</view>
4.4. Реализовать классификацию/рекламную карту/реализовать пол
Внедрение кода вручную, вставьте код напрямую, в основном об использовании запроса на получение данных на нижнем этаже.
<!--pages/home/index.wxml-->
<page class="home">
<!-- 搜索 -->
<view class="shop-input">
<search-input></search-input>
</view>
<!-- 轮播图 -->
<view class="shop-swiper">
<swiper class="" indicator-dots autoplay interval="5000">
<block wx:for="{{swiperList}}" wx:key="{{item}}">
<swiper-item item-id="">
<image class="" src="{{item.url}}" mode="widthFix" />
</swiper-item>
</block>
</swiper>
</view>
<!-- 分类数据 -->
<view class="category-list">
<block wx:for="{{categoryList}}" wx:key="{{item.name}}">
<view class="category" bindtap="hancleClickItem" data-itemList="{{item}}">
<view class="img">
<image src="{{item.image_src}}" mode="widthFix" />
</view>
<view>
<view class="text">{{item.name}}</view>
</view>
</view>
</block>
</view>
<!-- 广告图 -->
<view class="banner">
<MarqueeUp />
<view class="img-box">
<image src="https://ae01.alicdn.com/kf/H5470c644e6454719a610620f1e6f67d9y.jpg" />
</view>
</view>
<!-- 楼层数据 -->
<view class="goods-list">
<view class="title">
<image src="https://ae01.alicdn.com/kf/H551edcdd154a4936a5762971504fb3e2r.jpg"></image>
猜你喜欢
<image src="https://ae01.alicdn.com/kf/H551edcdd154a4936a5762971504fb3e2r.jpg"></image>
</view>
<view class="product-list">
<block wx:for="{{productList}}" wx:key="{{item}}">
<view class="product">
<image src="{{item.img_url}}" />
<view class="name ellipsis">{{ item.name }}</view>
<view class="info">
<view class="price">{{ item.price }}</view>
<view class="slogan">{{ item.slogan }}</view>
</view>
</view>
</block>
</view>
</view>
</page>
/* pages/home/index.wxss */
swiper {
height: 260rpx;
}
/* 分类 */
.category-list {
width: 92%;
margin: 0 4%;
padding: 0 0 30rpx 0;
border-bottom: solid 2rpx #f6f6f6;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.category-list .category {
width: 25%;
margin-top: 50rpx;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.category-list .category .img {
width: 100%;
display: flex;
justify-content: center;
}
.category-list .category .img image {
width: 9vw;
height: 9vw;
}
.category-list .category .text {
margin-top: 16rpx;
width: 100%;
display: flex;
justify-content: center;
font-size: 24rpx;
color: #3c3c3c;
}
/* 广告图 */
.banner {
width: 92%;
margin: 40rpx 4%;
}
.banner .img-box {
position: relative;
width: 100%;
height: 150rpx;
margin-top: 20rpx;
border-radius: 80rpx;
}
.banner .img-box::before {
content: "";
position: absolute;
width: calc(100% + 6%);
height: 180rpx;
border-radius: 100rpx;
top: -15rpx;
left: -3%;
z-index: -1;
background-image: linear-gradient(60deg, red, cornflowerblue, yellow, hotpink, salmon, lightgreen, sandybrown, violet);
background-size: 300%;
animation: animate_bg 5s infinite;
}
@keyframes animate_bg {
0%,
100% {
background-position: 0%, 50%;
}
50% {
background-position: 100%, 50%;
}
}
.banner image {
width: 100%;
height: 20vw;
border-radius: 10vw;
box-shadow: 0rpx 5rpx 25rpx rgba(0, 0, 0, 0.3);
}
/* 楼层 */
.goods-list{
width: 100%;
}
.goods-list .title {
width: 100%;
margin-top: 10rpx;
display: flex;
justify-content: center;
align-items: center;
height: 80rpx;
color: #f47825;
font-size: 30rpx;
}
.goods-list .title image {
width: 30rpx;
height: 30rpx;
}
.goods-list .product-list {
width: 100%;
padding: 0 4% 3vw 4%;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.product {
width: 48%;
border-radius: 20rpx;
background-color: #fff;
margin: 0 0 15rpx 0;
box-shadow: 0rpx 5rpx 25rpx rgba(0, 0, 0, 0.1);
}
.product image {
width: 100%;
height: 332rpx;
border-radius: 20rpx 20rpx 0 0;
}
.product .name {
width: 92%;
padding: 10rpx 4%;
font-size: 30rpx;
}
.product .info {
display: flex;
justify-content: space-between;
align-items: flex-end;
width: 92%;
padding: 10rpx 4% 10rpx 4%;
}
.product .info .price {
color: #e65339;
font-size: 30rpx;
font-weight: 600;
}
.product .info .slogan {
color: #807c87;
font-size: 24rpx;
}
wx.request для получения внутренних данных
Инициируйте сетевой запрос HTTPS, подробности см. в документации WeChat.
запрос + обещание инкапсуляции
class request {
constructor() {
this._baseUrl = 'https://www.fastmock.site/mock/31875da47f27128e357e3d3e6ac0cc37/api/';
this._token = wx.getStorageSync('token');
// this._header = {'Authorization': 'Bearer ' + token}
}
/**
* GET类型的网络请求
*/
getRequest(url, data, header = this._header) {
return this.requestAll(url, data, header, 'GET')
}
/**
* DELETE类型的网络请求
*/
deleteRequest(url, data, header = this._header) {
return this.requestAll(url, data, header, 'DELETE')
}
/**
* PUT类型的网络请求
*/
putRequest(url, data, header = this._header) {
return this.requestAll(url, data, header, 'PUT')
}
/**
* POST类型的网络请求
*/
postRequest(url, data, header = this._header) {
return this.requestAll(url, data, header, 'POST')
}
/**
* 网络请求
*/
requestAll(url, data, header, method) {
return new Promise((resolve, reject) => {
// 显示正在等待
wx.showLoading({
title: "正在加载中",
mask: false
});
wx.request({
url: this._baseUrl + url,
data: data,
header: header,
method: method,
success: (res => {
let {
data
} = res;
// console.log(res);
if (data.success && data.code == 200) {
//200: 服务端业务处理正常结束
resolve(data.data)
} else {
//其它错误,提示用户错误信息
reject(data.data)
}
}),
fail: (res => {
reject(res)
}),
complete: () => {
// 隐藏正在等待图标
wx.hideLoading();
}
})
})
}
}
export default request
Страница использует запрос
import request from '../../utils/request'; //引入
const api = new request(); //创建实例
инструкции
- Получить запрос ------------------ api.getRequest(
接口路径
,入参(对象)
) - Почтовый запрос ---------------- api.postRequest( 'home/getProductList',this.QueryParams )
- .....
Уведомление:Необходимо проверить во время разработки
不校验合法域名、web-view业务域名
Подождите, официальная конфигурация соответствующего доменного имени для апплета входа в производственную линию, иначе запрос не может быть инициирован.
4.5 Динамический сбор данных пола
import request from '../../utils/request';
const api = new request();
Page({
/**
* 页面的初始数据
*/
data: {
swiperList: [{
id: 1,
url: 'https://ae01.alicdn.com/kf/H9450011bbd2e480882aa986c8ceaa312i.jpg'
},
{
id: 2,
url: 'https://ae01.alicdn.com/kf/H1eeb66ae770b44ad9147c1123fb63a32P.jpg'
},
{
id: 3,
url: 'https://ae01.alicdn.com/kf/H0fdf0f299c2a49d5995582f085d24522G.jpg'
},
],
// 分类菜单
categoryList: [{
id: 1,
"name": "办公",
image_src: 'https://ae01.alicdn.com/kf/H974e4de8124b4783b7768d06a2b847ab0.jpg'
},
{
id: 2,
"name": "家电",
image_src: 'https://ae01.alicdn.com/kf/H53dede49e8bd4037b702eeb1f83f1b55M.jpg'
},
{
id: 3,
"name": "服饰",
image_src: 'https://ae01.alicdn.com/kf/H575960420d6b4990960160fba79f443bw.jpg'
},
{
id: 4,
"name": "日用",
image_src: 'https://ae01.alicdn.com/kf/H30b911d8668d46deb9cfed0fd68da1fex.jpg'
},
{
id: 5,
"name": "蔬果",
image_src: 'https://ae01.alicdn.com/kf/Hd3edad8b6c834a23aa214fa83ecca4ddm.jpg'
},
{
id: 6,
"name": "运动",
image_src: 'https://ae01.alicdn.com/kf/Hdb7bb002f13c4b79bc876c28555ca7ceV.jpg'
},
{
id: 7,
"name": "书籍",
image_src: 'https://ae01.alicdn.com/kf/Hc1a477b73bc147728ef29ab6c74af0f0O.jpg'
},
{
id: 8,
"name": "文具",
image_src: 'https://ae01.alicdn.com/kf/H23940f3a1f3145418b439c32521e263b4.jpg'
}
],
//猜你喜欢列表
productList: [],
},
// 定义接口参数对象
QueryParams: {
// 页码
pagenum: 1,
// 页容量
pagesize: 10
},
// 总页码
totalPage: 1,
// 获取商品列表
getProductList() {
// 使用微信小程序内置发送请求的代码来获取数据
api.postRequest(
'home/getProductList',
this.QueryParams
).then(res => {
console.log(res);
// 执行加载下一页的时候 productList 应该是 叠加
// 拼接数组
let productList = [...this.data.productList, ...res.productList];
this.setData({
productList
});
// 计算总页码
this.totalPage = Math.ceil(res.total / this.QueryParams.pagesize);
})
},
// 点击分类事件
hancleClickItem(e) {
let data = e.currentTarget.dataset.itemlist;
wx.showToast({
title: '点击了' + data.name,
icon: 'none'
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
this.getProductList()
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
// wx.showNavigationBarLoading() //在标题栏中显示加载
this.QueryParams.pagenum = 1;
this.setData({
productList: []
});
this.getProductList();
// 结束下拉刷新组件的显示
wx.stopPullDownRefresh();
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
// 判断有没有下一页数据
if (this.QueryParams.pagenum >= this.totalPage) {
// 没有数据
wx.showToast({
title: '没有更多数据了',
icon: 'none',
duration: 1500,
// 蒙版 遮罩层
mask: false
});
} else {
this.QueryParams.pagenum++;
this.getProductList();
}
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
4.6 Реализуйте выпадающее обновление и загрузите больше
Включите раскрывающееся обновление на главной странице
(1) В Index.json вытяните новое обновление, вам нужно установить backgroundColor или BackgroundTextStyle, потому что загруженная анимация может быть белым фоном, это будет ясно.
{
"enablePullDownRefresh": true,
"onReachBottomDistance": 50,
"usingComponents": {
"search-input":"/components/SearchInput/SearchInput"
}
}
(2), вonPullDownRefresh
Функция прослушивает событие раскрывающегося списка и выполняет метод обновления.
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
// wx.showNavigationBarLoading() //在标题栏中显示加载
this.QueryParams.pagenum = 1;
this.setData({
productList: []
});
this.getProductList();
// 结束下拉刷新组件的显示
wx.stopPullDownRefresh();
},
Включите подтягивание, чтобы загрузить больше
прямой мониторингonReachBottom
событие, чтобы загрузить больше
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
// 判断有没有下一页数据
if (this.QueryParams.pagenum >= this.totalPage) {
// 没有数据
wx.showToast({
title: '没有更多数据了',
icon: 'none',
duration: 1500,
// 蒙版 遮罩层
mask: false
});
} else {
this.QueryParams.pagenum++;
this.getProductList();
}
},
На сегодня это все, а следующая статья будет по-прежнему включать классификацию продуктов и подробные сведения о них. Спасибо за ваше прочтение и поддержку. Пожалуйста, оставьте сообщение ниже, чтобы учиться и совершенствоваться вместе!
💕 После прочтения трех вещей:
- Нравится | Вы можете нажать --> Избранное --> Выйти за один раз, но не забудьте поставить лайк 🤭
- Подписывайтесь | Нажмите, чтобы подписаться, не теряйтесь в следующий раз😘