switchBox.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <template>
  2. <div class="m-switch-wrap">
  3. <div @click="disabled ? e => e.preventDefault() : onSwitch()" :class="['m-switch', { 'switch-checked': checkedVal == activeValue, 'disabled': disabled }]">
  4. <div :class="['u-switch-inner', checkedVal == activeValue ? 'inner-checked' : 'inner-unchecked' ]">{{ checkedVal == activeValue ? checkedInfo : uncheckedInfo }}</div>
  5. <div :class="['u-node', { 'node-checked': checkedVal == activeValue }]"></div>
  6. </div>
  7. </div>
  8. </template>
  9. <script>
  10. export default {
  11. name: 'SwitchBox',
  12. model: {
  13. prop: 'checked',
  14. event: 'change'
  15. },
  16. props: {
  17. defaultChecked: { // 初始是否选中
  18. type: Boolean,
  19. default: false
  20. },
  21. checkedInfo: { // 选中时的内容
  22. type: [Number, String],
  23. default: null
  24. },
  25. uncheckedInfo: { // 未选中时的内容
  26. type: [Number, String],
  27. default: null
  28. },
  29. disabled: { // 是否禁用
  30. type: Boolean,
  31. default: false
  32. },
  33. checked: { // (v-model)指定当前是否选中
  34. type: [String,Boolean,Number],
  35. default: false
  36. },
  37. activeValue: { // 选中的值
  38. type: [String,Boolean,Number],
  39. default: true
  40. },
  41. inactiveValue: { // 不选中的值
  42. type: [String,Boolean,Number],
  43. default: false
  44. },
  45. },
  46. data () {
  47. return {
  48. checkedVal: null
  49. }
  50. },
  51. watch: {
  52. checked () {
  53. this.initSwitcher()
  54. },
  55. defaultChecked () {
  56. this.initSwitcher()
  57. }
  58. },
  59. created () {
  60. this.initSwitcher()
  61. },
  62. methods: {
  63. initSwitcher () {
  64. this.checkedVal = this.checked
  65. // if (typeof this.checked === 'boolean') {
  66. // this.checkedVal = this.checked
  67. // } else if (typeof this.checked === 'object') {
  68. // this.checkedVal = this.defaultChecked
  69. // }
  70. },
  71. onSwitch () {
  72. //this.checkedVal = !this.checkedVal
  73. //this.$emit('change', this.checkedVal)
  74. this.$emit('changeFun', this.checkedVal)
  75. }
  76. }
  77. }
  78. </script>
  79. <style lang="scss" scoped>
  80. .m-switch-wrap {
  81. height: 22px;
  82. min-width: 44px;
  83. display: inline-block;
  84. --themeColor: rgb(19, 206, 102);
  85. .m-switch {
  86. position: relative;
  87. height: 22px;
  88. color: rgba(0,0,0,.65);
  89. font-size: 14px;
  90. background: rgba(0,0,0,.25);
  91. border-radius: 100px;
  92. cursor: pointer;
  93. transition: background .36s;
  94. .u-switch-inner {
  95. display: inline-block;
  96. color: #fff;
  97. font-size: 14px;
  98. line-height: 22px;
  99. padding: 0 8px;
  100. transition: all .36s;
  101. }
  102. .inner-checked {
  103. margin-right: 18px;
  104. }
  105. .inner-unchecked {
  106. margin-left: 18px;
  107. }
  108. .u-node {
  109. position: absolute;
  110. top: 2px;
  111. left: 2px;
  112. width: 18px;
  113. height: 18px;
  114. background: #FFF;
  115. border-radius: 100%;
  116. cursor: pointer;
  117. transition: all .36s;
  118. }
  119. .node-checked { // 结果等价于right: 2px; 为了滑动效果都以左边为基准进行偏移
  120. left: 100%;
  121. margin-left: -2px;
  122. transform: translateX(-100%);
  123. }
  124. }
  125. .switch-checked {
  126. background: var(--themeColor);
  127. }
  128. .disabled {
  129. cursor: not-allowed;
  130. opacity: .4;
  131. }
  132. }
  133. </style>