index.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. <template>
  2. <view :class="classes">
  3. <textarea
  4. class="nut-textarea__textarea"
  5. :style="styles"
  6. :rows="rows"
  7. :disabled="disabled"
  8. :readonly="readonly"
  9. :value="modelValue"
  10. @input="change"
  11. @blur="blur"
  12. @focus="focus"
  13. :maxlength="maxLength"
  14. :placeholder="placeholder"
  15. />
  16. <view class="nut-textarea__limit" v-if="limitShow"> {{ modelValue ? modelValue.length : 0 }}/{{ maxLength }}</view>
  17. </view>
  18. </template>
  19. <script lang="ts">
  20. import { computed, watch } from 'vue';
  21. import { createComponent } from '../../utils/create';
  22. const { componentName, create } = createComponent('textarea');
  23. export default create({
  24. props: {
  25. modelValue: {
  26. type: [String, Number],
  27. default: ''
  28. },
  29. textAlign: {
  30. type: String,
  31. default: 'left'
  32. },
  33. limitShow: {
  34. type: Boolean,
  35. default: false
  36. },
  37. maxLength: {
  38. type: [String, Number],
  39. default: ''
  40. },
  41. rows: {
  42. type: [String, Number],
  43. default: ''
  44. },
  45. placeholder: {
  46. type: String,
  47. default: '请输入内容'
  48. },
  49. readonly: {
  50. type: Boolean,
  51. default: false
  52. },
  53. disabled: {
  54. type: Boolean,
  55. default: false
  56. },
  57. autosize: {
  58. type: Boolean,
  59. default: false
  60. }
  61. },
  62. emits: ['update:modelValue', 'change', 'blur', 'focus'],
  63. setup(props, { emit }) {
  64. const classes = computed(() => {
  65. const prefixCls = componentName;
  66. return {
  67. [prefixCls]: true,
  68. [`${prefixCls}--disabled`]: props.disabled
  69. };
  70. });
  71. const styles = computed(() => {
  72. return {
  73. textAlign: props.textAlign,
  74. resize: props.autosize ? 'vertical' : 'none'
  75. };
  76. });
  77. const emitChange = (value: string, event: Event) => {
  78. if (props.maxLength && value.length > Number(props.maxLength)) {
  79. value = value.substring(0, Number(props.maxLength));
  80. }
  81. emit('update:modelValue', value, event);
  82. emit('change', value, event);
  83. };
  84. const change = (event: Event) => {
  85. const input = event.target as HTMLInputElement;
  86. emitChange(input.value, event);
  87. };
  88. const focus = (event: Event) => {
  89. if (props.disabled) return;
  90. if (props.readonly) return;
  91. emit('focus', event);
  92. };
  93. const blur = (event: Event) => {
  94. if (props.disabled) return;
  95. if (props.readonly) return;
  96. const input = event.target as HTMLInputElement;
  97. let value = input.value;
  98. emitChange(value, event);
  99. emit('blur', { value, event });
  100. };
  101. return {
  102. classes,
  103. styles,
  104. change,
  105. focus,
  106. blur
  107. };
  108. }
  109. });
  110. </script>