u-switch.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <template>
  2. <view class="u-switch" :class="[value == true ? 'u-switch--on' : '', disabled ? 'u-switch--disabled' : '']" @tap="onClick"
  3. :style="[switchStyle]">
  4. <view class="u-switch__node node-class" :style="{
  5. width: $u.addUnit(this.size),
  6. height: $u.addUnit(this.size)
  7. }">
  8. <u-loading :show="loading" class="u-switch__loading" :size="size * 0.6" :color="loadingColor" />
  9. </view>
  10. <text :style="value==false?'padding-left:50rpx':'padding-left: 8rpx;'" style="font-size: 20rpx;">{{value==true?'离职':'入职'}}</text>
  11. </view>
  12. </template>
  13. <script>
  14. /**
  15. * switch 开关选择器
  16. * @description 选择开关一般用于只有两个选择,且只能选其一的场景。
  17. * @tutorial https://www.uviewui.com/components/switch.html
  18. * @property {Boolean} loading 是否处于加载中(默认false)
  19. * @property {Boolean} disabled 是否禁用(默认false)
  20. * @property {String Number} size 开关尺寸,单位rpx(默认50)
  21. * @property {String} active-color 打开时的背景色(默认#2979ff)
  22. * @property {Boolean} inactive-color 关闭时的背景色(默认#ffffff)
  23. * @property {Boolean | Number | String} active-value 打开选择器时通过change事件发出的值(默认true)
  24. * @property {Boolean | Number | String} inactive-value 关闭选择器时通过change事件发出的值(默认false)
  25. * @event {Function} change 在switch打开或关闭时触发
  26. * @example <u-switch v-model="checked" active-color="red" inactive-color="#eee"></u-switch>
  27. */
  28. export default {
  29. name: "u-switch",
  30. props: {
  31. // 是否为加载中状态
  32. loading: {
  33. type: Boolean,
  34. default: false
  35. },
  36. // 是否为禁用装填
  37. disabled: {
  38. type: Boolean,
  39. default: false
  40. },
  41. // 开关尺寸,单位rpx
  42. size: {
  43. type: [Number, String],
  44. default: 50
  45. },
  46. // 打开时的背景颜色
  47. activeColor: {
  48. type: String,
  49. default: '#2979ff'
  50. },
  51. // 关闭时的背景颜色
  52. inactiveColor: {
  53. type: String,
  54. default: '#ffffff'
  55. },
  56. // 通过v-model双向绑定的值
  57. value: {
  58. type: Boolean,
  59. default: false
  60. },
  61. // 是否使手机发生短促震动,目前只在iOS的微信小程序有效(2020-05-06)
  62. vibrateShort: {
  63. type: Boolean,
  64. default: false
  65. },
  66. // 打开选择器时的值
  67. activeValue: {
  68. type: [Number, String, Boolean],
  69. default: true
  70. },
  71. // 关闭选择器时的值
  72. inactiveValue: {
  73. type: [Number, String, Boolean],
  74. default: false
  75. },
  76. },
  77. data() {
  78. return {
  79. }
  80. },
  81. computed: {
  82. switchStyle() {
  83. let style = {};
  84. style.fontSize = this.size + 'rpx';
  85. style.backgroundColor = this.value ? this.activeColor : this.inactiveColor;
  86. return style;
  87. },
  88. loadingColor() {
  89. return this.value ? this.activeColor : null;
  90. }
  91. },
  92. methods: {
  93. onClick() {
  94. if (!this.disabled && !this.loading) {
  95. // 使手机产生短促震动,微信小程序有效,APP(HX 2.6.8)和H5无效
  96. if(this.vibrateShort) uni.vibrateShort();
  97. this.$emit('input', !this.value);
  98. // 放到下一个生命周期,因为双向绑定的value修改父组件状态需要时间,且是异步的
  99. this.$nextTick(() => {
  100. this.$emit('change', this.value ? this.activeValue : this.inactiveValue);
  101. })
  102. }
  103. }
  104. }
  105. };
  106. </script>
  107. <style lang="scss" scoped>
  108. @import "../../libs/css/style.components.scss";
  109. .u-switch {
  110. position: relative;
  111. /* #ifndef APP-NVUE */
  112. display: inline-block;
  113. /* #endif */
  114. box-sizing: initial;
  115. width: 2em;
  116. height: 1em;
  117. background-color: #fff;
  118. border: 1px solid rgba(0, 0, 0, 0.1);
  119. border-radius: 1em;
  120. transition: background-color 0.3s;
  121. font-size: 50rpx;
  122. display: flex;
  123. align-items: center;
  124. color: #ffffff;
  125. }
  126. .u-switch__node {
  127. @include vue-flex;
  128. align-items: center;
  129. justify-content: center;
  130. position: absolute;
  131. top: 0;
  132. left: 0;
  133. border-radius: 100%;
  134. z-index: 1;
  135. background-color: #fff;
  136. background-color: #fff;
  137. 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);
  138. 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);
  139. transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
  140. 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);
  141. transition: transform cubic-bezier(0.3, 1.05, 0.4, 1.05);
  142. transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05)
  143. }
  144. .u-switch__loading {
  145. @include vue-flex;
  146. align-items: center;
  147. justify-content: center;
  148. }
  149. .u-switch--on {
  150. background-color: #1989fa;
  151. }
  152. .u-switch--on .u-switch__node {
  153. transform: translateX(100%);
  154. }
  155. .u-switch--disabled {
  156. opacity: 0.4;
  157. }
  158. </style>