更新记录

1.0.2(2025-12-11) 下载此版本

更新了git 和加载失败图片不显示的bug

1.0.1(2025-12-01) 下载此版本

1.0.1:

删除了m-authorize 后续添加 新增瀑布流组件 m-waterfall

1.0.0(2025-12-01) 下载此版本

1.0.0 组件上线,开始如下组件 m-authorize 登录组件 m-button 按钮 m-checkbox 多选组件 m-city-selector 城市选择 m-code 验证码 m-countdown 定时获取验证码 m-downlist 搜索框 m-form 表单组件 m-form-item 表单项组件 m-icon icon组件 m-images 图片组件 m-list 数据列表 m-loading 加载中 m-login 快捷登录 m-navbar 自定义导航 m-number-box 数字输入框 m-picker 选择弹出 m-popup 弹出框 m-rating 评分 m-skeleton 骨架 m-swiper 轮播图 m-swiper-item m-tabbar 自定义底部菜单 m-toast 消息提示 m-uploadimg 图片上传组件 m-video 视频显示组件

查看更多

平台兼容性

uni-app(4.86)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× - - × × × ×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 快应用-华为 快应用-联盟
3.11.1 - - - - - - - - × ×

myCompont 组件说明

一款支持vue3 ts 的uniapp常用组件库,免费试用、主要是作者工作中使用然后收集慢慢完善,有问题qun 1044861125 共同学习 完善该组件

使用方法

 把 m-component 复制到\components目录下

 pages.json中配置
 "easycom": {
   // 基础/业务组件全局自动注册(保持原使用方式)
   // "autoscan": true
   "autoscan": true,
   "custom": {
    "^m-(.*)$": "@/components/m-compont/m-$1/m-$1.vue"
   }

  },

组件目录


m-button 按钮
m-checkbox 多选组件
m-city-selector 城市选择
m-code 验证码
m-countdown 定时获取验证码
m-downlist 搜索框
m-form 表单组件
m-form-item 表单项组件
m-icon icon组件
m-images 图片组件
m-list 数据列表
m-loading 加载中
m-login 快捷登录
m-navbar 自定义导航
m-number-box 数字输入框
m-picker 选择弹出
m-popup 弹出框
m-rating 评分
m-skeleton 骨架
m-swiper 轮播图 m-swiper-item
m-tabbar 自定义底部菜单
m-toast 消息提示
m-uploadimg 图片上传组件
m-video 视频显示组件
m-waterfall 瀑布流组件

组件使用

m-button

按钮组件


showText: {
    type: Boolean, // 是否显示按钮文字 
    default: true
},
type:{
    type: String,
    default: "text"},
fontSize: {
    type: String,
    default: "24rpx"
},
openType: {
    type: String, //调用小程序原生使用
    default: ""
},
btnStyle: {
    type: Object, //按钮样式
    default: () => ({})
},
color: {
    type: String, //文字颜色
    default: "#fff"
},
text: {
    type: String, //文本内容
    default: '确定'
},
click: {
    type: Function, //点击事件
    default: null
}

<m-button openType="share" @click="share" type="botton" :title="``" :btnStyle="style1">
    <view class="flex flex-column align-center" style="margin-top: 6rpx;" @click="share">
        <view class="flex align-center justify-center">
            <text class="iconfont icon-share"></text>
        </view>
            <view class="foaim">
                分享
            </view>
    </view>
</m-button>

m-checkbox

复选按钮

 * @param activeColor 选中的背景颜色
   * @param inactiveColor 未选中的背景颜色
   * @param iconColor 图标颜色
   * @param direction 选择框和文本的布局方向
   * @param size 选择框的大小
   * @param gap 选择框和文本的间距
   * @param activeValue 选中的值
   * @param inactiveValue 未选中的值

   modelValue: any
shape?: 'circle' | 'square' | 'round'
direction?: 'left' | 'right' | 'top' | 'bottom'
size?: number
/** 选中的背景颜色 */
activeColor?: string
/** 未选中的时候颜色 border颜色 */
inactiveColor?: string
/** 图标颜色*/
iconColor?: string
gap?: number
/**自定义选中值*/
activeValue?: any // ✅ 自定义选中值
/** 自定义未选中值*/
inactiveValue?: any // ✅ 自定义未选中值

<m-checkbox
  :size="20"
  shape="circle"
  direction="left"
  :activeColor="'#4199FF'"
  :inactiveColor="'#666666'"
  :iconColor="'#fff'"
  @onchange="onchange($event, index)"
  v-model="item.checked"
>
</m-checkbox>

m-city-selector

城市选择 城市选择插件,城市数据在city.ts中,可以自行更新,选择城市后给父组件返回选中城市数据。支持城市搜索

详情 https://ext.dcloud.net.cn/plugin?id=24847

m-code

输入验证码

 /**
 * 双向绑定的值
 */
modelValue?: string | number
/**
 * 验证码长度
 * @default 4
 */
length?: number
/**
 * 输入框边框颜色(选中时)
 * @default '#9666FF'
 */
borderColor?: string
/**
 * 文字颜色
 * @default '#333'
 */
textColor?: string
/**
 * 文字大小,单位 rpx
 * @default 36
 */
textSize?: number | string
/**
 * 每个格子的宽高,单位 rpx
 * @default 90
 */
size?: number | string

m-countdown

获取手机验证码倒计时

duration

<m-countdown ref="countdownRef" 
  :duration="60"
  @click="getCode"
  @start="onStart"
  @end="onEnd"></m-countdown>

  onStart 开始
  getCode 点击 获取验证码
  onEnd 结束

m-downlist

items: Record<string, any>[] 数据类型
selectedId?: string | number | null 选择中的
valueKey?: string  数据的KEY
labelKey?: string lbae key字段
multiple?: boolean 是否多选

<m-downlist style="width: 100%" v-model:selectedId="formData.merchant_category_id" @search="searchStore"
            :items="adminStoreClassData" valueKey="merchant_category_id"
labelKey="category_name"></m-downlist>

m-form

表单组件

<m-form ref="formRef" :rules="rules" :labelStyle="labelStyle" :model="formData">
    <view class="detail">
        <view class="itms">
            <m-form-item label="收货人" prop="real_name">
                <input v-model="formData.real_name" placeholder="收货人"></input>
            </m-form-item>
        </view>
        <view class="itms">
            <m-form-item label="联系手机" prop="phone">
                <input v-model="formData.phone" placeholder="联系手机"></input>
            </m-form-item>
        </view>
        <view class="itms">
            <m-form-item label="所在地区" prop="province">
                <view class="flex justify-space w" @click="selectAddress">
                    <!-- <input disabled v-model="formData.real_name" placeholder-style="color:#C8C8C8;" placeholder="请输入店铺名称" /> -->
                    <view style="width:400rpx;">
                        <view v-if="!formData.province">
                            请选择地区
                        </view>
                        <view v-else>
                            <text>
                                {{formData.province}}
                            </text>
                            <text>
                                {{formData.city}}
                            </text>
                            <text>
                                {{formData.district}}
                            </text>
                        </view>
                    </view>
                    <m-images :url='mapicon' width="28rpx" height="34rpx"></m-images>
                </view>
                <view>

                </view>
            </m-form-item>
        </view>
        <view class="itms">
            <m-form-item label="详细地址" prop="address_name">
                <input v-model="formData.address_name" placeholder="请输入详细地址"></input>
            </m-form-item>
        </view>

    </view>
    <!-- 设为默认地址 -->
    <view class="flex align-center"
        style="margin-top:20rpx;gap:6rpx;background:#fff;height: 122rpx;padding-left:68rpx">
        <m-checkbox :size="14" direction="left" :activeColor="'#4199FF'" :inactiveColor="'#666666'"
            :iconColor="'#fff'" :gap="0" :activeValue="1" :inactiveValue="0" shape="circle"
            v-model="formData.is_default" />
        <text style="color:#4199FF;">设为默认地址</text>
    </view>
</m-form>

表单验证
// 表单验证
const rules = ref({
    real_name: [
        { required: true, message: '请输入收货人', trigger: 'blur' },
    ],
    phone: [
        { required: true, message: '请输入手机号码', trigger: 'blur' },
        {
            pattern: /^1[3-9]\d{9}$/,
            message: '手机号格式不正确',
            trigger: 'blur'
        }
    ],
    province: [
        { required: true, message: '请选择地区', trigger: 'blur' },
    ],
    address_name: [
        { required: true, message: '请输入详细地址', trigger: 'blur' },
    ]

})
获取验证结果
const valid = await formRef.value.validate()

if (!valid.valid) {
  return toastRef.value.show('请将数据填写完整')
}

m-icon

icon组件


<m-icon
  :size="midButton && item.midButton ? midButtonSize : iconSize"
  :name="elIconPath(index)"
  img-mode="scaleToFill"
  :color="elColor(index)"
  :custom-prefix="item.customIcon ? 'custom-icon' : 'uicon'"
/>

m-images

图片显示组件

// 图片链接
url: {
  type: String,
  required: true
},
// 图片裁剪、缩放模式
mode: {
  type: String as PropType<ModeType>,
  default: 'scaleToFill'
},
// 宽度
width: {
  type: [String, Number],
  default: '100%'
},
// 高度
height: {
  type: [String, Number],
  default: '100%'
},
// loading图片大小
loadingSize: {
  type: [String, Number],
  default: '60rpx'
},
// 圆角 角度
rounded:{
      type: [Number,String],
      default: 0
},
// 是否开启点击后查看大图
showLarge:{
      type:Boolean,
      default:false
},
// 查看大图的数组
currImage:{
      type: Array,
      default: ()=>[]
}

     <m-images :url="serachUrl" width="40rpx" height="40rpx" />

m-list

m-loading

加载状态

  status?: LoadStatus    /**'loading' | 'nodata' | 'getall' | 'loaded' 加载中 暂无数据 加载更多 加载完成 */
 <m-loading v-if="loading!='loaded'"  :status="loading"></m-loading>

m-login

其他登录方式

<view>
    <m-login></m-login>

m-navbar

自定义导航栏

backColor: { type: String, default: '#000019' }, // 返回图标颜色
background: { type: String, default: '' }, // 导航栏背景色
isFixed: { type: Boolean, default: true }, // 是否固定顶部
borderBottom: { type: Boolean, default: true }, // 是否显示底部边框
isBack: { type: [Boolean, String], default: true }, // 是否显示返回按钮
height: { type: [String, Number], default: '' }, // 导航栏高度(非小程序平台)
backText: { type: String, default: '' }, // 返回按钮文字
backTextStyle: { type: Object, default: () => ({ color: '#606266' }) }, // 返回文字样式
title: { type: String, default: '' }, // 标题文本
titleWidth: { type: [String, Number], default: '250' }, // 标题宽度
titleColor: { type: String, default: '#606266' }, // 标题颜色
immersive: { type: Boolean, default: false }, // 是否沉浸式
titleBold: { type: Boolean, default: false }, // 标题是否加粗
titleSize: { type: [String, Number], default: 32 }, // 标题字号
customBack: { type: Function, default: null } // 自定义返回事件

  <m-navbar :title="title" :isBack="true" :background="backgroundNav">
  <view class="ssetflex justify-space" style="width: 94%">
    <JointSearch
      ref="joinREf"
      v-model="searchKeyword"
      @clear="clear"
      labelKey="keyword"
      :showType="false"
      :background="`#F9F9F9`"
      @confirm="confirmInput"
    />
  </view>
</m-navbar>

m-number-box

数字输入框

 modelValue: { type: [Number, String], default: 1 },
min: { type: [Number, String], default: 1 },
max: { type: [Number, String], default: 100 },
step: { type: [Number, String], default: 1 },
disabled: { type: Boolean, default: false },
showMinus: { type: Boolean, default: true },
showPlus: { type: Boolean, default: true },

 <m-number-box style="height: 100%;" :showMinus="false" :showPlus="false" :max="spectData?spectData.stock:`1`" v-model="inputValue"></m-number-box>

m-picker

下拉选择数据

 modelValue: boolean
columns: PickerItem[]
defaultValue?: (string | number)[]
labelKey?: string 
valueKey?: string

 <m-picker v-model="qyShowSelect" :columns="configPay.bankAccountType" 
 @change="qyPickerChange" labelKey="name" 
  valueKey="type"></m-picker>

m-popup

弹出层

    // 显示隐藏
    /** 显示隐藏*/
modelValue: { type: Boolean, default: false },
showmark: { type: Boolean, default: true },
bacground: { type: String, default: '#fff' },
title: { type: String, default: '' },
fontSize: { type: Number, default: 26 },
fontWeight: { type: Boolean, default: true },
showClose: { type: Boolean, default: false },
lineHeight: { type: Number, default: 30 },
zIndex: { type: Number, default: 11 },
closeIndex: { type: Number, default: 0 },
showTitle:{ type: Boolean, default: true },
 /** 圆角: 可以传字符串统一四个角,也可以传对象分别控制 */
  borderRadius: {
    type: [String, Object] as PropType<RadiusType>,
    default: '20rpx'
  },
type: {
  type: String as PropType<Direction>,
  default: 'bottom',
},

 <m-popup :zIndex="22" v-model="showSelectSpec" :showClose="true">
   <SelectSpec :productDetail="productData" @changeSku="changeSku"></SelectSpec>
</m-popup>

m-rating

评分


modelValue: { type: Number, default: 0 }, // 当前评分(可小数)
max: { type: Number, default: 5 },        // 总星数
color: { type: String, default: "#FF7300" }, // 实心颜色
emptyColor: { type: String, default: "#e1e1e1" }, // 空心颜色

<m-rating v-model="item.service_score" color="#FFF05D" :max="5" />

m-skeleton

 <m-skeleton v-if="loading" :rows="5" width="300rpx" height="400rpx"></m-skeleton>

m-swiper

轮播图

* 轮播图组件
 * 支持视频和图片轮播
 * 轮播切换时视频暂停,视频播放时轮播暂停,视频结束后轮播恢复

<m-swiper :url="swiperData" width="750rpx" height="600rpx" ></m-swiper>

m-tabbar

自定义底部导航

// 非凸起按钮未激活的图标,可以是uView内置图标名或自定义扩展图标库的图标
    // 或者png图标的【绝对路径】,建议尺寸为80px * 80px
    // 如果是中间凸起的按钮,只能使用图片,且建议为120px * 120px的png图片
    iconPath: "home",
    // 激活(选中)的图标,同上
    selectedIconPath: "home-fill",
    // 显示的提示文字
    text: "首页",
    // 红色角标显示的数字,如果需要移除角标,配置此参数为0即可
    count: 2,
    // 如果配置此值为true,那么角标将会以红点的形式显示
    isDot: true,
    // 如果使用自定义扩展的图标库字体,需配置此值为true
    // 自定义字体图标库教程:https://www.uviewui.com/guide/customIcon.html
    customIcon: false,
    // 如果是凸起按钮项,需配置此值为true
    midButton: false,
    // 点击某一个item时,跳转的路径,此路径必须是pagees.json中tabBar字段中定义的路径
    pagePath: "", // 1.5.6新增,路径需要以"/"开头

    定义 tabbar 场景,我们不建议在一个页面内通过几个组件,用v-if切换去模拟各个页面,而应该使用 uni-app 自带的 tabbar 系统,同时隐藏原生的 tabbar, 再引入自定导航栏,这样可以保证原有性能,同时又能自定义 tabbar,思路如下:

    在 pages.json 中正常定义 tabbar 逻辑和字段,只需配置tabBar字段list中的pagePath(需以"/"开头)属性即可
    在各个 tabbar 页面引入u-tabbar组件,组件会默认自动通过uni.hideTabBar()隐藏系统 tabbar
    通过vuex引用同一份 tabbar 组件的list参数,这样可以做到修改某一个页面的u-tabbar数据,其他页面的u-tabbar也能同步更新
    组件内部会自动处理各种跳转的逻辑,同时需要注意以下两点:
    要在list参数中配置pagePath路径,此路径为pages.json中定义的 tabbar 字段的路径
    此种方式,无需通过v-model绑定活动项,内部会自动进行判断和跳转

    代码
    let list = [
      {
        // 非凸起按钮未激活的图标,可以是uView内置图标名或自定义扩展图标库的图标
        // 或者png图标的【绝对路径】,建议尺寸为80px * 80px
        // 如果是中间凸起的按钮,只能使用图片,且建议为120px * 120px的png图片
        iconPath: "home",
        // 激活(选中)的图标,同上
        selectedIconPath: "home-fill",
        // 显示的提示文字
        text: "首页",
        // 红色角标显示的数字,如果需要移除角标,配置此参数为0即可
        count: 2,
        // 如果配置此值为true,那么角标将会以红点的形式显示
        isDot: true,
        // 如果使用自定义扩展的图标库字体,需配置此值为true
        // 自定义字体图标库教程:https://www.uviewui.com/guide/customIcon.html
        customIcon: false,
        // 如果是凸起按钮项,需配置此值为true
        midButton: false,
        // 点击某一个item时,跳转的路径,此路径必须是pagees.json中tabBar字段中定义的路径
        pagePath: "", // 1.5.6新增,路径需要以"/"开头
      },
    ];

    # 代码

     <view>
        <view class="u-page">
          <!-- 所有内容的容器 -->
        </view>
        <!-- 与包裹页面所有内容的元素u-page同级,且在它的下方 -->
        <u-tabbar v-model="current" :list="list" :mid-button="true"></u-tabbar>
      </view>
    </template>

    <script>
      export default {
        data() {
          return {
            list: [
              {
                iconPath: "home",
                selectedIconPath: "home-fill",
                text: "首页",
                count: 2,
                isDot: true,
                customIcon: false,
              },
              {
                iconPath: "photo",
                selectedIconPath: "photo-fill",
                text: "放映厅",
                customIcon: false,
              },
              {
                iconPath: "https://cdn.uviewui.com/uview/common/min_button.png",
                selectedIconPath: "https://cdn.uviewui.com/uview/common/min_button_select.png",
                text: "发布",
                midButton: true,
                customIcon: false,
              },
              {
                iconPath: "play-right",
                selectedIconPath: "play-right-fill",
                text: "直播",
                customIcon: false,
              },
              {
                iconPath: "account",
                selectedIconPath: "account-fill",
                text: "我的",
                count: 23,
                isDot: false,
                customIcon: false,
              },
            ],
            current: 0,
          };
        },
      };

m-toast

消息提示

      <m-toast ref="toastREf"></m-toast>

      const toastREf = ref<InstanceType<typeof MToast> | null>(null);
        toastREf.value?.show("删除成功");

m-uploadimg

图片上传组件

<m-uploadimg v-model="formData.licenceUrl" :defaultImage="businessUrl" :imgWidth="552"
  @defaultClick="defaultClickbase(1)" :imgHeight="396">
  <template #default="{ index, src }">
    <view @click.stop="upYbFile(1)" v-if="!formData.licenceUrl" class="addImgUp">
      点击上传
    </view>
  </template>
</m-uploadimg>

// 默认显示的营业执照
const businessUrl = ref(
  staticUrl + "/tx_user_sever_img/createStore/zhizhoa.png"
);
const defaultClickbase = (num:number) => {
 upYbFile(num)
};

m-watrfall

瀑布流组件

 * @param value  瀑布流数据
 * @param addTime 插入数据的时间间隔
 * @param keyIdData / id值,用于清除某一条数据时,根据此idKey名称找到并移除

<m-waterfall :value="product" ref="commproduct">
    <!-- 左边数据 -->
    <template v-slot:left="{leftList}">
        <view @click="goodsDetail(item)" class="prodecutitem" v-for="(item,index) in leftList" :key="item.goodsId" >
            <view style="width: 100%;">
                <m-imgage  mode="widthFix" :url="statusUrl+item.showImage"></m-imgage>
            </view>
            <view class="textDertail">
                <view class="title">{{item.name}}</view>
                <!-- <view class="desc">{{item.title}}</view> -->
                <view class="descList">
                    <text class="tej" v-for="(citem,cindex) in item.labelName.split(',')" :key="citem">{{citem}}</text>
                    <!-- <text class="tej">特价</text>
                    <text class="te24">24H发货</text> -->
                </view>
                <view class="numb1">
                    <text class="fh">¥</text><text class="pay">{{item[leveKey]}}</text>/元
                </view>
                <view class="numb2">
                    原价¥{{item.originalPrice}}/元
                </view>
            </view>
        </view>
    </template>
    <!-- 右边数据 -->
    <template v-slot:right="{rightList}">
        <view class="prodecutitem" v-for="(item,index) in rightList" :key="item.goodsId" @click="goodsDetail(item)">
            <view>
                <m-imgage  :url="statusUrl+item.showImage" mode="widthFix"></m-imgage>
            </view>
            <view class="textDertail">
                <view class="title">{{item.name}}</view>
                <!-- <view class="desc">{{item.title}}</view> -->
                <view class="descList" v-if="item.labelName">
                    <text class="tej" v-for="(citem,cindex) in item.labelName.split(',')" :key="citem">{{citem}}</text>
                    <!-- <text class="te24">24H发货</text> -->
                </view>
                <view class="numb1">
                    <text class="fh">¥</text><text class="pay">{{item[leveKey]}}</text>/元
                </view>
                <view class="numb2">
                    原价¥{{item.originalPrice}}/元
                </view>
            </view>
        </view>
    </template>
</m-waterfall>

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议