index.taro.vue 2.8 KB

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