<template>
	<!-- #ifdef APP-NVUE -->
	<list
		class="v-list"
		:enableBackToTop="enableBackToTop"
		:loadmoreoffset="lowerThreshold"
		:showScrollbar="showScrollbar"
		:style="[listStyle]"
		:offset-accuracy="Number(offsetAccuracy)"
		@scroll="onScroll"
		@loadmore="scrolltolower"
	>
		<slot />
	</list>
	<!-- #endif -->
	<!-- #ifndef APP-NVUE -->
	<scroll-view
		class="v-list"
		:scroll-into-view="scrollIntoView"
		:style="[listStyle]"
		:scroll-y="scrollable"
		:scroll-top="Number(scrollTop)"
		:lower-threshold="Number(lowerThreshold)"
		:upper-threshold="Number(upperThreshold)"
		:show-scrollbar="showScrollbar"
		:enable-back-to-top="enableBackToTop"
		:scroll-with-animation="scrollWithAnimation"
		@scroll="onScroll"
		@scrolltolower="scrolltolower"
		@scrolltoupper="scrolltoupper"
	>
		<view>
			<slot />
		</view>
	</scroll-view>
	<!-- #endif -->
</template>

<script>
import props from "./props.js";
import mpMixin from "../../libs/mixin/mpMixin.js";
import mixin from "../../libs/mixin/mixin.js";
// #ifdef APP-NVUE
const dom = uni.requireNativePlugin("dom");
// #endif
/**
 * List 列表
 * @description 该组件为高性能列表组件
 * @property {Boolean}			showScrollbar		控制是否出现滚动条，仅nvue有效 （默认 false ）
 * @property {String ｜ Number}	lowerThreshold		距底部多少时触发scrolltolower事件 （默认 50 ）
 * @property {String ｜ Number}	upperThreshold		距顶部多少时触发scrolltoupper事件，非nvue有效 （默认 0 ）
 * @property {String ｜ Number}	scrollTop			设置竖向滚动条位置（默认 0 ）
 * @property {String ｜ Number}	offsetAccuracy		控制 onscroll 事件触发的频率，仅nvue有效（默认 10 ）
 * @property {Boolean}			enableFlex			启用 flexbox 布局。开启后，当前节点声明了display: flex就会成为flex container，并作用于其孩子节点，仅微信小程序有效（默认 false ）
 * @property {Boolean}			pagingEnabled		是否按分页模式显示List，（默认 false ）
 * @property {Boolean}			scrollable			是否允许List滚动（默认 true ）
 * @property {String}			scrollIntoView		值应为某子元素id（id不能以数字开头）
 * @property {Boolean}			scrollWithAnimation	在设置滚动条位置时使用动画过渡 （默认 false ）
 * @property {Boolean}			enableBackToTop		iOS点击顶部状态栏、安卓双击标题栏时，滚动条返回顶部，只对微信小程序有效 （默认 false ）
 * @property {String ｜ Number}	height				列表的高度 （默认 0 ）
 * @property {String ｜ Number}	width				列表宽度 （默认 0 ）
 * @property {String ｜ Number}	preLoadScreen		列表前后预渲染的屏数，1代表一个屏幕的高度，1.5代表1个半屏幕高度  （默认 1 ）
 * @property {Object}			customStyle			定义需要用到的外部样式
 *
 * @example <v-list @scrolltolower="scrolltolower"></v-list>
 */
export default {
	name: "v-list",
	mixins: [mpMixin, mixin, props],
	watch: {
		scrollIntoView(n) {
			this.scrollIntoViewById(n);
		},
	},
	data() {
		return {
			// 记录内部滚动的距离
			innerScrollTop: 0,
			// vue下，scroll-view在上拉加载时的偏移值
			offset: 0,
			sys: uni.$u.sys(),
		};
	},
	computed: {
		listStyle() {
			const style = {},
				addUnit = uni.$u.addUnit;
			if (this.width != 0) style.width = addUnit(this.width);
			if (this.height != 0) style.height = addUnit(this.height);
			// 如果没有定义列表高度，则默认使用屏幕高度
			if (!style.height)
				style.height = addUnit(this.sys.windowHeight, "px");
			return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle));
		},
	},
	provide() {
		return {
			uList: this,
		};
	},
	created() {
		this.refs = [];
		this.children = [];
		this.anchors = [];
	},
	mounted() {},
	emits: ["scroll", "scrolltolower", "scrolltoupper"],
	methods: {
		updateOffsetFromChild(top) {
			this.offset = top;
		},
		onScroll(e) {
			let scrollTop = 0;
			// #ifdef APP-NVUE
			scrollTop = e.contentOffset.y;
			// #endif
			// #ifndef APP-NVUE
			scrollTop = e.detail.scrollTop;
			// #endif
			this.innerScrollTop = scrollTop;
			this.$emit("scroll", Math.abs(scrollTop));
		},
		scrollIntoViewById(id) {
			// #ifdef APP-NVUE
			// 根据id参数，找到所有v-list-item中匹配的节点，再通过dom模块滚动到对应的位置
			const item = this.refs.find((item) =>
				item.$refs[id] ? true : false
			);
			dom.scrollToElement(item.$refs[id], {
				// 是否需要滚动动画
				animated: this.scrollWithAnimation,
			});
			// #endif
		},
		// 滚动到底部触发事件
		scrolltolower(e) {
			uni.$u.sleep(30).then(() => {
				this.$emit("scrolltolower");
			});
		},
		// #ifndef APP-NVUE
		// 滚动到底部时触发，非nvue有效
		scrolltoupper(e) {
			uni.$u.sleep(30).then(() => {
				this.$emit("scrolltoupper");
				// 这一句很重要，能绝对保证在性功能障碍的webview，滚动条到顶时，取消偏移值，让页面置顶
				this.offset = 0;
			});
		},
		// #endif
	},
};
</script>

<style lang="scss" scoped>
@import "../../libs/css/components.scss";

.v-list {
	@include flex(column);
}
</style>
