You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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