index.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <script>
  2. export default {
  3. name: 'AutoImage',
  4. props: {
  5. src: {
  6. type: String,
  7. default: null
  8. },
  9. placeholder: {
  10. type: String,
  11. default: null
  12. },
  13. broken: {
  14. type: String,
  15. default: 'image-broken'
  16. },
  17. retry: {
  18. type: [Boolean, String],
  19. default: false
  20. }
  21. },
  22. data () {
  23. return {
  24. status: 0
  25. }
  26. },
  27. watch: {
  28. src: {
  29. handler (val) {
  30. if (val) {
  31. this.load()
  32. } else {
  33. this.setStatus()
  34. }
  35. },
  36. immediate: true
  37. }
  38. },
  39. beforeDestroy () {
  40. this.setStatus()
  41. },
  42. methods: {
  43. load () {
  44. this.setStatus(1)
  45. const img = new Image()
  46. img.onload = () => {
  47. this.setStatus(2)
  48. }
  49. img.onerror = () => {
  50. this.setStatus(3)
  51. }
  52. this.$img = img
  53. img.src = this.src
  54. },
  55. setStatus (status = 0) {
  56. if (this.$img) {
  57. this.$img.onload = null
  58. this.$img.onerror = null
  59. this.$img = null
  60. }
  61. this.status = status
  62. },
  63. createPlacehoder (h, val) {
  64. return h('div', {
  65. staticClass: 'l-flex--row center o-error-image'
  66. }, [
  67. this.createSvgIcon(h, val)
  68. ])
  69. },
  70. createSvgIcon (h, icon) {
  71. return h('svg-icon', {
  72. staticClass: 'o-error-image__img',
  73. props: {
  74. 'icon-class': icon
  75. }
  76. })
  77. }
  78. },
  79. render (h) {
  80. switch (this.status) {
  81. case 1:
  82. return h('div', {
  83. staticClass: 'l-flex--row center o-error-image'
  84. }, [
  85. h('i', {
  86. staticClass: 'el-icon-loading'
  87. })
  88. ])
  89. case 2:
  90. return h('img', {
  91. staticClass: 'o-image',
  92. attrs: {
  93. src: this.src
  94. }
  95. })
  96. case 3:
  97. return this.retry
  98. ? h('div', {
  99. staticClass: 'o-error-image retry',
  100. on: {
  101. click: $event => {
  102. $event.stopPropagation()
  103. this.load()
  104. }
  105. }
  106. }, [
  107. this.createSvgIcon(h, this.broken),
  108. h('i', {
  109. staticClass: 'o-error-image__refresh el-icon-refresh'
  110. })
  111. ])
  112. : this.createPlacehoder(h, this.broken)
  113. default:
  114. return this.placeholder ? this.createPlacehoder(h, this.placeholder) : null
  115. }
  116. }
  117. }
  118. </script>
  119. <style lang="scss" scoped>
  120. .o-image {
  121. object-fit: contain;
  122. }
  123. .o-error-image {
  124. position: relative;
  125. overflow: hidden;
  126. &__img {
  127. width: 100%;
  128. height: 100%;
  129. }
  130. &.retry:hover {
  131. border-radius: $radius;
  132. cursor: pointer;
  133. &::before {
  134. content: "";
  135. position: absolute;
  136. top: 0;
  137. left: 0;
  138. right: 0;
  139. bottom: 0;
  140. background-color: rgba(#000, 0.5);
  141. }
  142. .o-error-image__refresh {
  143. display: inline-block;
  144. }
  145. }
  146. &__refresh {
  147. display: none;
  148. position: absolute;
  149. top: 50%;
  150. left: 50%;
  151. color: #fff;
  152. transform: translate(-50%, -50%);
  153. }
  154. }
  155. </style>