u-checkbox.vue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. <template>
  2. <view class="u-checkbox" :style="[checkboxStyle]">
  3. <view class="u-checkbox__icon-wrap" @tap="toggle">
  4. <u-icon :class="iconClass" name="checkbox-mark" :size="iconSize" :color="iconColor" class="u-checkbox__icon" :style="[iconStyle]" />
  5. </view>
  6. <view class="u-label-class u-checkbox__label" @tap="onClickLabel" :style="{
  7. fontSize: labelSize + 'rpx'
  8. }">
  9. <slot />
  10. </view>
  11. </view>
  12. </template>
  13. <script>
  14. /**
  15. * checkbox 复选框
  16. * @description 该组件需要搭配checkboxGroup组件使用,以便用户进行操作时,获得当前复选框组的选中情况。
  17. * @tutorial https://www.uviewui.com/components/checkbox.html
  18. * @property {String Number} icon-size 图标大小,单位rpx(默认24)
  19. * @property {String Number} label-size label字体大小,单位rpx(默认28)
  20. * @property {String Number} name checkbox组件的标示符
  21. * @property {String} shape 形状,见官网说明(默认circle)
  22. * @property {Boolean} disabled 是否禁用(默认false)
  23. * @property {Boolean} label-disabled 点击文本是否可以操作checkbox(默认true)
  24. * @property {String} active-color 选中时的颜色,如设置CheckboxGroup的active-color将失效
  25. * @event {Function} change 某个checkbox状态发生变化时触发,回调为一个对象
  26. * @example <u-checkbox v-model="checked" :disabled="false">天涯</u-checkbox>
  27. */
  28. export default {
  29. name: "u-checkbox",
  30. props: {
  31. // checkbox的名称
  32. name: {
  33. type: [String, Number],
  34. default: ''
  35. },
  36. // 形状,square为方形,circle为原型
  37. shape: {
  38. type: String,
  39. default: 'square'
  40. },
  41. // 是否为选中状态
  42. value: {
  43. type: Boolean,
  44. default: false
  45. },
  46. // 是否禁用
  47. disabled: {
  48. type: Boolean,
  49. default: false
  50. },
  51. // 是否禁止点击提示语选中复选框
  52. labelDisabled: {
  53. type: Boolean,
  54. default: false
  55. },
  56. // 选中状态下的颜色,如设置此值,将会覆盖checkboxGroup的activeColor值
  57. activeColor: {
  58. type: String,
  59. default: ''
  60. },
  61. // 图标的大小,单位rpx
  62. iconSize: {
  63. type: [String, Number],
  64. default: 20
  65. },
  66. // label的字体大小,rpx单位
  67. labelSize: {
  68. type: [String, Number],
  69. default: 28
  70. },
  71. // 组件的整体大小
  72. size: {
  73. type: [String, Number],
  74. default: 34
  75. },
  76. },
  77. inject: {
  78. checkboxGroup: {
  79. // 添加默认值,是为了能让u-checkbox组件无需u-checkbox-group组件嵌套时单独使用
  80. default() {
  81. return {
  82. disabled: false,
  83. children: [],
  84. size: 34,
  85. activeColor: '#2979ff',
  86. max: 999999,
  87. emitEvent: () => {},
  88. width: '',
  89. wrap: false
  90. }
  91. }
  92. }
  93. },
  94. data() {
  95. return {
  96. parentDisabled: false,
  97. };
  98. },
  99. created() {
  100. this.parentDisabled = this.checkboxGroup.disabled;
  101. this.checkboxGroup.children.push(this);
  102. },
  103. computed: {
  104. iconStyle() {
  105. let style = {};
  106. if (this.checkboxActiveColor && this.value && !this.disabled && !this.parentDisabled) {
  107. style.borderColor = this.checkboxActiveColor;
  108. style.backgroundColor = this.checkboxActiveColor;
  109. }
  110. style.width = this.checkboxGroup.size + 'rpx';
  111. style.height = this.checkboxGroup.size + 'rpx';
  112. return style;
  113. },
  114. iconColor() {
  115. return this.value ? '#ffffff' : 'transparent';
  116. },
  117. iconClass() {
  118. let classs = [];
  119. classs.push('u-checkbox__icon--' + this.shape);
  120. if (this.value == true) classs.push('u-checkbox__icon--checked');
  121. if (this.disabled || this.parentDisabled) classs.push('u-checkbox__icon--disabled');
  122. if (this.value && (this.disabled || this.parentDisabled)) classs.push('u-checkbox__icon--disabled--checked');
  123. return classs;
  124. },
  125. // 激活的颜色,可能受checkboxGroup和本组件的activeColor影响
  126. // 本组件的activeColor值优先
  127. checkboxActiveColor() {
  128. return this.activeColor ? this.activeColor : this.checkboxGroup.activeColor;
  129. },
  130. checkboxStyle() {
  131. let style = {};
  132. if(this.checkboxGroup.width) {
  133. style.width = this.checkboxGroup.width;
  134. // #ifdef MP
  135. // 各家小程序因为它们特殊的编译结构,使用float布局
  136. style.float = 'left';
  137. // #endif
  138. // #ifndef MP
  139. // H5和APP使用flex布局
  140. style.flex = `0 0 ${this.checkboxGroup.width}`;
  141. // #endif
  142. }
  143. if(this.checkboxGroup.wrap) {
  144. style.width = '100%';
  145. // #ifndef MP
  146. // H5和APP使用flex布局,将宽度设置100%,即可自动换行
  147. style.flex = '0 0 100%';
  148. // #endif
  149. }
  150. return style;
  151. }
  152. },
  153. methods: {
  154. onClickLabel() {
  155. if (!this.disabled && !this.labelDisabled && !this.parentDisabled) {
  156. this.setValue();
  157. }
  158. },
  159. toggle() {
  160. if (!this.disabled && !this.parentDisabled) {
  161. this.setValue();
  162. }
  163. },
  164. emitEvent() {
  165. this.$emit('change', {
  166. value: this.value,
  167. name: this.name
  168. })
  169. this.checkboxGroup.emitEvent();
  170. },
  171. // 设置input的值,这里通过input事件,设置通过v-model绑定的组件的值
  172. setValue() {
  173. // 判断是否超过了可选的最大数量
  174. let checkedNum = 0;
  175. this.checkboxGroup.children.map(val => {
  176. if (val.value) checkedNum++;
  177. })
  178. // 如果原来为选中状态,那么可以取消
  179. if (this.value == true) {
  180. this.$emit('input', !this.value);
  181. // 等待下一个周期再执行,因为this.$emit('input')作用于父组件,再反馈到子组件内部,需要时间
  182. this.$nextTick(function() {
  183. this.emitEvent();
  184. })
  185. } else if (checkedNum < this.checkboxGroup.max && this.value == false) {
  186. // 如果原来为未选中状态,需要选中的数量少于父组件中设置的max值,才可以选中
  187. this.$emit('input', !this.value);
  188. // 等待下一个周期再执行,因为this.$emit('input')作用于父组件,再反馈到子组件内部,需要时间
  189. this.$nextTick(function() {
  190. this.emitEvent();
  191. })
  192. }
  193. }
  194. }
  195. };
  196. </script>
  197. <style lang="scss" scoped>
  198. .u-checkbox {
  199. display: -webkit-flex;
  200. display: flex;
  201. -webkit-align-items: center;
  202. align-items: center;
  203. overflow: hidden;
  204. -webkit-user-select: none;
  205. user-select: none;
  206. line-height: 1.8;
  207. }
  208. .u-checkbox__icon-wrap,
  209. .u-checkbox__label {
  210. color: $u-content-color;
  211. }
  212. .u-checkbox__icon-wrap {
  213. -webkit-flex: none;
  214. flex: none;
  215. }
  216. .u-checkbox__icon {
  217. display: -webkit-flex;
  218. display: flex;
  219. -webkit-align-items: center;
  220. align-items: center;
  221. -webkit-justify-content: center;
  222. justify-content: center;
  223. box-sizing: border-box;
  224. width: 42rpx;
  225. height: 42rpx;
  226. color: transparent;
  227. text-align: center;
  228. transition-property: color, border-color, background-color;
  229. font-size: 20px;
  230. border: 1px solid #c8c9cc;
  231. transition-duration: 0.2s;
  232. }
  233. .u-checkbox__icon--circle {
  234. border-radius: 100%;
  235. }
  236. .u-checkbox__icon--square {
  237. border-radius: 3px;
  238. }
  239. .u-checkbox__icon--checked {
  240. color: #fff;
  241. background-color: #2979ff;
  242. border-color: #2979ff;
  243. }
  244. .u-checkbox__icon--disabled {
  245. background-color: #ebedf0;
  246. border-color: #c8c9cc;
  247. }
  248. .u-checkbox__icon--disabled--checked {
  249. color: #c8c9cc !important;
  250. }
  251. .u-checkbox__label {
  252. word-wrap: break-word;
  253. margin-left: 10rpx;
  254. margin-right: 24rpx;
  255. color: $u-content-color;
  256. font-size: 30rpx;
  257. }
  258. .u-checkbox__label--disabled {
  259. color: #c8c9cc;
  260. }
  261. .u-checkbox__label:empty {
  262. margin: 0;
  263. }
  264. </style>