本人封装了一个vue3 ts的uniapp通用组件,欢迎大家使用有任何问题可以去Q交流也可以去gitee上提,共同学习,完全免费
myCompont 组件说明
组件目录
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>