lazy-image.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import {
  2. inBrowser,
  3. loadImageAsync,
  4. noop
  5. } from './util'
  6. import Lazy from './lazy'
  7. const LazyImage = (lazyManager) => {
  8. return {
  9. props: {
  10. src: [String, Object],
  11. tag: {
  12. type: String,
  13. default: 'img'
  14. }
  15. },
  16. render (h) {
  17. return h(this.tag, {
  18. attrs: {
  19. src: this.renderSrc
  20. }
  21. }, this.$slots.default)
  22. },
  23. data () {
  24. return {
  25. el: null,
  26. options: {
  27. src: '',
  28. error: '',
  29. loading: '',
  30. attempt: lazyManager.options.attempt
  31. },
  32. state: {
  33. loaded: false,
  34. error: false,
  35. attempt: 0
  36. },
  37. rect: {},
  38. renderSrc: ''
  39. }
  40. },
  41. watch: {
  42. src () {
  43. this.init()
  44. lazyManager.addLazyBox(this)
  45. lazyManager.lazyLoadHandler()
  46. }
  47. },
  48. created () {
  49. this.init()
  50. this.renderSrc = this.options.loading
  51. },
  52. mounted () {
  53. this.el = this.$el
  54. lazyManager.addLazyBox(this)
  55. lazyManager.lazyLoadHandler()
  56. },
  57. beforeDestroy () {
  58. lazyManager.removeComponent(this)
  59. },
  60. methods: {
  61. init () {
  62. const { src, loading, error } = lazyManager._valueFormatter(this.src)
  63. this.state.loaded = false
  64. this.options.src = src
  65. this.options.error = error
  66. this.options.loading = loading
  67. this.renderSrc = this.options.loading
  68. },
  69. getRect () {
  70. this.rect = this.$el.getBoundingClientRect()
  71. },
  72. checkInView () {
  73. this.getRect()
  74. return inBrowser &&
  75. (this.rect.top < window.innerHeight * lazyManager.options.preLoad && this.rect.bottom > 0) &&
  76. (this.rect.left < window.innerWidth * lazyManager.options.preLoad && this.rect.right > 0)
  77. },
  78. load (onFinish = noop) {
  79. if ((this.state.attempt > this.options.attempt - 1) && this.state.error) {
  80. if (!lazyManager.options.silent) console.log(`VueLazyload log: ${this.options.src} tried too more than ${this.options.attempt} times`)
  81. onFinish()
  82. return
  83. }
  84. const src = this.options.src
  85. loadImageAsync({ src }, ({ src }) => {
  86. this.renderSrc = src
  87. this.state.loaded = true
  88. }, e => {
  89. this.state.attempt++
  90. this.renderSrc = this.options.error
  91. this.state.error = true
  92. })
  93. }
  94. }
  95. }
  96. }
  97. LazyImage.install = (Vue, options = {}) => {
  98. const LazyClass = Lazy(Vue)
  99. const lazy = new LazyClass(options)
  100. Vue.component('lazy-image', LazyImage(lazy))
  101. }
  102. export default LazyImage