四零语境前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
3.6 KiB

  1. export default {
  2. install(Vue) {
  3. Vue.prototype.$scrollTo = function(el, behavior = 'smooth', retryCount = 0) {
  4. if (!el) {
  5. console.warn('scrollTo: 元素参数为空')
  6. return
  7. }
  8. const maxRetries = 3
  9. const retryDelay = 100 // 100ms
  10. let targetEL = typeof el === 'string' ? this.$refs[el] : el
  11. console.log(`scrollTo called with: ${el} (尝试次数: ${retryCount + 1})`)
  12. console.log('原始targetEL:', targetEL)
  13. // 如果targetEL为undefined且还有重试次数,则延迟重试
  14. if (!targetEL && retryCount < maxRetries) {
  15. console.log(`元素未找到,${retryDelay}ms后重试...`)
  16. setTimeout(() => {
  17. this.$scrollTo(el, behavior, retryCount + 1)
  18. }, retryDelay)
  19. return
  20. }
  21. // 如果重试次数用完仍未找到元素,输出详细信息
  22. if (!targetEL) {
  23. console.error(`scrollTo: 经过${maxRetries + 1}次尝试仍未找到元素 "${el}"`)
  24. console.log('当前可用的refs:', Object.keys(this.$refs))
  25. return
  26. }
  27. // 如果targetEL是数组,取第一个元素
  28. if (Array.isArray(targetEL) && targetEL.length > 0) {
  29. targetEL = targetEL[0]
  30. console.log('检测到数组,取第一个元素:', targetEL)
  31. } else if (Array.isArray(targetEL) && targetEL.length === 0) {
  32. console.error('scrollTo: 找到的是空数组')
  33. return
  34. }
  35. if (targetEL) {
  36. // #ifdef H5
  37. console.log('进h5环境的滚动插件了');
  38. console.log('targetEL类型:', typeof targetEL);
  39. console.log('targetEL是否有$el属性:', !!targetEL.$el);
  40. console.log('targetEL是否有scrollIntoView方法:', !!targetEL.scrollIntoView);
  41. try {
  42. // H5环境下使用原生的scrollIntoView方法
  43. if (targetEL.$el) {
  44. // 如果是Vue组件(uni-app的view等组件),获取其DOM元素
  45. console.log('检测到uni-app Vue组件,使用$el获取DOM元素');
  46. console.log('DOM元素:', targetEL.$el);
  47. targetEL.$el.scrollIntoView({
  48. behavior: behavior,
  49. block: 'start',
  50. inline: 'nearest'
  51. })
  52. console.log('✅ 滚动成功')
  53. } else if (targetEL.scrollIntoView) {
  54. console.log('检测到原生DOM元素');
  55. // 如果是原生DOM元素
  56. targetEL.scrollIntoView({
  57. behavior: behavior,
  58. block: 'start',
  59. inline: 'nearest'
  60. })
  61. console.log('✅ 滚动成功')
  62. } else {
  63. console.log('无法识别的元素类型,尝试其他方法');
  64. // 如果都不是,可能需要其他处理方式
  65. }
  66. } catch (error) {
  67. console.error('scrollTo 执行失败:', error)
  68. }
  69. // #endif
  70. // #ifndef H5
  71. // 非H5环境(小程序等)使用uni.pageScrollTo
  72. const query = uni.createSelectorQuery().in(this)
  73. query.select(`[ref="${el}"]`).boundingClientRect((data) => {
  74. console.log('element position:', data)
  75. if (data) {
  76. uni.pageScrollTo({
  77. scrollTop: data.top,
  78. duration: behavior === 'smooth' ? 300 : 0
  79. })
  80. console.log('✅ 滚动成功')
  81. } else {
  82. console.error('scrollTo: 未找到元素位置信息')
  83. }
  84. }).exec()
  85. // #endif
  86. }
  87. }
  88. }
  89. }
  90. // 使用方式
  91. // 在 main.js 中引入:Vue.use(require('./plugins/scrollTo'))
  92. // 然后在组件中:this.$scrollTo('targetRef')