讲讲微信小程序开发中的一些技巧,包括CSS和JS的,也算是自己的一个备忘录吧。希望对你有用
CSS 背景图片百分比及应用
适用于rpx雪碧图标中背景图片精准定位 百分比计算公式 任何CSS属性值为百分比时,都需要根据某个参考值进行计算,搞明白这个参考值是什么,理解就容易多了。 标准规定:background-position:percent的参考值x为:百分比为background-position-x的值 = (背景在雪碧中的左边宽度)/(容器宽度 - 背景图片宽度)*100%。 举个例子: 百度分享中有四个图标(大小设置是0.72rem0.72rem),我把这四个小图标扣到一张大小为(0.72rem3.65rem)的背景图,宽度跟图标是一样的,高度则为四个图片 1倍的高度,主要是为了后面的高度百分比成正比。 那么我们可以得到这张小图片的样式为:
.icon{ width:.72rem; height:.72rem; backgorund:url(img/sprite.png) no-repeat center top; background-size:100%; //cover background-position:0 0}.icon1{ backgorund-position:0 0;}.icon2{ background-position:0 -73/(73 - 365)*100%=25%}.icon3{ background-position:0 -146/(73-365)*100%=50%}.icon4{ background-position:0 -219/(73-365)*100%=75%}
最关键是要理解上面这个计算方式。其实我们如果换另一大家都熟悉的常见定位就清楚了。
.icon2{ background-position:0 -0.73rem; (这个距离就是图标距离背景图片中的偏离值) }
无限加载的两种处理
- 利用scroll-view组件自带的滑到底部触发函数
- 利用page函数上拉触底onReachBottom第一种
第一种
<scroll-view bindscrolltolower="scrollBottom"></scroll-view>
Page({ scrollBottom:function(){ console.log('滚动到底部了'); }})
第二种
Page({ onReachBottom:function(){ console.log('滚动到底部了'); }})
swiper多栏切换无限加载
- 使用swiper scroll-view结合
- 使用touch事件
第一种
<swiper><block for="{{list}}"><swiper-item><scroll-view class="list" scroll-y="true" bindscrolltolower="loadMoreList"><block for="{{list[item]}}"><view class="item"></view></block></scroll-view></swiper-item></block></swiper>
CSS 代码
.tab { /* position: fixed; left: 0; top: 0; */ border-bottom: 1px solid #f8f8f8; background: #fff; z-index: 1; width: 100%; height: 100rpx; line-height: 100rpx;}.tab-inner { height: 100rpx; overflow: hidden;}.scroll-bangdan { width: 100%; position: relative; height: 130rpx;}.tab .ctrl { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; flex-flow: row wrap; -webkit-flex: row wrap; font-size: 28rpx; height: 100rpx; line-height: 100rpx;}
第二种
隐藏滚动条
内外层固定宽高,scroll-view添加padding或者把高度设为比外层的高度高。
<view class="tab"> <view class="tab-inner"> <scroll-view class="scroll-bangdan" scroll-x="true" scroll-left="{{scrollLeft}}"> <view class="ctrl" style="width:1054rpx"> <block wx:for="{{nav}}" wx:key="{{item.columnId}}"> <view class="toc{{current==index?' cur':''}}" bindtap="changeTab" data-index="{{index}}"> <view class="text"> <text>{{item.columnName}}</text> </view> </view> </block> </view> </scroll-view> <view class="mask"></view> </view></view>
第二种直接加下面的代码:
/* 去掉默认滚动条 */::-webkit-scrollbar { width: 0; height: 0; color: transparent;}
订阅发布模式
支持先订阅后发布,以及先发布后订阅
var Event = (function() { var clientList = {}, pub, sub, remove; var cached = {}; sub = function(key, fn) { if (!clientList[key]) { clientList[key] = []; } // 使用缓存执行的订阅不用多次调用执行 cached[key "time"] == undefined ? clientList[key].push(fn) : ""; if (cached[key] instanceof Array && cached[key].length > 0) { //说明有缓存的 可以执行 fn.apply(null, cached[key]); cached[key "time"] = 1; } }; pub = function() { var key = Array.prototype.shift.call(arguments), fns = clientList[key]; if (!fns || fns.length === 0) { //初始默认缓存 cached[key] = Array.prototype.slice.call(arguments, 0); return false; } for (var i = 0, fn; (fn = fns[i ]); ) { // 再次发布更新缓存中的 data 参数 cached[key "time"] != undefined ? (cached[key] = Array.prototype.slice.call(arguments, 0)) : ""; fn.apply(this, arguments); } }; remove = function(key, fn) { var fns = clientList[key]; // 缓存订阅一并删除 var cachedFn = cached[key]; if (!fns && !cachedFn) { return false; } if (!fn) { fns && (fns.length = 0); cachedFn && (cachedFn.length = 0); } else { if (cachedFn) { for (var m = cachedFn.length - 1; m >= 0; m--) { var _fn_temp = cachedFn[m]; if (_fn_temp === fn) { cachedFn.splice(m, 1); } } } for (var n = fns.length - 1; n >= 0; n--) { var _fn = fns[n]; if (_fn === fn) { fns.splice(n, 1); } } } }; return { pub: pub, sub: sub, remove: remove };})();
// app.jsApp({ onLaunch: function(e) { // 注册 storage,这是第二条 wx.Storage = Storage; // 注册发布订阅模式 wx.yue = Event; }});
实际应用
// 添加收货地址页面订阅 onLoad: function (options) { wx.yue.sub("addAddress", function (data) { y.setData({ addAddress: data }) }) }/** * 生命周期函数--监听页面隐藏 */ onHide: function () { // 取消多余的事件订阅 wx.Storage.removeItem("addAddress");}, onUnload: function () { // 取消多余的事件订阅 wx.yue.remove("addAddress");}
// 传递地址页面获取好数据传递wx.yue.pub("addAddress", data.info);// 补充跳转返回
注意:使用完成数据后要注意卸载,在页面被关闭时操作
Storage
const Storage = { setItem: function(key, obj, callback) { wx.setStorage({ key: key, data: obj, success: callback || function() {} }); }, getItem: function(key) { return wx.getStorageSync(key); }, removeItem: function(key) { wx.removeStorage({ key: key }); }};
async await
使用runtime.js,使小程序支持 async await,拷贝文件至项目目录下。
const regeneratorRuntime = require("../../utils/runtime.js");Page({ shopCartInit() { var y = this; // 拿到商铺位置信息再去渲染购物计算当前的address符合不符合规定 var showCartList = function() { // 显示全局的地址信息 var globalAddress = wx.Storage.getItem("globalAddress"); if (globalAddress) { y.setData({ globalAddress: globalAddress, addr_id: globalAddress.id }); y.calculateDistance( qqmapsdk, globalAddress.latitude, globalAddress.longitude ); } else { y.setData({ globalAddress: {} }); } }; // await 等待获取商铺位置信息 async function getShopPosTionMsg() { await util.promiseRequest(api.merchant_addr, {}).then(res => { var data = res.data.response_data.lists[0]; y.setData({ shop_lat: data.latitude, // 商铺纬度 shop_lng: data.longitude, // 商铺经度 peiSongFanWei: data.scope // 配送范围 }); }); } async function initData() { await getShopPosTionMsg(); await showCartList(); util.closeLoading(); y.setData({ loading: false }); } // 开始执行 initData(); }});
promise引入
github上的一个库,wx.promise
// 演示 wxPromise 的能力wx.showLoading({ title: '加载中', mask: true})wx.pro.request({ url: 'https://cnodejs.org/api/v1/topics', data: {}, method: 'GET', header: {'content-type': 'application/json'}}).then(res => { console.log(res)}).catch(err => { console.log(err)}).finally(() => { wx.hideLoading()})