option.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <template>
  2. <li
  3. @mouseenter="hoverItem"
  4. @click.stop="selectOptionClick"
  5. class="el-select-dropdown__item"
  6. v-show="visible"
  7. :class="{
  8. 'selected': itemSelected,
  9. 'is-disabled': disabled || groupDisabled || limitReached,
  10. 'hover': parent.hoverIndex === index
  11. }">
  12. <slot>
  13. <span>{{ currentLabel }}</span>
  14. </slot>
  15. </li>
  16. </template>
  17. <script type="text/babel">
  18. import Emitter from 'element-ui/src/mixins/emitter';
  19. export default {
  20. mixins: [Emitter],
  21. name: 'ElOption',
  22. componentName: 'ElOption',
  23. props: {
  24. value: {
  25. required: true
  26. },
  27. label: [String, Number],
  28. selected: {
  29. type: Boolean,
  30. default: false
  31. },
  32. created: Boolean,
  33. disabled: {
  34. type: Boolean,
  35. default: false
  36. }
  37. },
  38. data() {
  39. return {
  40. index: -1,
  41. groupDisabled: false,
  42. visible: true,
  43. hitState: false
  44. };
  45. },
  46. computed: {
  47. currentLabel() {
  48. return this.label || ((typeof this.value === 'string' || typeof this.value === 'number') ? this.value : '');
  49. },
  50. currentValue() {
  51. return this.value || this.label || '';
  52. },
  53. parent() {
  54. let result = this.$parent;
  55. while (!result.isSelect) {
  56. result = result.$parent;
  57. }
  58. return result;
  59. },
  60. itemSelected() {
  61. if (!this.parent.multiple) {
  62. return this.value === this.parent.value;
  63. } else {
  64. return this.parent.value.indexOf(this.value) > -1;
  65. }
  66. },
  67. limitReached() {
  68. if (this.parent.multiple) {
  69. return !this.itemSelected &&
  70. this.parent.value.length >= this.parent.multipleLimit &&
  71. this.parent.multipleLimit > 0;
  72. } else {
  73. return false;
  74. }
  75. }
  76. },
  77. watch: {
  78. currentLabel() {
  79. if (!this.created) this.dispatch('ElSelect', 'setSelected');
  80. },
  81. value() {
  82. if (!this.created) this.dispatch('ElSelect', 'setSelected');
  83. }
  84. },
  85. methods: {
  86. handleGroupDisabled(val) {
  87. this.groupDisabled = val;
  88. },
  89. hoverItem() {
  90. if (!this.disabled && !this.groupDisabled) {
  91. this.parent.hoverIndex = this.parent.options.indexOf(this);
  92. }
  93. },
  94. selectOptionClick() {
  95. if (this.disabled !== true && this.groupDisabled !== true) {
  96. this.dispatch('ElSelect', 'handleOptionClick', this);
  97. }
  98. },
  99. queryChange(query) {
  100. // query 里如果有正则中的特殊字符,需要先将这些字符转义
  101. let parsedQuery = query.replace(/(\^|\(|\)|\[|\]|\$|\*|\+|\.|\?|\\|\{|\}|\|)/g, '\\$1');
  102. this.visible = new RegExp(parsedQuery, 'i').test(this.currentLabel) || this.created;
  103. if (!this.visible) {
  104. this.parent.filteredOptionsCount--;
  105. }
  106. },
  107. resetIndex() {
  108. this.$nextTick(() => {
  109. this.index = this.parent.options.indexOf(this);
  110. });
  111. }
  112. },
  113. created() {
  114. this.parent.options.push(this);
  115. this.parent.cachedOptions.push(this);
  116. this.parent.optionsCount++;
  117. this.parent.filteredOptionsCount++;
  118. this.index = this.parent.options.indexOf(this);
  119. this.$on('queryChange', this.queryChange);
  120. this.$on('handleGroupDisabled', this.handleGroupDisabled);
  121. this.$on('resetIndex', this.resetIndex);
  122. },
  123. beforeDestroy() {
  124. this.dispatch('ElSelect', 'onOptionDestroy', this);
  125. }
  126. };
  127. </script>