mySwitch.vue 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. <template>
  2. <view class="switchbox" :style="{background: value ? activeColor:inactiveColor}" @tap="change">
  3. <view :class="value ? 'switchbar checked-shadow':'switchbar checked-noshadow'"
  4. :style="{transform: value ?`translate(32rpx,-50%)`:`translate(4rpx,-50%)`}"></view>
  5. </view>
  6. </template>
  7. <script>
  8. export default {
  9. name: "mySwitch",
  10. props: {
  11. // 通过v-model双向绑定的值
  12. value: {
  13. type: [Boolean, String, Number],
  14. default: false
  15. },
  16. // switch打开时的值
  17. activeValue: {
  18. type: [String, Number, Boolean],
  19. default: true
  20. },
  21. // switch关闭时的值
  22. inactiveValue: {
  23. type: [String, Number, Boolean],
  24. default: false
  25. },
  26. // 打开时的背景色
  27. activeColor: {
  28. type: String,
  29. default: "#FF7700"
  30. },
  31. // 关闭时的背景色
  32. inactiveColor: {
  33. type: String,
  34. default: "#E9E9EA"
  35. }
  36. },
  37. data() {
  38. return {
  39. }
  40. },
  41. computed: {
  42. isActive(){
  43. return this.value === this.activeValue;
  44. }
  45. },
  46. watch: {
  47. value: {
  48. immediate: true,
  49. handler(n) {
  50. if(n !== this.inactiveValue && n !== this.activeValue) {
  51. console.error("('v-model绑定的值必须为inactiveValue、activeValue二者之一')")
  52. }
  53. }
  54. }
  55. },
  56. methods: {
  57. change() {
  58. const oldValue = this.isActive ? this.inactiveValue : this.activeValue
  59. // 放到下一个生命周期,因为双向绑定的value修改父组件状态需要时间,且是异步的
  60. this.$nextTick(() => {
  61. this.$emit('change', oldValue)
  62. })
  63. }
  64. }
  65. }
  66. </script>
  67. <style lang="scss" scoped>
  68. .switchbox {
  69. flex-shrink: 0;
  70. width: 76rpx;
  71. height: 48rpx;
  72. border-radius: 40rpx;
  73. position: relative;
  74. .switchbar {
  75. width: 40rpx;
  76. height: 40rpx;
  77. background: #FFFFFF;
  78. border-radius: 50%;
  79. position: absolute;
  80. left: 4rpx;
  81. top: 50%;
  82. transition: transform 0.3s;
  83. }
  84. .checked-shadow {
  85. box-shadow: -2rpx 2rpx 8rpx 0rpx rgba(233,84,3,0.7);
  86. }
  87. .checked-noshadow {
  88. box-shadow: 2rpx 0rpx 8rpx 0rpx rgba(204,204,204,0.7);
  89. }
  90. }
  91. </style>