f5cf3b1f5dafba929be1a919378672329a4f1ef0.svn-base 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. const vueSticky = {}
  2. let listenAction
  3. vueSticky.install = Vue => {
  4. Vue.directive('sticky', {
  5. inserted(el, binding) {
  6. const params = binding.value || {}
  7. const stickyTop = params.stickyTop || 0
  8. const zIndex = params.zIndex || 1000
  9. const elStyle = el.style
  10. elStyle.position = '-webkit-sticky'
  11. elStyle.position = 'sticky'
  12. // if the browser support css sticky(Currently Safari, Firefox and Chrome Canary)
  13. // if (~elStyle.position.indexOf('sticky')) {
  14. // elStyle.top = `${stickyTop}px`;
  15. // elStyle.zIndex = zIndex;
  16. // return
  17. // }
  18. const elHeight = el.getBoundingClientRect().height
  19. const elWidth = el.getBoundingClientRect().width
  20. elStyle.cssText = `top: ${stickyTop}px; z-index: ${zIndex}`
  21. const parentElm = el.parentNode || document.documentElement
  22. const placeholder = document.createElement('div')
  23. placeholder.style.display = 'none'
  24. placeholder.style.width = `${elWidth}px`
  25. placeholder.style.height = `${elHeight}px`
  26. parentElm.insertBefore(placeholder, el)
  27. let active = false
  28. const getScroll = (target, top) => {
  29. const prop = top ? 'pageYOffset' : 'pageXOffset'
  30. const method = top ? 'scrollTop' : 'scrollLeft'
  31. let ret = target[prop]
  32. if (typeof ret !== 'number') {
  33. ret = window.document.documentElement[method]
  34. }
  35. return ret
  36. }
  37. const sticky = () => {
  38. if (active) {
  39. return
  40. }
  41. if (!elStyle.height) {
  42. elStyle.height = `${el.offsetHeight}px`
  43. }
  44. elStyle.position = 'fixed'
  45. elStyle.width = `${elWidth}px`
  46. placeholder.style.display = 'inline-block'
  47. active = true
  48. }
  49. const reset = () => {
  50. if (!active) {
  51. return
  52. }
  53. elStyle.position = ''
  54. placeholder.style.display = 'none'
  55. active = false
  56. }
  57. const check = () => {
  58. const scrollTop = getScroll(window, true)
  59. const offsetTop = el.getBoundingClientRect().top
  60. if (offsetTop < stickyTop) {
  61. sticky()
  62. } else {
  63. if (scrollTop < elHeight + stickyTop) {
  64. reset()
  65. }
  66. }
  67. }
  68. listenAction = () => {
  69. check()
  70. }
  71. window.addEventListener('scroll', listenAction)
  72. },
  73. unbind() {
  74. window.removeEventListener('scroll', listenAction)
  75. }
  76. })
  77. }
  78. export default vueSticky