专栏首页Fundebug2019,6 招帮助你更好的开发小程序

2019,6 招帮助你更好的开发小程序

摘要: 微信小程序开发技巧。

Fundebug经授权转载,版权归原作者所有。

前言

原生开发小程序有了两个项目,在原生开发小程序经验技巧方面有一些自己的总结,此篇文章做原创分享!

本文适合老手查看,新手请参阅官方文档,同步至github

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 = {
    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
        });
    }
};

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

使用自定义属性的方法辅助完成业务逻辑

/**
 * 为数组添加新的自定义键值以及过滤每个子项的方法
 *
 * @param {*} arr
 * @param {*} obj { isShow:false,isStar:false}
 * @param {*} filterFn
 * @returns
 */
function addKey(arr, obj, filterFn) {
    var temp = arr.forEach((v, index, arr) => {
        typeof filterFn === "function" ? filterFn(v, index) : "";
        for (var key in obj) {
            v[key] = obj[key];
        }
    });
    return temp;
}
  • 使用实例
util.addKey(data, { y_isCheck: false }, function(v) {
    v.dazhe = Number(v.plus);
});
this.setData({
    cartList: data
});

7. 自定义 headerBar

后续分享...

参考

生态圈

  • ColorUI 鲜亮的高饱和色彩,专注视觉的小程序组件库
  • taro 多端统一开发框架, React 语法

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java线上应用实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了10亿+错误事件,付费客户有Google、360、金山软件、百姓网等众多品牌企业。欢迎大家免费试用

原文链接:https://segmentfault.com/a/1190000018608597

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 麻烦的JavaScript类型检查

    JS 的动态类型有好有坏。好的一面,不必指明变量的类型。不好的是,咱们永远无法确定变量的类型。

    Fundebug
  • JavaScript 为什么要有 Symbol 类型?

    Symbols 是 ES6 引入了一个新的数据类型 ,它为 JS 带来了一些好处,尤其是对象属性时。 但是,它们能为我们做些字符串不能做的事情呢?

    Fundebug
  • 如何快速搭建一个短链接服务?

    短链接我们或多或少都使用过,所谓短链接就是根据较长的原链接url生成一段较短的链接,访问短链接可以跳转到对应的原链接,这样做好处在于:1. url更加美观;2....

    Fundebug
  • 全栈开发工程师微信小程序-上

    wx:for是列表渲染标签,默认当前循环项的变量名为item.wx:key用于在动态列表渲染中保存子项的特征和状态.

    达达前端
  • CSS中Flex布局的可伸缩性(Flexibility)

    Flex伸缩布局决定性的特性是让伸缩项目可伸缩,也就是让伸缩项目的宽度或高度自动填充剩余的空间。这可以以flex属性完成。一个伸缩容器会等比地按照各伸缩项目的 ...

    Javanx
  • Nginx之美多商城前台部署

    通过浏览器发送请求,能够获取到响应则表示uwsgi和Django程序能够正常进行通信了。

    猿哥
  • C#中的正则表达式表达'.'和'\'

    如果要表达字符串中的'.',在正则表达式中表达为"\.",因为'.'在正则表达式中是元字符,需要'\'进行转义,那么在C#中就是"\\.",第一个'\'是C#用...

    望天
  • 后端程序员也能看懂的微信小程序开发入门

    小程序时至今日已经非常火爆了,作为软件体系中的一员,越来越多的公司与个人都在发展自己的小程序,而且小程序不再是单一的微信小程序了,还有百度小程序、支付宝小程序、...

    蒋老湿
  • 重温delphi之控制台程序:Hello World!

    这二天用c#开发ActiveX时,发现不管怎么弄,c#就是没办法生成ocx的纯正activeX控件,而且还要强迫用户安装巨大的.net framework(我只...

    菩提树下的杨过
  • ASP.NET常用导出Excel方法汇总

    本文转载:http://mattberseth.com/blog/2007/04/export_gridview_to_excel_1.html

    跟着阿笨一起玩NET

扫码关注云+社区

领取腾讯云代金券