123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- <template>
- <view
- class="u-switch"
- :class="[valueCom == true ? 'u-switch--on' : '', disabled ? 'u-switch--disabled' : '']"
- @tap="onClick"
- :style="[switchStyle]"
- >
- <view
- class="u-switch__node node-class"
- :style="{
- width: $u.addUnit(size),
- height: $u.addUnit(size)
- }"
- >
- <u-loading
- :show="loading"
- class="u-switch__loading"
- :size="size * 0.6"
- :color="loadingColor"
- />
- </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 打开时的背景色(默认#2979ff)
- * @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: Boolean,
- default: false
- },
- modelValue: {
- type: Boolean,
- default: false
- },
- // 是否为加载中状态
- loading: {
- type: Boolean,
- default: false
- },
- // 是否为禁用装填
- disabled: {
- type: Boolean,
- default: false
- },
- // 开关尺寸,单位rpx
- size: {
- type: [Number, String],
- default: 50
- },
- // 打开时的背景颜色
- activeColor: {
- type: String,
- default: "#2979ff"
- },
- // 关闭时的背景颜色
- 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
- }
- },
- data() {
- return {};
- },
- computed: {
- valueCom() {
- // #ifdef VUE2
- 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;
- return style;
- },
- loadingColor() {
- return this.valueCom ? this.activeColor : null;
- }
- },
- methods: {
- onClick() {
- if (!this.disabled && !this.loading) {
- // 使手机产生短促震动,微信小程序有效,APP(HX 2.6.8)和H5无效
- if (this.vibrateShort) uni.vibrateShort();
- this.$emit("input", !this.valueCom);
- this.$emit("update:modelValue", !this.valueCom);
- // 放到下一个生命周期,因为双向绑定的value修改父组件状态需要时间,且是异步的
- this.$nextTick(() => {
- this.$emit("change", this.valueCom ? this.activeValue : this.inactiveValue);
- });
- }
- }
- }
- };
- </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;
- }
- .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>
|