您现在的位置是:网站首页>前端技术>VueVue

VUE实现骨架屏,uniapp骨架屏,小程序骨架屏效果实现

神夜2020-05-26 11:10:54Vue4863人已围观文章来源:神夜个人博客

简介skeleton.vue 插件适用于VUE项目和uniapp小程序H5项目。使用简单


1、首先编写一个skeleton.vue 插件 代码如下,参考别人编写生成uniapp改了一下。


<template>
  <div>
    <div class="wrap"
         :style="{'width':systemInfo.width+'px','height':systemInfo.height+'px', 'background-color':bgcolor}">
      <div v-for="(item,index) in skeletonRectLists"
           :index='index'
           :key='index'
           class="chiaroscuro"
           :style="{'width':item.width+'px','height':item.height+'px','background-color':'rgba(233, 2, 233,1)','position':'absolute','left':item.left+'px','top':item.top+'px'}">
      </div>
      <div v-for="(item,index) in skeletonCircleLists"
           :index='index'
           :key="'info2-'+index"
           class="chiaroscuro"
           :style="{'width':item.width+'px','height':item.height+'px','background-color':'rgba(233, , 233,1)','border-radius':item.width+'px','position':'absolute','left':item.left+'px','top':item.top+'px'}">
      </div>
    </div>
  </div>
</template>



<script>
export default {
        props: {
		  bgcolor: { type: String, value: '#FFF' },
		  selector: { type: String, value: 'skeleton' },
		},

        data() {
            return {
                systemInfo: {},
                skeletonRectLists: [],
                skeletonCircleLists: [],
            };
        },

        components: {},

        mounted: function() {
            //默认的首屏宽高,防止内容闪现
            this.systemInfo = {
                width: window.innerWidth,
                height: window.innerHeight,
            };
            var dom = document.querySelectorAll(`.$ {
                this.selector
            }`);
            //this.systemInfo.height = dom[0].clientHeight + dom[0].offsetTop  || 0;
            //绘制矩形
            this.rectHandle();

            //绘制圆形
            this.radiusHandle();
        },

        methods: {
            //绘制距形
            rectHandle: function() {
                let dom = document.querySelectorAll(`.$ {
                    this.selector
                } - rect`);
                for (var i = 0; i < dom.length; i++) {
                    this.skeletonRectLists.push(dom[i].getBoundingClientRect());
                }
            },
            //绘制圆形
            radiusHandle: function() {
                let dom = document.querySelectorAll(`.$ {
                    this.selector
                } - radius`);
                for (var i = 0; i < dom.length; i++) {
                    this.skeletonCircleLists.push(dom[i].getBoundingClientRect())
                }
            },
        },

    };
</script>

<style scoped>
.wrap {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 9998;
  overflow: hidden;
}
.chiaroscuro {
  animation-duration: 1s;
  animation-fill-mode: forwards;
  animation-iteration-count: infinite;
  animation-name: placeHolderShimmer;
  animation-timing-function: linear;
  background: #f6f7f8;
  background: linear-gradient(to right, #eeeeee 8%, #dddddd 18%, #eeeeee 33%);
  background-size: 800px 104px;
  height: 40px;
  position: relative;
}
@keyframes placeHolderShimmer{
  0% {
    background-position: -468px 0
  }
  100% {
    background-position: 468px 0
  }
}
</style> 

如果将代码改一下可以用于UNIAPP小程序和公众号



<template>
  <div>
    <div class="wrap"
         :style="{'width':systemInfo.width+'px','height':systemInfo.height+'px', 'background-color':bgcolor}">
      <div v-for="(item,index) in skeletonRectLists"
           :index='index'
           :key='index'
           class="chiaroscuro"
           :style="{'width':item.width+'px','height':item.height+'px','background-color':'rgba(233, 2, 233,1)','position':'absolute','left':item.left+'px','top':item.top+'px'}">
      </div>
      <div v-for="(item,index) in skeletonCircleLists"
           :index='index'
           :key="'info2-'+index"
           class="chiaroscuro"
           :style="{'width':item.width+'px','height':item.height+'px','background-color':'rgba(233, , 233,1)','border-radius':item.width+'px','position':'absolute','left':item.left+'px','top':item.top+'px'}">
      </div>
    </div>
  </div>
</template>

<script>
/* eslint-disable */
export default {
  props: {
    bgcolor: { type: String, value: '#FFF' },
    selector: { type: String, value: 'skeleton' },
  },

  data() {
    return {
      systemInfo: {},
      skeletonRectLists: [],
      skeletonCircleLists: [],
    };
  },

  components: {},
		
		
		mounted: function() {
		  //默认的首屏宽高,防止内容闪现
		  const systemInfo = uni.getSystemInfoSync();
		  (this.systemInfo = {
		    width: systemInfo.windowWidth,
		    height: systemInfo.windowHeight,
		  });
		  const that = this;
				
		  //绘制背景
		  uni
		    .createSelectorQuery()
		    .selectAll(`.${this.selector}`)
		    .boundingClientRect()
		    .exec(function(res) {
							 console.log(res);
		      that.systemInfo.height = res[0][0].height + res[0][0].top || 0;
		    });
		
		  //绘制矩形
		  this.rectHandle();
		
		  //绘制圆形
		  this.radiusHandle();
		},
		
  methods: {
    rectHandle: function() {
      const that = this;
      //绘制不带样式的节点
      uni
        .createSelectorQuery()
        .selectAll(`.${this.selector}-rect`)
        .boundingClientRect()
        .exec(function(res) {
          that.skeletonRectLists = res[0];
        });
    },

    radiusHandle: function() {
      const that = this;
      uni
        .createSelectorQuery()
        .selectAll(`.${this.selector}-radius`)
        .boundingClientRect()
        .exec(function(res) {
            console.log(res[0].length);
          that.skeletonCircleLists = res[0];
        });
    },
  },

};
/* eslint-enable */
</script>

<style scoped>
.wrap {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 9998;
  overflow: hidden;
}
.chiaroscuro {
  animation-duration: 1s;
  animation-fill-mode: forwards;
  animation-iteration-count: infinite;
  animation-name: placeHolderShimmer;
  animation-timing-function: linear;
  background: #f6f7f8;
  background: linear-gradient(to right, #eeeeee 8%, #dddddd 18%, #eeeeee 33%);
  background-size: 800px 104px;
  height: 40px;
  position: relative;
}
@keyframes placeHolderShimmer{
  0% {
    background-position: -468px 0
  }
  100% {
    background-position: 468px 0
  }
}
</style>



2、调用插件 skeleton.vue


<template>
	<div class="content ">
		<skeleton selector="skeleton" bgcolor="#FFF" v-if="showSkeleton"></skeleton>
		<div class="skeleton">
			<img class="logo skeleton-rect" src="/static/logo.png">
			<div class="text-area skeleton-radius">
				<div class="title">{{ title }}</div>
			</div>
		</div>
	</div>
</template>

<script>
import skeleton from '@/pages/index/skeleton.vue'
export default {
	data() {
		return {
			showSkeleton:
			true,
			title: 'Hello',

		}
	},
	components: {
		'skeleton': skeleton
	},
	created() {
		this.reloadData();
	},
	methods: {
		reloadData() {
			setTimeout(() = >{
				this.showSkeleton = false
			},
			2000)
		},
	}
}
</script>


注意:显示距形:则在样式上添加 skeleton-rect, 显示圆形 :skeleton-radius , 如果没有添加这两个样式,则是一片空白

实现原理:根据原有的DIV 宽和高以及left和top 来绘制一个空白div。循环生成多个div 再给DIV加上样式动画。设置时间 多少秒后消失。



站点信息

  • 建站时间:2017-10-24
  • 网站程序:Hsycms 3.0
  • 文章统计:511条
  • 微信公众号:扫描二维码,关注我们