低代码可视化-uniapp开关选择组件-低码生成器
开关(Switch)选择组件是一种用户界面元素,允许用户在两种状态(通常是开/关、是/否、启用/禁用等)之间进行切换。这种组件在移动应用、桌面软件、网页以及物联网设备中广泛应用。以下是对开关Switch选择组件的详细介绍:
一、基本概念
开关Switch选择组件通常由一个滑块和一个滑道组成。滑块是用户可以拖动的部分,而滑道是背景。用户可以通过拖动滑块或点按开关来改变其状态。
二、主要属性
- 状态:
- 表示开关的当前状态,通常是一个布尔值(true/false或1/0)。
- 状态改变回调:
- 当开关状态发生变化时调用的回调函数。
- 该函数通常接收一个新的状态值作为参数。
- 启用/禁用:
- 控制开关是否可用。
- 当设置为禁用状态时,用户无法更改开关的状态。
- 文本标签:
- 在某些实现中,可以为开关的打开和关闭状态设置文本标签。
- 这些标签通常用于提供更清晰的指示或说明。
- 颜色(colors):
- 自定义开关的颜色,包括滑块和滑道的颜色。
- 某些框架允许为开关的不同状态(打开/关闭)设置不同的颜色。
三、组件扩展
基于uview类型的u-switch我们增加了有效文本、无效文本及颜色。扩展组件如下。
<template>
<view
class="u-switch"
:class="[valueCom? 'u-switch--on' : '', disabled ? 'u-switch--disabled' : '']"
@tap="onClick"
:style="[switchStyle]"
>
<view
class="u-switch__node node-class"
:style="nodeStyle"
>
<u-loading
:show="loading"
class="u-switch__loading"
:size="size * 0.6"
:color="loadingColor"
/>
</view>
<view v-if="activeText || inactiveText" class="u-switch__text" :class="{'u-switch__text-end':!valueCom}" >
<text v-if="!valueCom" class="u-switch__text--inactive" :style="{color:inactiveTextColor}">{{ inactiveText }}</text>
<text v-else class="u-switch__text--active" :style="{color:activeTextColor}">{{ activeText }}</text>
</view>
</view>
</template>
<script>
/**
* switch 开关选择器
* @description 选择开关一般用于只有两个选择,且只能选其一的场景。
* @tutorial https://www.uviewui.com/components/switch.html
* @property {Boolean} loading 是否处于加载中(默认false)
* @property {Boolean} disabled 是否禁用(默认false)
* @property {String Number} size 开关尺寸,单位rpx(默认50)
* @property {String} active-color 打开时的背景色(默认#19be6b)
* @property {Boolean} inactive-color 关闭时的背景色(默认#ffffff)
* @property {Boolean | Number | String} active-value 打开选择器时通过change事件发出的值(默认true)
* @property {Boolean | Number | String} inactive-value 关闭选择器时通过change事件发出的值(默认false)
* @event {Function} change 在switch打开或关闭时触发
* @example <u-switch v-model="checked" active-color="red" inactive-color="#eee"></u-switch>
*/
export default {
name: "u-switch",
emits: ["update:modelValue", "input", "change"],
props: {
// 通过v-model双向绑定的值
value: {
type: [Number, String, Boolean],
default: false
},
modelValue: {
type: [Number, String, Boolean],
default: false
},
// 是否为加载中状态
loading: {
type: Boolean,
default: false
},
// 是否为禁用装填
disabled: {
type: Boolean,
default: false
},
// 开关尺寸,单位rpx
size: {
type: [Number, String],
default: 50
},
// 打开时的背景颜色
activeColor: {
type: String,
default: "#19be6b"
},
// 关闭时的背景颜色
inactiveColor: {
type: String,
default: "#ffffff"
},
// 是否使手机发生短促震动,目前只在iOS的微信小程序有效(2020-05-06)
vibrateShort: {
type: Boolean,
default: false
},
// 打开选择器时的值
activeValue: {
type: [Number, String, Boolean],
default: true
},
// 关闭选择器时的值
inactiveValue: {
type: [Number, String, Boolean],
default: false
},
activeText: {
type: String,
default: ''
},
activeTextColor: {
type: String,
default: "#ffffff"
},
inactiveText: {
type: String,
default: ''
},
inactiveTextColor: {
type: String,
default: "#999999"
},
},
data() {
return {
switchWidth:this.size,
};
},
computed: {
valueCom() {
// #ifndef VUE3
return this.value;
// #endif
// #ifdef VUE3
return this.modelValue;
// #endif
},
switchStyle() {
let style = {};
style.fontSize = this.size + "rpx";
style.backgroundColor = this.valueCom ? this.activeColor : this.inactiveColor;
style.width = this.$u.addUnit(this.switchWidth*2);
return style;
},
loadingColor() {
return this.valueCom ? this.activeColor : null;
},
nodeStyle(){
const style = {};
style.width = this.$u.addUnit(this.size);
style.height = this.$u.addUnit(this.size);
style.transform = `translateX(${this.valueCom ? this.switchWidth - this.size/2 : 0}px)`;
return style;
}
},
methods: {
onClick() {
if (!this.disabled && !this.loading) {
// 使手机产生短促震动,微信小程序有效,APP(HX 2.6.8)和H5无效
if (this.vibrateShort) uni.vibrateShort();
this.$emit("input", this.valueCom==this.activeValue ? this.inactiveValue : this.activeValue);
this.$emit("update:modelValue", this.valueCom==this.activeValue ? this.inactiveValue : this.activeValue);
// 放到下一个生命周期,因为双向绑定的value修改父组件状态需要时间,且是异步的
this.$nextTick(() => {
this.$emit("change", this.valueCom==this.activeValue ? this.inactiveValue : this.activeValu);
});
}
},
updateSwitchWidth() {
let textLength = Math.max(this.activeText.length,this.inactiveText.length)
this.switchWidth = Math.max(textLength*12+10+this.size/2, this.size)
}
},
mounted() {
this.updateSwitchWidth();
},
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-switch {
position: relative;
/* #ifndef APP-NVUE */
display: inline-block;
/* #endif */
box-sizing: initial;
width: 2em;
height: 1em;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 1em;
transition: background-color 0.3s;
font-size: 50rpx;
&__text {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10rpx;
font-size: 24rpx;
&-end{
justify-content: flex-end;
}
&--inactive {
color: #999999;
white-space: nowrap;
text-align: right;
}
&--active {
color: #fff;
white-space: nowrap;
}
}
}
.u-switch__node {
@include vue-flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
border-radius: 100%;
z-index: 1;
background-color: #fff;
background-color: #fff;
box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1),
0 3px 3px 0 rgba(0, 0, 0, 0.05);
box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1),
0 3px 3px 0 rgba(0, 0, 0, 0.05);
transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05),
-webkit-transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
}
.u-switch__loading {
@include vue-flex;
align-items: center;
justify-content: center;
}
.u-switch--on {
background-color: #1989fa;
}
.u-switch--on .u-switch__node {
transform: translateX(100%);
}
.u-switch--disabled {
opacity: 0.4;
}
</style>
四、可视化设计
拖动开关组件进设计区。
保存源码至本地查看效果
<template>
<view class="container container329152">
<u-form-item class="diygw-col-24" label="开关" prop="switch">
<view class="flex diygw-col-24">
<u-switch :size="44" :activeValue="1" :inactiveValue="0" inactiveTextColor="#000000" activeTextColor="#ffffff" v-model="switched" slot="right"></u-switch>
</view>
</u-form-item>
<u-form-item class="diygw-col-24" label="开关" prop="switch1">
<view class="flex diygw-col-24">
<u-switch :size="44" activeText="有效" inactiveText="无效" :activeValue="1" :inactiveValue="0" inactiveTextColor="#000000" activeTextColor="#ffffff" v-model="switch1" slot="right"></u-switch>
</view>
</u-form-item>
<u-form-item class="diygw-col-24" label="开关" prop="switch2">
<view class="flex diygw-col-24">
<u-switch :size="44" activeText="男" inactiveText="女" :activeValue="1" :inactiveValue="0" inactiveTextColor="#000000" activeTextColor="#ffffff" v-model="switch2" slot="right"></u-switch>
</view>
</u-form-item>
<view class="clearfix"></view>
</view>
</template>
<script>
export default {
data() {
return {
//用户全局信息
userInfo: {},
//页面传参
globalOption: {},
//自定义全局变量
globalData: {},
listNum: 1,
list: {
code: 200,
msg: '获取数据成功',
data: [
{
title: '标题1',
remark: '描述1',
id: 1,
attr: {
title: '标题1'
},
img: 'https://php.diygw.com/logo.png'
},
{
title: '标题2',
remark: '描述2',
id: 2,
attr: {
title: '标题2'
},
img: 'https://php.diygw.com/logo.png'
},
{
title: '标题3',
remark: '描述3',
id: 3,
attr: {
title: '标题3'
},
img: 'https://php.diygw.com/logo.png'
},
{
title: '标题4',
remark: '描述4',
id: 4,
attr: {
title: '标题4'
},
img: 'https://php.diygw.com/logo.png'
},
{
title: '标题5',
remark: '描述5',
id: 5,
attr: {
title: '标题5'
},
img: 'https://php.diygw.com/logo.png'
},
{
title: '标题6',
remark: '描述6',
id: 6,
attr: {
title: '标题6'
},
img: 'https://php.diygw.com/logo.png'
},
{
title: '标题7',
remark: '描述7',
id: 7,
attr: {
title: '标题7'
},
img: 'https://php.diygw.com/logo.png'
},
{
title: '标题8',
remark: '描述8',
id: 8,
attr: {
title: '标题8'
},
img: 'https://php.diygw.com/logo.png'
},
{
title: '标题9',
remark: '描述9',
id: 9,
attr: {
title: '标题9'
},
img: 'https://php.diygw.com/logo.png'
},
{
title: '标题10',
remark: '描述10',
id: 10,
attr: {
title: '标题10'
},
img: 'https://php.diygw.com/logo.png'
}
]
},
switched: 1,
switch1: 1,
switch2: 1
};
},
onPageScroll(e) {
const scrollTop = e.scrollTop;
this.headerBackgroundStyle = this.headerBackgroundStyle || { background: 'none' };
if (scrollTop <= 80) {
const opacity = scrollTop / 100;
const color = `rgba(255, 255, 255, ${opacity})`;
this.headerBackgroundStyle.background = color;
} else {
this.headerBackgroundStyle.background = '#ffffff';
}
},
onShow() {
this.setCurrentPage(this);
},
onLoad(option) {
this.setCurrentPage(this);
if (option) {
this.setData({
globalOption: this.getOption(option)
});
}
this.init();
},
methods: {
async init() {
await this.listApi();
},
// 列表数据 API请求方法
async listApi(param) {
let thiz = this;
param = param || {};
//如果请求要重置页面,请配置点击附加参数refresh=1 增加判断如输入框回调param不是对象
if (param.refresh || typeof param != 'object') {
this.listNum = 1;
}
//请求地址及请求数据,可以在加载前执行上面增加自己的代码逻辑
let http_url = 'https://php.diygw.com/article.php';
let http_data = {
pageNum: this.listNum,
pageSize: 10,
sctdown: param.sctdown || this.sctdown
};
let http_header = {};
let list = await this.$http.post(http_url, http_data, http_header, 'json');
let datarows = list.rows;
if (http_data.pageNum == 1) {
this.list = list;
} else if (datarows) {
let rows = this.list.rows.concat(datarows);
list.rows = rows;
this.list = list;
}
if (datarows && datarows.length > 0) {
this.listNum = this.listNum + 1;
}
this.globalData.isshow = true;
console.log(http_data.sctdown);
}
},
onPullDownRefresh() {
// 列表数据 API请求方法
this.listNum = 1;
this.listApi();
uni.stopPullDownRefresh();
},
onReachBottom() {
// 列表数据 API请求方法
this.listApi();
}
};
</script>
<style lang="scss" scoped>
.container329152 {
}
</style>