媒介
原生
开辟小顺序有了两个项目,在原生开辟小顺序履历技能方面有一些本身的总结,此篇文章做原创分享!
1.宣布定阅处置惩罚庞杂逻辑
支撑先定阅后宣布,以及先宣布后定阅
- 要领源码
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.js
App({
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);
// 补充跳转返回
注重:运用完成数据后要注重卸载,在页面被封闭时操纵
2.Storage
storage 治理封装,用法和上面的一致,挂载在全局对象上挪用,运用引见就不列了
const Storage = {
// 第一个 key 参数能够省略,直接通报 obj 对象,支撑 callback
setItem: function(key, obj, callback) {
const getType = function(a) {
var typeArray = Object.prototype.toString.call(a).split(" ");
return typeArray[1].slice(0, -1);
};
var firstParamType = getType(arguments[0]);
if (firstParamType === "Object") {
var keyArrayLength = Object.keys(arguments[0]).length;
var index = 0;
for (var keyName in arguments[0]) {
index++;
wx.setStorage({
key: keyName,
data: arguments[0][keyName],
success: index == keyArrayLength ? arguments[1] : function() {}
});
}
}
if (firstParamType === "String") {
wx.setStorage({
key: key,
data: obj,
success: callback || function() {}
});
}
},
getItem: function(key) {
return wx.getStorageSync(key);
},
removeItem: function(key) {
wx.removeStorage({
key: key
});
}
};
例子
wx.Storage.setItem(
{
class_pid: that.data.class_pid,
class_id: that.data.class_id,
is_import: that.data.is_import,
shop_type: 1
},
function() {
console.log("Storage 已设置终了!");
}
);
3.filter 盘算属性
小顺序也有盘算属性,你知道吗?
// 文件名称为 :filter.wxs
// 不支撑es6,Date,Number
function filterOrderTitleName(status) {
switch (status) {
case "1":
return "待付出";
case "2":
return "待配送";
case "3":
return "配送中";
case "4":
return "已完成";
}
}
function filterPrice(str) {
// 四舍五入 格式化数字
// toFix(8440.55,1) => 8440.6
var times = Math.pow(10, 2);
var roundNum = Math.round(str * times) / times;
return roundNum.toFixed(2);
}
module.exports = {
filterOrderTitleName: filterOrderTitleName,
filterPrice: filterPrice
};
- 运用实例,过滤处置惩罚打折后的金额小数位数
// 当前文件名:shoppingCart.wxml
// wxs 文件顶部导入
<wxs src="../../filter/filter.wxs" module="filter"></wxs>
<view class='offerPrice nowrap'>¥{{filter.filterPrice(item.plus*100*item.price/1000)}}
<image class='youhuiBox' src="../../assets/youhuiBox.png">
<view class='youhuiText'>会员{{item.dazhe}}折</view>
</image>
</view>
4.flex Style
分享我常运用的自定义的一套 flex 款式,疾速完成规划
/* -------------------------------------------------------------flex------------------------------------------------------- */
.center {
display: flex;
align-items: center;
justify-content: center;
}
/* 单行程度垂直 */
.oneLineCenter {
display: flex;
display: -webkit-flex;
justify-content: center;
align-items: center;
}
/* 单行垂直居中,程度向左 */
.oneLineStart {
display: flex;
display: -webkit-flex;
justify-content: flex-start;
align-items: center;
}
/* 单行垂直居中,程度向右 */
.oneLineEnd {
display: flex;
display: -webkit-flex;
justify-content: flex-end;
align-items: center;
}
/* 单行垂直居中,程度坚持间距 */
.oneLineAround {
display: flex;
display: -webkit-flex;
justify-content: space-around;
align-items: center;
}
/* 单行垂直居中,两头对齐 */
.oneLineBetween {
display: flex;
display: -webkit-flex;
justify-content: space-between;
align-items: center;
}
/* 凌驾单行设置的最大宽度,许可换行显现 */
.f-wrap {
flex-wrap: wrap;
}
/* 多轴线方向,平常合营 wrap 运用 */
/* 宽度不足换行后,垂直方向靠上分列 */
.mulitLineStart {
display: flex;
display: -webkit-flex;
flex-wrap: wrap;
align-content: flex-start;
}
/* 宽度不足换行后,垂直方向居中分列 */
.mulitLineCenter {
display: flex;
display: -webkit-flex;
flex-wrap: wrap;
align-content: center;
}
/* 宽度不足换行后,垂直方向靠下分列 */
.mulitLineEnd {
display: flex;
display: -webkit-flex;
flex-wrap: wrap;
align-content: flex-end;
}
/* 宽度不足换行后,垂直方向上坚持间隔分列 */
.mulitLineAround {
display: flex;
display: -webkit-flex;
flex-wrap: wrap;
align-content: space-around;
}
/* 宽度不足换行后,垂直方向上靠两侧最顶最先间隔分列 */
.mulitLineBetween {
display: flex;
display: -webkit-flex;
flex-wrap: wrap;
align-content: space-between;
}
/* 纵轴变主轴,垂直靠上,程度居中 */
.columnStart {
display: flex;
display: -webkit-flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
/* 纵轴变主轴,垂直靠下,程度居中 */
.columnEnd {
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: center;
}
/* 纵轴变主轴,垂直居中,程度居中 */
.columnCenter {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
/* 纵轴变主轴,垂直间隔分列,程度居中 */
.columnAround {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}
/* 纵轴变主轴,垂直高低两侧按间隔分列,程度居中 */
.columnBetween {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
/* 纵轴变主轴,垂直高低两侧按间隔分列,程度靠左 */
.columnBetweenStart {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
}
/* 纵轴变主轴,垂直高低两侧按间隔分列,程度靠右 */
.columnBetweenEnd {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-end;
}
5.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();
}
});
6.addKey Api
运用自定义属性的要领辅佐完成营业逻辑,已宣布至
addKey
/**
* 为数组增加新的自定义键值以及过滤每一个子项的要领
*
* @param {*} arr
* @param {*} obj { isShow:false,isStar:false}
* @param {*} filterFn
* @returns
*/
function addKey(sourceArray, extendObj, filterFn) {
var getType = function(a) {
var typeArray = Object.prototype.toString.call(a).split(" ");
return typeArray[1].slice(0, -1);
};
var secondParamType = getType(arguments[1]);
if (!getType(sourceArray) == "Array") {
throw new Error("The first argument must be an array type");
}
if (secondParamType === "Object") {
return sourceArray.forEach((v, index, sourceArray) => {
for (var key in extendObj) {
v[key] = extendObj[key];
}
typeof filterFn === "function" ? filterFn(v, index, sourceArray) : "";
});
} else if (secondParamType === "Function") {
return sourceArray.forEach((v, index, sourceArray) => {
arguments[1](v, index, sourceArray);
});
} else {
return sourceArray;
}
}
- 运用实例
util.addKey(data, { y_isCheck: false }, function(v) {
v.dazhe = Number(v.plus);
});
this.setData({
cartList: data
});
7. 组件化复用开辟实践
组件化解构项目元件,进步开辟效力,可参照
官方引见起步 !
这里引见一个自定义的跑马灯的轮播图组件实例
(1) 第一步,检察目次构造分别,主要为 Carousel
组件 在 index
页面的运用
│
├───component
│ └───Carousel
│ Carousel.js
│ Carousel.json
│ Carousel.wxml
│ Carousel.wxss
│
├───filter
│ filter.wxs
│
├───pages
│ └───index
│ index.js
│ index.json
│ index.wxml
│ index.wxss
│
└───utils
api.js
runtime.js
util.js
(2) 第二步我们剖析看怎样运用,设想 组件须要的 props
- 数据项,必需
bannerList
- 轮播图的牢固高度
swiperHeight
- 自定义轮播按钮小点,宽与高一致,圆形
dotWidthAndHeight
- 轮播按钮盒子间隔顶部的高度
dotTop
终究在 index.wxml 的实际运用
<view class="Carousel">
<Carousel
swiperHeight="260rpx"
bannerList="{{bannerList}}"
dotWidthAndHeight="12rpx"
dotTop="-20rpx"
></Carousel>
</view>
(3).营业代码编写
- Carousel.json
开启自定义组件形式
{
"component": true
}
- Carousel.wxml
<view class="Carousel_wrap">
<!-- 图片区 -->
<swiper
current="{{swiperCurrentIndex}}"
circular="true"
bindchange="swiperChange"
indicator-dots="{{indicatorDots}}"
autoplay="true"
interval="5000"
duration="1000"
style="height:{{swiperHeight}}"
>
<swiper-item
wx:for="{{bannerList}}"
bindtap="toHref"
wx:key="{{index}}"
bindtap="toHref"
data-type="{{item.type}}"
data-id="{{item.goods_id}}"
data-content="{{item.content}}"
data-link="{{item.link}}"
>
<image src="{{item.img_url}}" class="slide-image" />
</swiper-item>
</swiper>
<!-- 关联按钮 -->
<view class="boxCell" style="top:{{dotTop}}">
<block
wx:for="{{bannerList.length > 1 ? bannerList:[]}}"
wx:for-index="index"
wx:key="{{item.banner}}"
>
<view
id="{{index}}"
class="dot {{index === swiperCurrentIndex ? 'dot_active':''}}"
style="width:{{dotWidthAndHeight}},height:{{dotWidthAndHeight}}"
bindtap="selectCarouselByIndex"
/>
</block>
</view>
</view>
- Carousel.js
Component({
/**
* 组件的属性列表 必需
*/
properties: {
bannerList: {
// 属性名
type: Array, // 范例(必填),现在接收的范例包含:String, Number, Boolean, Object, Array, null(示意恣意范例)
value: [], // 属性初始值(可选),假如未指定则会依据范例挑选一个
observer: function(newVal, oldVal) {} // 属性被转变时实行的函数(可选),也能够写成在methods段中定义的要领名字符串, 如:'_propertyChange'
},
dotWidthAndHeight: String,
swiperHeight: String, // swiper 高度
dotTop: String // 小点间隔顶部高度
},
/**
* 组件的初始数据
*/
data: {
swiperCurrentIndex: 0,
indicatorDots: false // 自定义轮播按钮
},
/**
* 组件的要领列表
*/
methods: {
swiperChange: function(e) {
var source = e.detail.source;
if (source === "autoplay" || source === "touch") {
this.setData({
swiperCurrentIndex: e.detail.current
});
}
},
selectCarouselByIndex: function(e) {
this.setData({
swiperCurrentIndex: Number(e.currentTarget.id)
});
},
// 轮播图跳转至内部页面
toHref(e) {
const data = e.currentTarget.dataset;
// type = 2,依据 goods_id 展现商品概况
// type = 3, 展现富文本的运动概况页面
if (data.type === "2") {
wx.navigateTo({
url: `../sort_detail/sort_detail?id=${data.id}`
});
} else if (data.type === "3") {
wx.yue.pub("renderData", data.content);
wx.navigateTo({
url: `../activity_detail/activity_detail`
});
}
}
}
});
更多
wxapp-rainbow 安利一下本身写的小顺序组件库(偏功能性)
- uploadImg 上传图片
- carousel 轮播图
- authorization 受权登录
- loading 加载中
参考
生态圈
- ColorUI 鲜明的高饱和颜色,专注视觉的小顺序组件库
- taro 多端一致开辟框架,支撑用 React 的开辟方式编写一次代码,天生能运行在微信小顺序、H5 、 React Native 等的运用
- uni-app 运用 Vue.js 开辟跨平台运用的前端框架
- 微信小顺序开辟资源汇总