index.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import baseComponent from '../helpers/baseComponent'
  2. import classNames from '../helpers/libs/classNames'
  3. const EMPTY = 'empty'
  4. const LOADING = 'loading'
  5. const LOADED = 'loaded'
  6. const ERROR = 'error'
  7. const UNMOUNTED = 'unmounted'
  8. const calcStyle = (value) => typeof value === 'number' ? `${value}px` : value
  9. baseComponent({
  10. properties: {
  11. prefixCls: {
  12. type: String,
  13. value: 'wux-image',
  14. },
  15. src: {
  16. type: String,
  17. value: '',
  18. },
  19. mode: {
  20. type: String,
  21. value: 'scaleToFill',
  22. },
  23. webp: {
  24. type: Boolean,
  25. value: false,
  26. },
  27. lazyLoad: {
  28. type: Boolean,
  29. value: false,
  30. },
  31. showMenuByLongpress: {
  32. type: Boolean,
  33. value: false,
  34. },
  35. shape: {
  36. type: String,
  37. value: 'normal',
  38. },
  39. width: {
  40. type: null,
  41. value: 300,
  42. },
  43. height: {
  44. type: null,
  45. value: 225,
  46. },
  47. unmountOnEmpty: {
  48. type: Boolean,
  49. value: false,
  50. },
  51. unmountOnError: {
  52. type: Boolean,
  53. value: false,
  54. },
  55. empty: {
  56. type: String,
  57. value: '',
  58. },
  59. loading: {
  60. type: String,
  61. value: '',
  62. },
  63. error: {
  64. type: String,
  65. value: '',
  66. },
  67. },
  68. data: {
  69. status: '',
  70. },
  71. computed: {
  72. classes: ['prefixCls, shape, mode, status, empty, loading, error', function(prefixCls, shape, mode, status, empty, loading, error) {
  73. const wrap = classNames(prefixCls, {
  74. [`${prefixCls}--${shape}`]: shape,
  75. [`${prefixCls}--${mode}`]: mode,
  76. [`${prefixCls}--${status}`]: status,
  77. })
  78. const inner = `${prefixCls}__inner`
  79. const thumb = `${prefixCls}__thumb`
  80. const mask = classNames(`${prefixCls}__mask`, {
  81. [`${prefixCls}__mask--text`]: empty || loading || error,
  82. })
  83. const text = `${prefixCls}__text`
  84. return {
  85. wrap,
  86. inner,
  87. thumb,
  88. mask,
  89. text,
  90. }
  91. }],
  92. },
  93. observers: {
  94. src(newVal) {
  95. this.updated(newVal)
  96. },
  97. ['width, height'](...args) {
  98. this.updateStyle(...args)
  99. },
  100. },
  101. methods: {
  102. /**
  103. * 更新资源地址
  104. */
  105. updated(src) {
  106. this.updateStatus(!!src ? LOADING : this.data.unmountOnEmpty ? UNMOUNTED : EMPTY)
  107. },
  108. /**
  109. * 更新组件样式
  110. */
  111. updateStyle(width, height) {
  112. const style = `width: ${calcStyle(width)}; height: ${calcStyle(height)}`
  113. this.setData({
  114. style,
  115. })
  116. },
  117. /**
  118. * 更新组件状态
  119. */
  120. updateStatus(status) {
  121. if (this.data.status !== status) {
  122. this.setData({
  123. status,
  124. })
  125. }
  126. this.triggerEvent('change', { status })
  127. },
  128. /**
  129. * 资源加载完成时的回调函数
  130. */
  131. onLoad(e) {
  132. this.updateStatus(LOADED)
  133. this.triggerEvent('load', { ...e.detail, status: LOADED })
  134. },
  135. /**
  136. * 资源加载失败时的回调函数
  137. */
  138. onError(e) {
  139. const status = this.data.unmountOnError ? UNMOUNTED : ERROR
  140. this.updateStatus(status)
  141. this.triggerEvent('error', { ...e.detail, status })
  142. },
  143. /**
  144. * 点击事件
  145. */
  146. onTap(e) {
  147. this.triggerEvent('click', { ...e.detail, status: this.data.status })
  148. },
  149. },
  150. attached() {
  151. const { width, height, src } = this.data
  152. this.updateStyle(width, height)
  153. this.updated(src)
  154. },
  155. })