|                                                                                                                                                                                                                                                  |  | <template>	<view class="uv-drop-down-popup">		<uv-transition :show="show" mode="fade" :duration="300" :custom-style="overlayStyle" @click="clickOverlay">			<view class="uv-dp__container" ref="uvDPContainer" :style="{height: `${height}px`}" @click.stop="blockClick">				<view class="uv-dp__container__list" ref="uvDPList">					<slot>						<view class="uv-dp__container__list--item" v-for="(item,index) in list" :key="index" @click="clickHandler(item,index)" :style="[itemCustomStyle(index)]">							<uv-text :text="item[keyName]" :size="getTextSize(index)" :color="getTextColor(index)"></uv-text>						</view>					</slot>				</view>			</view>		</uv-transition>	</view></template><script>	import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js';	import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js';	// #ifdef APP-NVUE
	const animation = uni.requireNativePlugin('animation');	const dom = uni.requireNativePlugin('dom');	// #endif
	/**	 * DropDownPopup 下拉框	 * @description 下拉筛选框	 * @tutorial https://ext.dcloud.net.cn/plugin?name=uv-drop-down
	 * @property {String | Number} name 字段标识	 * @property {String | Number} zIndex 弹出层的层级	 * @property {String | Number} opacity 遮罩层的透明度	 * @property {Boolean} clickOverlayOnClose 是否允许点击遮罩层关闭弹窗	 * @property {Object} currentDropItem 当前下拉筛选菜单对象	 * @property {String} keyName 指定从当前下拉筛选菜单对象元素中读取哪个属性作为文本展示	 */	export default {		name: 'uv-drop-down-popup',		mixins: [mpMixin, mixin],		props: {			sign: {				type: [String, Number],				default: 'UVDROPDOWN'			},			zIndex: {				type: [Number, String],				default: 999			},			opacity: {				type: [Number, String],				default: 0.5			},			clickOverlayOnClose: {				type: Boolean,				default: true			},			// 当前下拉选项对象
			currentDropItem: {				type: Object,				default () {					return {						activeIndex: 0,						child: []					}				}			},			keyName: {				type: String,				default: 'label'			}		},		data() {			return {				show: false,				rect: {},				height: 0			}		},		computed: {			overlayStyle() {				let { height = 0, top = 0 } = this.rect;				// #ifdef H5
				top += this.$uv.sys().windowTop;				// #endif
				const style = {					position: 'fixed',					top: `${top+height}px`,					left: 0,					right: 0,					zIndex: this.zIndex,					bottom: 0,					'background-color': `rgba(0, 0, 0, ${this.opacity})`				}				return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))			},			list() {				try {					return Array.isArray(this.currentDropItem.child) ? this.currentDropItem.child : [];				} catch (e) {					return [];				}			},			getTextColor(index) {				return index => {					const active = this.currentDropItem.activeIndex == index;					const color = this.currentDropItem.color;					const activeColor = this.currentDropItem.activeColor;					if (active) {						return activeColor ? activeColor : '#3c9cff';					}					return color ? color : '#333';				}			},			getTextSize(index) {				return index => {					const active = this.currentDropItem.activeIndex == index;					const size = this.currentDropItem.size;					const activeSize = this.currentDropItem.activeSize;					if (active) {						return activeSize ? activeSize : '30rpx';					}					return size ? size : '30rpx';				}			},			itemCustomStyle() {				return index => {					const active = this.currentDropItem.activeIndex == index;					const style = {};					if (active && this.currentDropItem.itemActiveCustomStyle) {						return this.$uv.deepMerge(style, this.$uv.addStyle(this.currentDropItem.itemActiveCustomStyle));					}					if (this.currentDropItem.itemCustomStyle) {						return this.$uv.deepMerge(style, this.$uv.addStyle(this.currentDropItem.itemCustomStyle))					}					return style;				}			}		},		created() {			this.init();		},		methods: {			blockClick() {},			clickHandler(item, index) {				this.currentDropItem.activeIndex = index;				this.$emit('clickItem', item);				this.close();			},			init() {				uni.$off(`${this.sign}_GETRECT`);				uni.$on(`${this.sign}_GETRECT`, rect => {					this.rect = rect;				})				uni.$off(`${this.sign}_CLICKMENU`);				uni.$on(`${this.sign}_CLICKMENU`, async res => {					if (res.show) {						this.open();					} else {						this.close();					}				})			},			open() {				this.show = true;				this.$nextTick(async () => {					// #ifndef H5 || MP-WEIXIN
					await this.$uv.sleep(60);					// #endif
					const res = await this.queryRect();					// #ifndef APP-NVUE
					this.height = res.height;					// #endif
					// #ifdef APP-NVUE
					this.animation(res.height);					// #endif
					this.$emit('popupChange', { show: true });				})			},			close() {				if(!this.show) return;				this.height = 0;				// #ifndef APP-NVUE
				this.height = 0;				// #endif
				// #ifdef APP-NVUE
				this.animation(0);				// #endif
				this.show = false;				uni.$emit(`${this.sign}_CLOSEPOPUP`);				this.$emit('popupChange', { show: false });			},			clickOverlay() {				if (this.clickOverlayOnClose) {					this.close();				}			},			// 查询内容高度
			queryRect() {				// #ifndef APP-NVUE
				// 组件内部一般用this.$uvGetRect,对外的为getRect,二者功能一致,名称不同
				return new Promise(resolve => {					this.$uvGetRect(`.uv-dp__container__list`).then(size => {						resolve(size)					})				})				// #endif
				// #ifdef APP-NVUE
				// nvue下,使用dom模块查询元素高度
				// 返回一个promise,让调用此方法的主体能使用then回调
				return new Promise(resolve => {					dom.getComponentRect(this.$refs.uvDPList, res => {						resolve(res.size)					})				})				// #endif
			},			// nvue下设置高度
			animation(height, duration = 200) {				// #ifdef APP-NVUE
				const ref = this.$refs['uvDPContainer'];				animation.transition(ref, {					styles: {						height: `${height}px`					},					duration				})				// #endif
			}		}	}</script><style scoped lang="scss">	.uv-dp__container {		/* #ifndef APP-NVUE */		overflow: hidden;		transition: all .15s;		/* #endif */		background-color: #fff;	}	.uv-dp__container__list {		&--item {			padding: 20rpx 60rpx;		}	}</style>
 |