mpvue

小程序全局菜单组件

2021-03-20  本文已影响0人  Enginner_XZ

组件代码

// components/menuList/menuList.js
let that;
import { WxApi } from '../../utils/utilsClass/utilsClass'

Component({
    /**
     * 组件的属性列表
     * @param cardMenuCont { Array } 菜单列表 在菜单列表数组内以每个对象为一个选项
     * @param text { String } 对象内填入 为显示的菜单选项文字
     * @param callBack { Function } 对象内填入 为点击后触发的回调函数 可通过bind()指定this指向
     */
    properties: {
        cardMenuCont: {
            default: [{
                    text: '编辑',
                    callBack: '',
                },
                {
                    text: '订单',
                    callBack: ''
                },
                {
                    text: '公开', // 默认值
                    callBack: ''
                }
            ],
            type: Array,
        },
        flag: {
            default: true,
            type: Boolean,
        },
        x: {
            defualt: 100,
            type: Number,
        },
        y: {
            default: 100,
            type: Number,
        }
    },

    lifetimes: {
        attached() {
            that = this;
        },
    },

    /**
     * 组件的初始数据
     */
    data: {
        menuArea : true, // 判断显示菜单的位置能否完整显示出菜单 true 为可以
        xx: 0,
        yy: 0,
        showFlag : false, // 计算完显示位置后显示菜单
    },

    /**
     * 组件的方法列表
     */
    methods: {
        // 触发菜单设置的回调函数
        optionsCallBack( e ){
            const { index } = e.currentTarget.dataset;
            this.properties.cardMenuCont[index].callBack();
        },

        // 计算菜单的高度并返回菜单高度
        MenuHeight(){
            const { cardMenuCont } = this.properties;
            const length = cardMenuCont.length;
            return length * 70 + 24;
        },
    },

    observers: {
        async flag(newVal) {
            if (newVal) {
                const systemInfo = wx.getSystemInfoSync();
                const {windowWidth , windowHeight} = systemInfo;
                const { x , y } = this.properties;
                const menuHeight = this.MenuHeight();
                const menuArea = WxApi.calcRpx(windowHeight) - y >= menuHeight;
                const right = WxApi.calcRpx(windowWidth) - x - 15;
                let yy;
                if( menuArea ){
                    yy = this.properties.y + 30;
                }
                if( !menuArea ){
                    yy = this.properties.y - menuHeight - 30;
                }
                
                this.setData({
                    xx : right,
                    yy,
                    showFlag : true,
                    menuArea,
                })
            } else {
                this.setData({
                    showFlag : false,
                })
            }
        },
    },
})

CSS

/* 弹出盒子 */

.z_view_1{
    min-width: 200rpx;
    background-color: rgba(255, 255, 255 , .9);
    border-radius : 12rpx;
    position: absolute;
    z-index: 100;
    top: 100rpx;
    right: 45rpx ;
    box-sizing: border-box;
    padding : 12rpx;
    box-shadow : 0 5rpx 20rpx 1rpx rgba(0,0,0,.15);
  }
  
  .z_view_1::after{
    content : "";
    position: absolute;
    top: -10rpx;
    right: 10rpx;
    border-bottom : 10rpx solid rgba(255, 255, 255 , .9);
    border-left : 10rpx solid transparent;
    border-right : 10rpx solid transparent;
    border-top : 0 none;
  }
  
  .z_view_1>.z_view_2{
    width: 100%;
    height: 70rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    position: relative;
  }
  
  .z_view_1>.z_view_2:nth-last-child(1)::after{
    content : none;
  }
  
  .z_view_1>.z_view_2::after{
    content : "";
    position: absolute;
    bottom: 0;
    left: 0;
    height: 1rpx;
    width: 100%;
    background-color: rgba(153, 153, 153 , .3);
  }
  
  .z_view_1>.z_view_2>.z_view_3{
    color : black;
    font-size : 32rpx;
    font-family: PingFang SC;
  }

  .reverse::after{
    content : none;
  }

  .reverse::before{
    content : "";
    border-top : 10rpx solid rgba(255, 255, 255 , .9);
    border-left : 10rpx solid transparent;
    border-right : 10rpx solid transparent;
    position: absolute;
    bottom: -10rpx;
    right : 10rpx;
  }

html

<view class="z_view_1 {{menuArea || 'reverse'}}" hidden="{{!showFlag}}" style="right : {{xx}}rpx; top : {{yy}}rpx" id="menu">
    <view class="z_view_2" wx:for="{{cardMenuCont}}" wx:key="index" wx:for-item="mitem" data-index="{{index}}"
        catchtap="optionsCallBack">
        <view class="z_view_3">{{mitem.text}}</view>
    </view>
</view>

Utils类代码

class Utils {
    constructor() {

    }

}

export class UtilsString extends Utils {
    constructor() {
        super()
    }

    /**
     * 递归获取字符串返回数组
     * @param str string 要截取的文本
     * @param intercept string 用于查询开始索引的字符串
     * @param endIntercept string 用于查询结束索引的字符串
     *   */
    static interceptStr(str, intercept, endIntercept, startIndex = 0, arr = []) {
        const index = str.indexOf(intercept, startIndex);
        const interceptLength = intercept.length;
        const strStartIndex = index + interceptLength;
        const strEndIndex = str.indexOf(endIntercept, strStartIndex);
        const result = str.substring(strStartIndex, strEndIndex);
        if (index !== -1) {
            arr.push(result);
            return this.interceptStr(str, intercept, endIntercept, strEndIndex, arr);
        } else {
            return arr;
        }
    }

    /**
     * 创建本地js时间戳+数学对象random生成的随机数拼接的字符串并返回
     */
    static createFileName() {
        const timeStamp = new Date().getTime();
        const randNum = Math.random().toString().substr(2);
        return `${timeStamp}${randNum}`
    }
}

export class WxApi extends Utils {
    constructor() {
        super()
    }

    /**
     * 发起微信支付
     * @param params {Object} 需要传入的参数 (必填项:timeStamp 当前时间戳 、nonceStr 随机字符串最大长度32、paySign 签名)
     * @param paymentPackage {String} 必填 (统一下单接口返回的prepay_id参数值) 
     * @param callBack {Function} 选填 一般通过后端查询支付结果 如有需要callBack将在success内触发
     */
    static payment(params, paymentPackage, callBack) {
        wx.requestPayment({
            ...params,
            package: paymentPackage,
            success(res) {
                if (callBack) {
                    callBack();
                }
            },
            fail(res) {
                console.log(res, 'fail');
            },
        })
    }

    /**
     * @param delta {Number} 返回的页数
     * @param callBack {Function} 非必填 成功回调中触发的回调函数
     */
    static naviBack(delta, callBack) {
        wx.navigateBack({
            delta: delta,
            success() {
                if (callBack) callBack();
            },
        })
    }

    /**
     * @param url {String} 跳转路径
     * @param params {String} 非必填 跳转页面时携带的参数 ?id=1的完整参数
     * @param callBack {Function} 非必填 成功回调中触发的回调函数
     */
    static naviTo(url, params = false, callBack) {
        if (params !== false) url += params;
        wx.navigateTo({
            url,
            success() {
                if (callBack) callBack();
            },
        })
    }

    /**
     * 计算并返回rpx单位
     * @param px {Number} 传入px单位数值 计算出rpx值并返回
     */
    static calcRpx(px) {
        const systemInfo = wx.getSystemInfoSync()
        const {
            windowWidth
        } = systemInfo;
        const rpx = 750 / windowWidth;
        return px * rpx;
    }
}
上一篇下一篇

猜你喜欢

热点阅读