e6e0c2917da7a87a9952e2ff8d2c491741f6c7bfa86a59c955e791515082614a2f14e5b55f6da891dd3202a8af844b81f47e157d01d526a11696344cc99d44 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <template>
  2. <label
  3. class="el-checkbox"
  4. :class="[
  5. border && checkboxSize ? 'el-checkbox--' + checkboxSize : '',
  6. { 'is-disabled': isDisabled },
  7. { 'is-bordered': border },
  8. { 'is-checked': isChecked }
  9. ]"
  10. :id="id"
  11. >
  12. <span class="el-checkbox__input"
  13. :class="{
  14. 'is-disabled': isDisabled,
  15. 'is-checked': isChecked,
  16. 'is-indeterminate': indeterminate,
  17. 'is-focus': focus
  18. }"
  19. :tabindex="indeterminate ? 0 : false"
  20. :role="indeterminate ? 'checkbox' : false"
  21. :aria-checked="indeterminate ? 'mixed' : false"
  22. >
  23. <span class="el-checkbox__inner"></span>
  24. <input
  25. v-if="trueLabel || falseLabel"
  26. class="el-checkbox__original"
  27. type="checkbox"
  28. :aria-hidden="indeterminate ? 'true' : 'false'"
  29. :name="name"
  30. :disabled="isDisabled"
  31. :true-value="trueLabel"
  32. :false-value="falseLabel"
  33. v-model="model"
  34. @change="handleChange"
  35. @focus="focus = true"
  36. @blur="focus = false">
  37. <input
  38. v-else
  39. class="el-checkbox__original"
  40. type="checkbox"
  41. :aria-hidden="indeterminate ? 'true' : 'false'"
  42. :disabled="isDisabled"
  43. :value="label"
  44. :name="name"
  45. v-model="model"
  46. @change="handleChange"
  47. @focus="focus = true"
  48. @blur="focus = false">
  49. </span>
  50. <span class="el-checkbox__label" v-if="$slots.default || label">
  51. <slot></slot>
  52. <template v-if="!$slots.default">{{label}}</template>
  53. </span>
  54. </label>
  55. </template>
  56. <script>
  57. import Emitter from 'element-ui/src/mixins/emitter';
  58. export default {
  59. name: 'ElCheckbox',
  60. mixins: [Emitter],
  61. inject: {
  62. elForm: {
  63. default: ''
  64. },
  65. elFormItem: {
  66. default: ''
  67. }
  68. },
  69. componentName: 'ElCheckbox',
  70. data() {
  71. return {
  72. selfModel: false,
  73. focus: false,
  74. isLimitExceeded: false
  75. };
  76. },
  77. computed: {
  78. model: {
  79. get() {
  80. return this.isGroup
  81. ? this.store : this.value !== undefined
  82. ? this.value : this.selfModel;
  83. },
  84. set(val) {
  85. if (this.isGroup) {
  86. this.isLimitExceeded = false;
  87. (this._checkboxGroup.min !== undefined &&
  88. val.length < this._checkboxGroup.min &&
  89. (this.isLimitExceeded = true));
  90. (this._checkboxGroup.max !== undefined &&
  91. val.length > this._checkboxGroup.max &&
  92. (this.isLimitExceeded = true));
  93. this.isLimitExceeded === false &&
  94. this.dispatch('ElCheckboxGroup', 'input', [val]);
  95. } else {
  96. this.$emit('input', val);
  97. this.selfModel = val;
  98. }
  99. }
  100. },
  101. isChecked() {
  102. if ({}.toString.call(this.model) === '[object Boolean]') {
  103. return this.model;
  104. } else if (Array.isArray(this.model)) {
  105. return this.model.indexOf(this.label) > -1;
  106. } else if (this.model !== null && this.model !== undefined) {
  107. return this.model === this.trueLabel;
  108. }
  109. },
  110. isGroup() {
  111. let parent = this.$parent;
  112. while (parent) {
  113. if (parent.$options.componentName !== 'ElCheckboxGroup') {
  114. parent = parent.$parent;
  115. } else {
  116. this._checkboxGroup = parent;
  117. return true;
  118. }
  119. }
  120. return false;
  121. },
  122. store() {
  123. return this._checkboxGroup ? this._checkboxGroup.value : this.value;
  124. },
  125. /* used to make the isDisabled judgment under max/min props */
  126. isLimitDisabled() {
  127. const { max, min } = this._checkboxGroup;
  128. return !!(max || min) &&
  129. (this.model.length >= max && !this.isChecked) ||
  130. (this.model.length <= min && this.isChecked);
  131. },
  132. isDisabled() {
  133. return this.isGroup
  134. ? this._checkboxGroup.disabled || this.disabled || (this.elForm || {}).disabled || this.isLimitDisabled
  135. : this.disabled || (this.elForm || {}).disabled;
  136. },
  137. _elFormItemSize() {
  138. return (this.elFormItem || {}).elFormItemSize;
  139. },
  140. checkboxSize() {
  141. const temCheckboxSize = this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
  142. return this.isGroup
  143. ? this._checkboxGroup.checkboxGroupSize || temCheckboxSize
  144. : temCheckboxSize;
  145. }
  146. },
  147. props: {
  148. value: {},
  149. label: {},
  150. indeterminate: Boolean,
  151. disabled: Boolean,
  152. checked: Boolean,
  153. name: String,
  154. trueLabel: [String, Number],
  155. falseLabel: [String, Number],
  156. id: String, /* 当indeterminate为真时,为controls提供相关连的checkbox的id,表明元素间的控制关系*/
  157. controls: String, /* 当indeterminate为真时,为controls提供相关连的checkbox的id,表明元素间的控制关系*/
  158. border: Boolean,
  159. size: String
  160. },
  161. methods: {
  162. addToStore() {
  163. if (
  164. Array.isArray(this.model) &&
  165. this.model.indexOf(this.label) === -1
  166. ) {
  167. this.model.push(this.label);
  168. } else {
  169. this.model = this.trueLabel || true;
  170. }
  171. },
  172. handleChange(ev) {
  173. if (this.isLimitExceeded) return;
  174. let value;
  175. if (ev.target.checked) {
  176. value = this.trueLabel === undefined ? true : this.trueLabel;
  177. } else {
  178. value = this.falseLabel === undefined ? false : this.falseLabel;
  179. }
  180. this.$emit('change', value, ev);
  181. this.$nextTick(() => {
  182. if (this.isGroup) {
  183. this.dispatch('ElCheckboxGroup', 'change', [this._checkboxGroup.value]);
  184. }
  185. });
  186. }
  187. },
  188. created() {
  189. this.checked && this.addToStore();
  190. },
  191. mounted() { // 为indeterminate元素 添加aria-controls 属性
  192. if (this.indeterminate) {
  193. this.$el.setAttribute('aria-controls', this.controls);
  194. }
  195. },
  196. watch: {
  197. value(value) {
  198. this.dispatch('ElFormItem', 'el.form.change', value);
  199. }
  200. }
  201. };
  202. </script>