事先声明,这是一个高仿小米Lite的微信小程序。html
我呢如今是一个大三快大四的学生,这个小程序花了我很长时间,把能写的功能基本上都写了。我秉着分享开源的心理,尽可能把我写的这个小程序怎么写的,为何这样写,详细的告诉你们。为何是尽可能?这是由于,我不太会说,可能说的不是很清楚,因此只能尽可能.前端
├<assets>
│ ├<images>
├<components>
│ ├<goodList>
│ ├<icon>
│ ├<tabbar>
│ ├<userList>
├<pages>
│ ├<cart>
│ ├<category>
│ ├<deleteGoods>
│ ├<find>
│ ├<goodDetails>
│ ├<index>
│ ├<selectGoods>
│ ├<user>
├<utils>
│ └util.js
├<weui>
│ └weui.wxss
├<wxapi>
│ ├Api.js
│ ├main.js
│ └mock.js
复制代码
对于初学者来讲,可能拿到设计图就立马写,其实这样很很差,写出来的代码会有不少重复的代码,这样不利于以后的维护。因此应该把一些公用的代码封装,以后直接调用就好了,以后维护起来也更加的方便。git
咱们前端想要获取页面的数据,就须要发送HTTP请求后端提供给咱们的API接口,从API接口中获取咱们想要的数据。在微信小程序中,微信官方给咱们提供了一个方法wx.request来请求.github
一个程序,须要的HTTP请求会不少,若是咱们每一个请求都去写一个wx.request,这样写出来的代码,看起来会很冗长,他人看咱们的代码时也会很累,也不利于咱们以后的修改。所以为了代码的整洁,和以后的修改方便。我就把全部的API请求请求封装在wxapi文件目录下。web
// Api.js
const banners = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/banners'
const navdata = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/navdata'
const goodList = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/goodList'
const category = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/category'
const findData = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/findData'
const userData = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/userData'
const goodDetail = 'https://www.easy-mock.com/mock/5cf9c392006feb28c7eedf28/goodDetail'
const QQ_MAP_KEY = 'NNFBZ-6DRCP-IRLDU-VEQ4F-TXLP2-PFBEN'
const MAPURL = 'https://apis.map.qq.com/ws/geocoder/v1/'
module.exports = {
banners,
navdata,
goodList,
category,
findData,
userData,
goodDetail,
QQ_MAP_KEY,
MAPURL
}
复制代码
import * as MOCK from "./mock"
import * as API from "./Api"
const request = (url,mock = true,data) => {
let _url = url
return new Promise((resolve, reject) => {
if (mock) {
let res = {
statusCode: 200,
data: MOCK[_url]
}
if (res && res.statusCode === 200 && res.data) {
resolve(res.data)
} else {
reject(res)
}
} else {
wx.request({
url: url,
data,
success(request) {
resolve(request.data)
},
fail(error) {
reject(error)
}
})
}
});
}
// showLoading
const showLoading = () => {
wx.showLoading({
title: '数据加载中',
mask: true,
});
}
// 获取地理位置
const geocoder = (lat, lon) => {
return request(API.MAPURL,false,{
location: `${lat},${lon}`,
key: API.QQ_MAP_KEY,
get_poi: 0
})
}
module.exports = {
getBanners: () => {
// return request('banners')
return request(API.banners,false) //首页 banners
},
getNavData: () => {
// return request('navdata')
return request(API.navdata,false) //首页 navdata
},
getGoodList: () => {
// return request('goodList')
return request(API.goodList,false) //首页 商品列表
},
getCategroy: () => {
// return request('category')
return request(API.category,false) //分类页面
},
getFindData: () => {
// return request('findData')
return request(API.findData,false) //发现 页面
},
getUserData: () => {
// return request('userData')
return request(API.userData,false) // 个人 页面
},
getGoodDetail: () => {
// return request('goodDetail')
return request(API.goodDetail,false) //商品详情
},
showLoading,
geocoder
}
复制代码
看到这里,可能就会有一些疑问,为何我在每一个请求后面都加上了一个false?面试
这是由于,我在写这个微信小程序开始时,没有使用easy-mock来模拟http请求数据。我是把假数据都放在mock.js文件中。而后使用 **return request('banners')**这种方式就能够获取我想要的数据。数据库
API封装完了,该怎么调用呢?我就以首页的banners数据为例json
// index.js
const WXAPI = require('../../wxapi/main')
onLoad: function (options) {
WXAPI.showLoading()
this.getBanners()
},
getBanners() {
WXAPI
.getBanners()
.then(res => {
wx.hideLoading()
this.setData({
banners: res.data
})
})
},
复制代码
记住,若是想要发送HTTP请求数据的页面,都必须加上这一句const WXAPI = require('../../wxapi/main')小程序
开始准备OK,如今开始写页面。第一步要写的是tabBar部分。后端
看起来是否是有点奇怪,为何有点透明的感受?由于这个tabBar组件是我本身写的。
通常来将,直接在把tabBar组件写在app.json中,就能够了。
可是我以为不是那么好看,因此就本身撸了一个tabBar组件出来。
写完以后查文档才发现,微信小程序官方提供了自定义tabBar组件的方法,有须要的能够查看微信小程序文档
写完这个组件后我总解了一下,须要注意的问题.
选中了的当前页面,再次点击因该无效。
因此我在app.js中存入了一个page属性,来存储当前页面,而后在点击事件goToPage()方法中加入判断去解决。
<!--components/tabbar/tabbar.wxml-->
<view class="tabbar">
<!-- 首页 -->
<view class="shouye {{on === 'index' ? 'on': ''}}" data-page="index" bindtap="goToPage">
<icon type="shouye" size="42" class="icon" color="{{on === 'index' ? '#f96702': ''}}"/>
<text >首页</text>
</view>
<!-- 分类 -->
<view class="fenlei {{on === 'category' ? 'on': ''}}" data-page="category" bindtap="goToPage">
<icon type="classify" size="42" class="icon" color="{{on === 'category' ? '#f96702': ''}}"/>
<text >分类</text>
</view>
<!-- 发现 -->
<view class="faxian {{on === 'find' ? 'on': ''}}" data-page="find" bindtap="goToPage">
<icon type="faxian" size="42" class="icon" color="{{on === 'find' ? '#f96702': ''}}"/>
<text >发现</text>
</view>
<!-- 购物车 -->
<view class="gouwuche {{on === 'cart' ? 'on': ''}}" data-page="cart" bindtap="goToPage">
<icon type="gouwuche" size="42" class="icon" color="{{on === 'cart' ? '#f96702': ''}}"/>
<text >购物车</text>
</view>
<!-- 个人 -->
<view class="wode {{on === 'user' ? 'on': ''}}" data-page="user" bindtap="goToPage">
<icon type="wode" size="42" class="icon" color="{{on === 'user' ? '#f96702': ''}}"/>
<text >个人</text>
</view>
</view>
复制代码
// components/tabbar/tabbar.js
// 全局里面存了一个page 表示当前 路由
const app = getApp();
Component({
/**
* 组件的属性列表
*/
properties: {
// 是否选中
on:{
type: String,
value: ''
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
// 跳转到相应的页面
// 加了一个判断
// 由于若是如今显示的是当前页面就不须要再跳转
goToPage(e) {
let page = e.currentTarget.dataset.page || 'user';
if(app.globalData.page === page) {
return ;
}
wx.redirectTo({
url: `/pages/${page}/${page}`,
});
app.globalData.page = page;
}
}
})
复制代码
/* components/tabbar/tabbar.wxss */
.tabbar {
width: 100%;
height: 100rpx;
background-color: #ffffff;
display: flex;
position: fixed;
bottom: 0;
font-size: 26rpx;
z-index: 99;
}
.shouye,.fenlei,.faxian,.gouwuche,.wode {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
opacity: 0.5;
}
.icon {
height: 60rpx;
}
.on {
color:#f96702;
}
复制代码
关于如何使用的问题,只须要在,须要tabBar功能的页面底部加上就能够.
好比index页面
<tabbar on="index"></tabbar>
复制代码
记得在json中引入组件
{
"usingComponents": {
"goodList": "../../components/goodList/goodList",
"tabbar": "../../components/tabbar/tabbar"
}
}
复制代码
tabBar组件中须要图标,我使用的是阿里的图标库
如何使用?
这个组件很简单,定义出来就能够直接使用,而且修改颜色和大小.
<!--components/icon/icon.wxml-->
<text class='iconfont icon-{{type}}' style='color:{{color}}; font-size:{{size}}rpx;'></text>
复制代码
properties: {
type: {
type: String,
value: ''
},
color: {
type: String,
value: '#000000'
},
size: {
type: Number,
value: '45'
}
},
复制代码
在首页中存在不少这样的商品列表,一个一个写,这样写出来的代码会致使首页的代码显得不少,而且很差维护,因此我就封装成了一个组件.
<!--components/goodList/goodList.wxml-->
<view class="goodList-good">
<!-- 商品的图片 -->
<view class="goodList-good-img">
<image src="{{url}}" mode="aspectFill" />
</view>
<!-- 商品详细的信息 -->
<view class="goodList-good_detail">
<!-- 名称 -->
<view class="good_detail_name">
{{name}}
</view>
<!-- 信息 -->
<view class="good_detail_brief">
{{brief}}
</view>
<!-- 价格 -->
<view class="good_detail_price">
<text class="price" >¥{{price}}</text>
<text class="oldPrice" style="display:{{oldPrice == '' ? 'none': 'inline'}};">¥{{oldPrice}}</text>
</view>
</view>
</view>
复制代码
properties: {
// 图片连接
url: {
type: String,
value: ''
},
// 名称
name: {
type: String,
value: ''
},
// 信息
brief: {
type: String,
value: ''
},
// 新的价格
price: {
type: String,
value: ''
},
// 旧的价格
oldPrice: {
type: String,
value: ''
}
},
复制代码
/* components/goodList/goodList.wxss */
.goodList-good {
position: relative;
width: 100%;
height: 100%;
}
.goodList-good-img {
width: 100%;
height: 312rpx;
position: relative;
}
.goodList-good-img image {
width: 100%;
height: 100%;
}
.goodList-good_detail {
padding: 26rpx 23rpx;
}
.good_detail_name {
width:100%;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
.good_detail_brief {
width:100%;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
font-size: 25rpx;
color: #8c8c8c;
}
.good_detail_price {
display: flex;
justify-content: flex-start;
align-items: flex-end;
}
.good_detail_price .price {
color: #a36d4a;
font-size: 28rpx;
padding-right: 16rpx;
}
.good_detail_price .oldPrice {
font-size: 24rpx;
color: #8c8c8c;
text-decoration: line-through;
}
复制代码
大家会发现,个人边框为何那么细。
初学者,可能会说,0.5px边框,不就是border: 0.5px吗,其实这是错的。
浏览器会把任何小于1px的边框都解析成1px,因此你写0.5px其实浏览器会解析成1px,这样就实现不了效果。
其实也很简单,使用伪类去画。
例如,goodList组件的右部边框.
在index页面的html中,我在包裹goodList的view标签的class中加上了rightBorder这个类来表示画出上边框。
<view class="item topBorder rightBorder" data-id="{{item.id}}" bindtap="goDetails">
<goodList url="{{item.url}}"
name="{{item.name}}"
brief="{{item.brief}}"
price="{{item.price}}"
oldPrice="{{item.oldPrice}}" ></goodList>
</view>
复制代码
.rightBorder::after {
content: '';
position: absolute;
height: 200%;
width: 1rpx;
right: -1rpx;
top: 0;
transform-origin: 0 0;
border-right: 1rpx solid#e0e0e0;
transform: scale(.5);
z-index: 1;
}
复制代码
其实画0.5px边框就记住。
其它还有一些 细节问题就按照所需写就行。
只是个人页面中的一个列表信息,这个很简单
<!--components/userList/userList.wxml-->
<view class="main">
<image src="{{List.img}}" />
<view class="text" >
<text >{{List.text}}</text>
</view>
<view class="state" wx:if="{{List.state !== ''}}">
<text >({{List.state}})</text>
</view>
</view>
复制代码
/* components/userList/userList.wxss */
.main {
width: 100%;
height: 120rpx;
display: flex;
align-items: center;
background-color: #fff;
padding: 40rpx;
box-sizing: border-box;
}
.main image {
width: 80rpx;
height: 80rpx;
}
.main .text {
font-size: 32rpx;
padding: 0 10rpx 0 5rpx;
}
.main .state {
font-size: 26rpx;
color: #8c8c8c;
}
复制代码
properties: {
List: {
type: Object
}
},
复制代码
我这里引入的是weui组件的搜索样式。如何用?
这是微信小程序提供的一个组件swiper,微信小程序开发者文档
swiper和swiper-item组合起来就能够实现,一些配置信息,请查看官方文档
具体代码
<swiper indicator-dots="{{indicatorDots}}" indicator-active-color="#ffffff" autoplay="{{autoPlay}}" interval="{{interval}}" duration="{{duration}}">
<block wx:for="{{banners}}" wx:key="index">
<swiper-item>
<image src="{{item.imgurl}}" mode="aspectFill" class="banner-image" />
</swiper-item>
</block>
</swiper>
复制代码
data: {
banners: [],
indicatorDots: true,
autoPlay: true,
interval: 3000,
duration: 1000,
navdata: [],
goodList: [],
goodListOne: {},
name:'',
},
复制代码
在商城小程序中常常要作一个这样的功能.例如:
功能要求:
功能要求并不难,可是对于初学者而言,可能会有些问题。我就直接说功能该怎么作
首先:分析一下,页面结构是左右布局。而且两边均可以滑动.因此可使用微信给咱们提供的
scroll-view组件.两个组件就能够采用float,分布在左右两边.
<!-- miniprogram/pages/category/category.wxml -->
<view class="container">
<!-- 左边商品的标签信息 -->
<scroll-view scroll-y scroll-with-animation="{{true}}" class="categroy-left">
<view wx:for="{{categroy}}" wx:key="{{index}}" data-index="{{index}}" bindtap="switchTab" class="cate-list {{curIndex === index ? 'on': ''}}">
{{item[0].name}}
</view>
</scroll-view>
<!-- 右边 标签对应的商品信息 -->
<scroll-view scroll-y scroll-into-view="{{toView}}" scroll-with-animation="true" bindscroll="scrollContent" bindscrolltolower="scrollEnd" class="categroy-right">
<block wx:for="{{categroy}}" wx:key="inedx">
<view id="right-list" class="right-list" id="{{index}}">
<view class="right-title">
<text>{{item[0].name}}</text>
</view>
<view class="right-content">
<block wx:for="{{item}}" wx:key="idex" wx:for-item="product" wx:for-index="idex">
<view class="list-detail" wx:if="{{idex > 0}}">
<image src="{{product.picture}}" />
<view class="detail-name">
<text>{{product.desc}}</text>
</view>
</view>
</block>
</view>
</view>
</block>
</scroll-view>
</view>
<tabbar on="category"></tabbar>
复制代码
/* miniprogram/pages/category/category.wxss */
/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar
{
width: 0px;
height: 0px;
background-color: pink;
}
.categroy-left {
height: 100%;
width: 150rpx;
float: left;
border-right: 1px solid #ebebeb;
box-sizing: border-box;
position: fixed;
font-size: 30rpx;
padding-bottom: 100rpx;
box-sizing: border-box;
}
.categroy-left .cate-list {
height: 90rpx;
line-height: 90rpx;
text-align: center;
border: 2px solid #fff;
}
.categroy-left .cate-list.on {
color: #ff4800;
font-size: 34rpx;
}
/* 右边的列表 */
.categroy-right {
width: 600rpx;
float: right;
height: 1334rpx;
/* height: 100%; */
padding-bottom: 100rpx;
box-sizing: border-box;
overflow: hidden;
}
.right-title {
width: 100%;
text-align: center;
position: relative;
padding-top: 30rpx;
/* font-size: 30rpx; */
padding-bottom: 30rpx;
}
.right-title text::before, .right-title text::after {
content: '';
position: absolute;
width: 60rpx;
/* height: 1px; */
top: 50%;
border-top: 1px solid #e0e0e0;
/* transform: scale(.5); */
}
.right-title text::before {
left: 30%;
}
.right-title text::after {
right: 30%;
}
.right-list {
/* height: 100%; */
background-color: #fff;
}
.right-content {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
}
.right-content .list-detail {
flex-shrink: 0;
width: 33.3%;
height: 100%;
font-size: 26rpx;
text-align: center;
}
.right-content .list-detail image {
width: 120rpx;
height: 120rpx;
padding: 10rpx;
/* background-color: pink; */
}
复制代码
这个功能的难点就在于js逻辑
先贴出data中须要的数据
data: {
categroy:[], //商品信息
curIndex: 'A', //当前的选中的标签
toView: 'A', //去到的标签
// 存入每一个list的高度叠加
heightArr: [],
// 最后一个list,就是最后一个标签的id
endActive: 'A'
},
复制代码
这一功能很简单就能实现
只须要在右边scroll-view组件中添加事件scroll-into-view="{{toView}}",toView就是商品显示的id
注意,右边每一个商品信息,页面渲染时必须加上id属性
而后左边的scroll-view组件只需添加一个点击事件去修改toView的值就好了
// 点击左边标签要修改的信息
switchTab(e) {
this.setData({
curIndex: e.target.dataset.index,
toView: e.target.dataset.index
})
},
复制代码
首先须要计算出 右边商品每一块占据的高度,而且存入数组中,能够放入onReady生命周期中
// 计算出右边每一个商品占据的高度
getPageMessage() {
// console.log(4)
let self = this
let heightArr = []
let h = 0
const query = wx.createSelectorQuery()
query.selectAll('.right-list').boundingClientRect()
query.exec( res => {
res[0].forEach( item => {
h += item.height
heightArr.push(h)
})
self.setData({
heightArr: heightArr
})
})
},
复制代码
在右边的scroll-view组件中加上事件。bindscroll="scrollContent,这是scroll-view提供的事件,在滑动时就会触发.
// 页面滑动时触发
scrollContent(e) {
const scrollTop = e.detail.scrollTop
const scrollArr = this.data.heightArr
const length = scrollArr.length - 1
let endChar = String.fromCharCode(65 + length)
let curChar = this.getCurrentIndex(scrollTop)
if(this.data.endActive != endChar) {
this.setData({
curIndex: curChar
})
} else {
this.setData({
endActive: 'A'
})
}
},
复制代码
// 判断curIndex应该是那个
getCurrentIndex(scrollTop) {
const scrollArr = this.data.heightArr
let find = scrollArr.findIndex(item => {
// 提早10rpx触发效果
return scrollTop < item - 10
})
let curChar = String.fromCharCode(65 + find)
return curChar
},
复制代码
以上就能够实现全部的功能要求了。
可是这样的滑动并非很完美,右边滑动到最下面,左边高亮却不是最后一个
相对完美效果就是这样
想要完美一点就要在,右边scroll-view添加一个事件:bindscrolltolower="scrollEnd"
// 页面滑动到底部触发
scrollEnd() {
const scrollArr = this.data.heightArr
const length = scrollArr.length - 1
let endChar = String.fromCharCode(65 + length)
this.setData({
curIndex: endChar,
endActive: endChar
})
},
复制代码
想要实现这样的效果并不困难。
逻辑顺序: 首页点击商品信息 -> 商品详情页面显示对应的商品详情信息 -> 购物车页面显示商品购买的商品信息. -> 修改以后,商品详情页面显示修改的信息。
想要实现这样的功能,必须有一个 id 在页面跳转时,传入给跳转的页面,跳转的页面再经过id值获取页面所需的数据
例如:首页 -> 商品详情页
这是一条商品的列表的信息,经过点击事件bindtap="goDetails",跳到对应的页面.
<view class="list">
<block wx:for="{{goodList}}" wx:key="{{item.id}}">
<view class="item topBorder rightBorder" data-id="{{item.id}}" bindtap="goDetails">
<goodList url="{{item.url}}"
name="{{item.name}}"
brief="{{item.brief}}"
price="{{item.price}}"
oldPrice="{{item.oldPrice}}" ></goodList>
</view>
</block>
</view>
复制代码
goDetails(e) {
const id = e.currentTarget.dataset.id
wx.navigateTo({
url: `/pages/goodDetails/goodDetails?id=${id}`,
});
},
复制代码
商品详情页:
传入的id值能够再onLoad生命周期的options参数上获取
onLoad: function (options) {
WXAPI.showLoading()
// 获取用户的地址信息
const address = wx.getStorageSync('Address');
this.setData({
id: options.id,
address
})
this.getGoodDetail()
},
复制代码
我是把数据直接存在本地缓存中(也能够直接存入到云数据库中),使用的是 wx.setStorage()
在本地存入了两个数据,一个是全部购买的商品信息,一个是总的商品购买数量
// 添加到购物车
toAddCart() {
let cartData = wx.getStorageSync('goods') || [];
let data = {
id: this.data.id,
name: this.data.goodData.name,
memory: this.data.memory,
color: this.data.color,
price: this.data.price,
num: this.data.selectNum,
img: this.data.imgSrc,
select: true
}
// wx.removeStorageSync('goods');
cartData.push(data)
const allNum =this.getAllNum(cartData)
wx.setStorage({
key: 'goods',
data: cartData,
success: (res) => {
console.log(res)
let pageIndex = getCurrentPages()
let backIndex = pageIndex.length - 2
wx.navigateBack({
delta: backIndex
})
},
fail: () => {},
complete: () => {}
});
// 存储数量到storage
wx.setStorageSync('allNum', allNum);
// 写到外面就可让showToast 显示在前一个页面
setTimeout(()=>{
wx.showToast({
title: '已加入购物车',
icon: 'success',
duration: 2000
});
},500)
},
// 获取全部的数量
getAllNum(cartData) {
return cartData.reduce((sum, item) => {
return sum + (+item.num)
},0)
},
复制代码
实现这个功能只须要加一个状态,点击时就修改状态的值,而且修改相关渲染的数据就行。
data: {
state: 'details_img', //判断概述 参数
}
复制代码
<view class="summarize-parameter">
<view class="title">
<view class="summarize" bindtap="changeState">
<text class="{{state === 'details_img'? 'on' : ''}}">概述</text>
</view>
<view class="parameter" bindtap="changeState">
<text class="{{state === 'param_img'? 'on' : ''}}">参数</text>
</view>
</view>
<view class="state">
<block wx:for="{{state === 'details_img'? details_img : param_img}}" wx:key="index">
<image src="{{item}}" mode="widthFix"/>
</block>
</view>
</view>
复制代码
// 改变概述和参数
changeState() {
let state = this.data.state
if(state === 'details_img') {
state = 'param_img'
} else {
state = 'details_img'
}
this.setData({
state
})
},
复制代码
对比一下上面两张图的区别.
在购物页面中选的商品数量和具体的商品信息,以后跳转回商品详情页面中,对应的数据会修改
<view class="sales" bindtap="goSelectGoods">
<text class="describe">已选</text>
<view class="detail detail-change">
{{default_change.name}}
{{default_change.memory}}
{{default_change.color}}
<text >× {{default_change.num}}</text>
</view>
<view class="right"></view>
</view>
复制代码
<view class="shopping-img" bindtap="goCart">
<icon type="gouwuche" color="#e0e0e0" size="40"/>
<text wx:if="{{allNum != 0}}">{{allNum}}</text>
</view>
复制代码
上面时两块修改的html结构
在购物页面点击确认以后,我默认就把商品添加到购物车中,而且位于数据的最后一条
返回商品详情页面时,会从新触发onShow生命周期的函数。
因此我只须要,在onShow中触发修改方法就行.
// 改变默认的版本数据 default_change
changeDefauleChange() {
const goods = wx.getStorageSync('goods') || [];
if(goods.length === 0) {
return
}
const id = this.data.id
const default_change = goods[goods.length - 1]
let memory = default_change.memory.toString()
memory = memory.substring(0,memory.length - 4)
default_change.memory = memory
this.setData({
default_change
})
},
复制代码
这一个三角形是使用CSS画出来的,并非图标。
使用CSS画出一个三角形,也不是那么困难。使用的是伪类和border属性
.right:before,
.right:after {
content: '';
position: absolute;
top: 35%;
right: 0;
border-width: 8px;
/* transform: translateY(10000rpx); */
border-color: transparent transparent transparent transparent;
border-style: solid;
transform: rotate(90deg);
}
.right:before {
border-bottom: 8px #aaaaaa solid;
}
.right:after {
right: 1px;
/*覆盖并错开1px*/
border-bottom: 8px #fff solid;
}
复制代码
能够直接使用微信小程序提供的picker组件,具体配置请查看文档
先搜索腾讯地图,而且注册开发者信息,申请一个密钥key.
// 获取地理位置
const geocoder = (lat, lon) => {
return request(API.MAPURL,false,{
location: `${lat},${lon}`,
key: API.QQ_MAP_KEY,
get_poi: 0
})
}
复制代码
而后把密钥复制,由于我封装了全部的API接口。因此使用了 API.QQ_MAP_KEY代替,这里就填写申请的密钥就行.
想要获取用户的经纬度信息,可使用wx.getLocation(),就能够获取用户的经纬度信息了.
getLocation() {
wx.getLocation({
type: 'gcj02',
success: this.getAddress,
fail: () => {
this.openLocation()
}
})
},
getAddress(res) {
let { latitude: lat, longitude: lon} = res
WXAPI.geocoder(lat, lon)
.then(res => {
if(res.status !== 0 || !res.result) {
return
}
let {address_component
} = res.result
const Address = {
city: address_component.city,
district: address_component.district
}
wx.setStorageSync("Address", Address);
})
},
复制代码
由于我未让用户受权,因此直接把获取的地理位置,保存在本地storage中.
获取的地理位置,就能够在商品详情页面的送至显示出来
作这个项目的过程来讲是快乐的,没有使用云函数(页面数据并很少,我以为不须要就能够写出来了),因此总共加起来写的时间也很短,不到一个星期就写完了。写完以后的那一刻的成就感也很好。若是你以为这篇文章有帮到你的地方,不妨给个赞吧!同时也很是但愿在下方看到给出的建议!最后奉上源码.若是有须要就自取吧!
最后,说点题外话,由于我是2020届的毕业生,如今面临实习压力。由于须要话时间去看面试题,因此后面写的一段文章,我只是简要的把重要的功能逻辑写了出来,若是写的不清楚,请见谅。