tui-skeleton

tui-skeleton 骨架屏,数据请求时常见到锁屏的loading动画,而现在越来越多的产品倾向于使用Skeleton Screen替代 。

组件结构

<view class="tui-skeleton-cmomon tui-skeleton-box" :style="{width: winWidth+'px', height:winHeight+'px', backgroundColor:backgroundColor}">
	<view class="tui-skeleton-cmomon" v-for="(item,index) in skeletonElements" :key="index" :style="{width: item.width+'px', height:item.height+'px', left: item.left+'px', top: item.top+'px',backgroundColor: skeletonBgColor,borderRadius:getRadius(item.skeletonType,borderRadius)}"></view>
	<view class="tui-loading" :class="[getLoadingType(loadingType)]" v-if="isLoading"></view>
</view>

组件脚本

<script>
	export default {
		name: "tuiSkeleton",
		props: {
			//选择器(外层容器)
			selector: {
				type: String,
				default: "tui-skeleton"
			},
			//外层容器背景颜色
			backgroundColor: {
				type: String,
				default: "#fff"
			},
			//骨架元素背景颜色
			skeletonBgColor: {
				type: String,
				default: "#e9e9e9"
			},
			//骨架元素类型:矩形,圆形,带圆角矩形["rect","circular","fillet"]
			//默认所有,根据页面情况进行传值
			//页面对应元素class为:tui-skeleton-rect,tui-skeleton-circular,tui-skeleton-fillet
			//如果传入的值不在下列数组中,则为自定义class值,默认按矩形渲染
			skeletonType: {
				type: Array,
				default () {
					return ["rect", "circular", "fillet"]
				}
			},
			//圆角值,skeletonType=fillet时生效
			borderRadius: {
				type: String,
				default: "16rpx"
			},
			//骨架屏预生成数据:提前生成好的数据,当传入该属性值时,则不会再次查找子节点信息
			preloadData: {
				type: Array,
				default () {
					return []
				}
			},
			//是否需要loading
			isLoading: {
				type: Boolean,
				default: true
			},
			//loading类型[1-10]
			loadingType: {
				type: Number,
				default: 1
			}
		},
		created() {
			const res = uni.getSystemInfoSync();
			this.winWidth = res.windowWidth;
			this.winHeight = res.windowHeight;
			//如果有预生成数据,则直接使用
			this.isPreload(true)
		},
		// #ifdef H5
		mounted() {
			this.$nextTick(() => {
				this.nodesRef(`.${this.selector}`).then((res) => {
					this.winHeight = res[0].height + Math.abs(res[0].top)
				});
				!this.isPreload() && this.selectorQuery()
			})
	
		},
		// #endif
		onReady() {
			this.nodesRef(`.${this.selector}`).then((res) => {
				this.winHeight = res[0].height + Math.abs(res[0].top)
			});
			!this.isPreload() && this.selectorQuery()
		},
		data() {
			return {
				winWidth: 375,
				winHeight: 800,
				skeletonElements: []
			};
		},
		methods: {
			getLoadingType: function(type) {
				let value = 1
				if (type && type > 0 && type < 11) {
					value = type
				}
				return 'tui-loading-' + value
			},
			getRadius: function(type, val) {
				let radius = "0"
				if (type == "circular") {
					radius = "50%"
				} else if (type == "fillet") {
					radius = val
				}
				return radius;
			},
			isPreload(init) {
				let preloadData = this.preloadData || []
				if (preloadData.length) {
					init && (this.skeletonElements = preloadData)
					return true
				}
				return false
			},
			async selectorQuery() {
				let skeletonType = this.skeletonType || []
				let nodes = []
				for (let item of skeletonType) {
					let className = `.${this.selector} >>> .${item}`
					// #ifdef H5
					className = `.${item}`
					// #endif
					if (~"rect_circular_fillet".indexOf(item)) {
						// #ifndef H5
						className = `.${this.selector} >>> .${this.selector}-${item}`
						// #endif
						// #ifdef H5
						className = `.${this.selector}-${item}`
						// #endif
					}
					await this.nodesRef(className).then((res) => {
						res.map(d => {
							d.skeletonType = item
						})
						nodes = nodes.concat(res)
					})
				}
				this.skeletonElements = nodes
			},
			async nodesRef(className) {
				return await new Promise((resolve, reject) => {
					uni.createSelectorQuery().selectAll(className).boundingClientRect((res) => {
						if (res) {
							resolve(res);
						} else {
							reject(res)
						}
					}).exec();
				})
			}
		}
	}
</script>

组件样式

... 此处省略n行

脚本说明

props

参数 类型 描述 默认值
selector String 选择器(外层容器) tui-skeleton
backgroundColor String 外层容器背景颜色 #fff
skeletonBgColor String 骨架元素背景颜色 #e9e9e9
skeletonType Array 骨架元素类型:矩形,圆形,带圆角矩形 ["rect", "circular", "fillet"]
borderRadius String 圆角值,skeletonType=fillet时生效 16rpx
preloadData Array 骨架屏预生成数据 []
isLoading Boolean 是否需要loading true
loadingType Number loading类型[1-10] 1

methods

名称 描述
getLoadingType 获取loading类型
getRadius 获取圆角值
isPreload 骨架屏是否有预生成数据
selectorQuery 查找骨架元素节点
nodesRef 查找骨架元素节点api执行

示例

... 此处省略n行,下载源码查看

预览图