index.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import baseComponent from '../helpers/baseComponent'
  2. import classNames from '../helpers/libs/classNames'
  3. import eventsMixin from '../helpers/mixins/eventsMixin'
  4. import styleToCssString from '../helpers/libs/styleToCssString'
  5. import { useRect } from '../helpers/hooks/useDOM'
  6. import { nativeTextareaProps } from './props'
  7. const defaultEvents = {
  8. onChange() {},
  9. onFocus() {},
  10. onBlur() {},
  11. onConfirm() {},
  12. onClear() {},
  13. onError() {},
  14. onLineChange() {},
  15. }
  16. baseComponent({
  17. behaviors: [eventsMixin({ defaultEvents })],
  18. relations: {
  19. '../field/index': {
  20. type: 'ancestor',
  21. },
  22. },
  23. properties: {
  24. ...nativeTextareaProps,
  25. prefixCls: {
  26. type: String,
  27. value: 'wux-textarea',
  28. },
  29. label: {
  30. type: String,
  31. value: '',
  32. },
  33. extra: {
  34. type: String,
  35. value: '',
  36. },
  37. defaultValue: {
  38. type: String,
  39. value: '',
  40. },
  41. value: {
  42. type: String,
  43. value: '',
  44. observer(newVal) {
  45. if (this.data.controlled) {
  46. this.updated(newVal)
  47. }
  48. },
  49. },
  50. controlled: {
  51. type: Boolean,
  52. value: false,
  53. },
  54. disabled: {
  55. type: Boolean,
  56. value: false,
  57. },
  58. readOnly: {
  59. type: Boolean,
  60. value: false,
  61. },
  62. rows: {
  63. type: Number,
  64. value: 1,
  65. observer: 'updateHeight',
  66. },
  67. hasCount: {
  68. type: Boolean,
  69. value: false,
  70. },
  71. clear: {
  72. type: Boolean,
  73. value: false,
  74. },
  75. error: {
  76. type: Boolean,
  77. value: false,
  78. },
  79. },
  80. data: {
  81. inputValue: '',
  82. inputFocus: false,
  83. inputRows: 1,
  84. inputHeight: '',
  85. internalPlaceholderStyle: '',
  86. },
  87. observers: {
  88. placeholderStyle(placeholderStyle) {
  89. this.setInternalPlaceholderStyle(placeholderStyle)
  90. },
  91. },
  92. computed: {
  93. classes: ['prefixCls, disabled, readOnly, inputFocus, error, hasCount', function(prefixCls, disabled, readOnly, inputFocus, hasError, hasCount) {
  94. const wrap = classNames(prefixCls, {
  95. [`${prefixCls}--focus`]: inputFocus,
  96. [`${prefixCls}--disabled`]: disabled,
  97. [`${prefixCls}--readonly`]: readOnly,
  98. [`${prefixCls}--error`]: hasError,
  99. [`${prefixCls}--has-count`]: hasCount,
  100. })
  101. const label = `${prefixCls}__label`
  102. const control = `${prefixCls}__control`
  103. const item = `${prefixCls}__item`
  104. const clear = `${prefixCls}__clear`
  105. const error = `${prefixCls}__error`
  106. const extra = `${prefixCls}__extra`
  107. const count = `${prefixCls}__count`
  108. const current = `${prefixCls}__current`
  109. const keyboardAccessory = `${prefixCls}__keyboard-accessory`
  110. return {
  111. wrap,
  112. label,
  113. control,
  114. item,
  115. clear,
  116. error,
  117. extra,
  118. count,
  119. current,
  120. keyboardAccessory,
  121. }
  122. }],
  123. },
  124. methods: {
  125. setInternalPlaceholderStyle(placeholderStyle) {
  126. const internalPlaceholderStyle = styleToCssString(placeholderStyle)
  127. if (this.data.internalPlaceholderStyle !== internalPlaceholderStyle) {
  128. this.setData({
  129. internalPlaceholderStyle,
  130. })
  131. }
  132. },
  133. updateHeight(val = this.data.rows) {
  134. // rows 取值为大于或等于 1 的正整数
  135. const rows = Math.max(1, parseInt(val))
  136. const { prefixCls, inputRows } = this.data
  137. if (inputRows !== rows) {
  138. useRect(`.${prefixCls}__item`, this)
  139. .then((rect) => {
  140. if (rect) {
  141. const lineHeight = inputRows > 1 ? rect.height / inputRows : rect.height
  142. const inputHeight = lineHeight * rows
  143. this.setData({
  144. inputRows: rows,
  145. inputHeight,
  146. })
  147. }
  148. })
  149. }
  150. },
  151. updated(inputValue) {
  152. if (this.hasFieldDecorator) return
  153. if (this.data.inputValue !== inputValue) {
  154. this.setData({ inputValue })
  155. }
  156. },
  157. onChange(e) {
  158. const { value } = e.detail
  159. if (!this.data.controlled) {
  160. this.updated(value)
  161. }
  162. this.triggerEvent('change', e.detail)
  163. },
  164. onFocus(e) {
  165. this.clearTimer()
  166. this.setData({
  167. inputFocus: true,
  168. })
  169. this.triggerEvent('focus', e.detail)
  170. },
  171. onBlur(e) {
  172. this.setTimer()
  173. this.triggerEvent('blur', e.detail)
  174. },
  175. onConfirm(e) {
  176. this.triggerEvent('confirm', e.detail)
  177. },
  178. onKeyboardHeightChange(e) {
  179. this.triggerEvent('keyboardheightchange', e.detail)
  180. },
  181. onClear(e) {
  182. const params = { value: '' }
  183. if (!this.data.controlled) {
  184. this.updated(params.value)
  185. }
  186. this.triggerEvent('change', params)
  187. this.triggerEvent('clear', params)
  188. },
  189. onError() {
  190. const { inputValue: value } = this.data
  191. this.triggerEvent('error', { value })
  192. },
  193. onLineChange(e) {
  194. this.triggerEvent('linechange', e.detail)
  195. },
  196. setTimer() {
  197. this.clearTimer()
  198. this.timeout = setTimeout(() => {
  199. this.setData({
  200. inputFocus: false,
  201. })
  202. }, 200)
  203. },
  204. clearTimer() {
  205. if (this.timeout) {
  206. clearTimeout(this.timeout)
  207. this.timeout = null
  208. }
  209. },
  210. },
  211. attached() {
  212. const { defaultValue, value, controlled, placeholderStyle } = this.data
  213. const inputValue = controlled ? value : defaultValue
  214. this.updated(inputValue)
  215. this.setInternalPlaceholderStyle(placeholderStyle)
  216. },
  217. ready() {
  218. this.updateHeight()
  219. },
  220. })