84 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			84 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|   | // directives/collapse.js
 | |||
|  | export default { | |||
|  |     mounted(el, binding) { | |||
|  |         el._collapse = { | |||
|  |             duration: binding.arg ? parseInt(binding.arg) : 300, // 使用指令参数设置 duration
 | |||
|  |             expanded: binding.value, | |||
|  |         }; | |||
|  | 
 | |||
|  |         el.style.overflow = 'hidden'; | |||
|  |         el.style.transition = `height ${el._collapse.duration}ms ease, opacity ${el._collapse.duration}ms ease`; | |||
|  | 
 | |||
|  |         if (!binding.value) { | |||
|  |             el.style.height = '0px'; | |||
|  |             el.style.opacity = '0'; | |||
|  |         } else { | |||
|  |             setTimeout(() => { | |||
|  |                 getHeight(el).then((height) => { | |||
|  |                     el.style.height = height + 'px'; | |||
|  |                     el.style.opacity = '1'; | |||
|  |                 }); | |||
|  |             }, 0); | |||
|  |         } | |||
|  |     }, | |||
|  | 
 | |||
|  |     updated(el, binding) { | |||
|  |         const duration = el._collapse.duration; | |||
|  |         const isShow = binding.value; | |||
|  | 
 | |||
|  |         if (isShow === el._collapse.expanded) return; | |||
|  | 
 | |||
|  |         el._collapse.expanded = isShow; | |||
|  | 
 | |||
|  |         if (isShow) { | |||
|  |             getHeight(el).then((height) => { | |||
|  |                 el.style.transition = `none`; | |||
|  |                 el.style.height = '0px'; | |||
|  |                 el.style.opacity = '0'; | |||
|  | 
 | |||
|  |                 // 动画开始
 | |||
|  |                 requestAnimationFrame(() => { | |||
|  |                     el.style.transition = `height ${duration}ms ease, opacity ${duration}ms ease`; | |||
|  |                     el.style.height = height + 'px'; | |||
|  |                     el.style.opacity = '1'; | |||
|  | 
 | |||
|  |                     // 动画结束后设置为 auto(避免内容变化导致高度错误)
 | |||
|  |                     setTimeout(() => { | |||
|  |                         el.style.height = 'auto'; | |||
|  |                     }, duration); | |||
|  |                 }); | |||
|  |             }); | |||
|  |         } else { | |||
|  |             getHeight(el).then((height) => { | |||
|  |                 console.log(height) | |||
|  |                 el.style.height = height + 'px'; | |||
|  |                 el.style.opacity = '1'; | |||
|  | 
 | |||
|  |                 requestAnimationFrame(() => { | |||
|  |                     el.style.height = '0px'; | |||
|  |                     el.style.opacity = '0'; | |||
|  |                 }); | |||
|  |             }); | |||
|  |         } | |||
|  |     }, | |||
|  | 
 | |||
|  |     unmounted(el) { | |||
|  |         delete el._collapse; | |||
|  |     }, | |||
|  | }; | |||
|  | 
 | |||
|  | // 获取元素高度(兼容 H5 和小程序)
 | |||
|  | function getHeight(el) { | |||
|  |     return new Promise((resolve) => { | |||
|  |         // #ifdef H5
 | |||
|  |         resolve(el.scrollHeight); | |||
|  |         // #endif
 | |||
|  | 
 | |||
|  |         // #ifndef H5
 | |||
|  |         const query = uni.createSelectorQuery(); | |||
|  |         query.select(el).boundingClientRect((res) => { | |||
|  |             resolve(res?.height || 0); | |||
|  |         }).exec(); | |||
|  |         // #endif
 | |||
|  |     }); | |||
|  | } |