vue手写骨架屏插件
我们在h5开发的过程中,内容可能是根据后台返回数据动态渲染出来的,但是,这样会造成跳屏,体验不好,一些应用中采用了骨架屏的设计,例如今日头条。在没有数据的时候使用骨架屏占位,今天咱们写一个vue骨架屏的插件。
写插件要采用api倒推的思想,想要用户怎么引入,怎么调用,根据用户的使用倒推写法。
首先我们引入一些vue插件的时候先引入样式,然后import引入一个js文件,最后vue.use(刚才引入的文件)
我们给骨架屏插件起个名字叫 skeleton ,我们希望用户将来是这么使用的
import './components/skeleton/skeleton.css' import skeleton from './components/skeleton/skeleton' Vue.use(skeleton)
希望将来用户用如下方式引入组件:
<skeleton :type="[{style:'list1',times:5},{style:'list2',times:4}]" v-if="isShow"></skeleton>
type是个对象数组,style代表插件提供的风格,times代表循环几次,我们的设计目标是可以在同一屏实现多个风格的骨架屏
那么首先我们要实现skeleton.js ,这个js有如下几个功能:
1 返回一个对象
2 作为vue插件,返回的对象要包含install方法
3 要创建一个全局组件,将来调用的时候不需要再进行引入
代码如下
class skeleton{ constructor(v){ this.vm = v; } install(vm){ //将来Vue.use会调用install方法,将vue实例作为参数传入。 // vm:vue实例对象 console.log("this is skeleton plugin") vm.component('skeleton',this.skeExtend(vm)) //注册一个全局组件,名字叫skeleton ,第二个参数是使用vue.extend创建的子类 } skeExtend(v){ return v.extend({ template: `<div class="ske-con"> <div v-for="item,index in computedType" :key="index" class="ske-style-1"> <div v-for="it,index in item.times" :key="index" class="ske-single-cell"> <div class="ske-item"> <div class="ske-list-title"></div> <div class="ske-list-con"></div> </div> </div> </div> <div v-for="item,index in computedType2" :key="item.style" class="ske-style-2"> <div v-for="it,index in item.times" :key="index" class="ske-single-cell"> <div class="ske-item"> <div class="left-part"> <div class="content1"></div> <div class="content2"></div> </div> <div class="right-part"> </div> </div> </div> </div> </div>`, props:{ type:{ type:[String,Array], desc:"骨架屏选项,传入结构为[{style:'list1',times:3},{style:'list2',times:4}]的数据,传入风格和循环的数量", required:true } }, computed:{ computedType(){ let newArr = [] this.type.forEach(item=>{ if(item.style=='list1'){ newArr.push(item) } }) return newArr; }, computedType2(){ let newArr = [] this.type.forEach(item=>{ if(item.style=='list2'){ newArr.push(item) } }) return newArr; } }, }) } } let s = new skeleton() export default s;
样式如下
/* */ .ske-class-list-1{ } /* */ .ske-class-list-2{ } /* common */ .ske-con{ background:#fff; } .ske-single-cell{ width:100vw; } .ske-style-1 .ske-item{ width:95%; margin:0 auto; display:flex; height:40px; border-bottom:1px solid #e4e4e4; } .ske-style-1 .ske-list-title{ width:30%; background:#e4e4e4; height:30px; margin-top:5px; } .ske-style-1 .ske-list-con{ flex:1; background:#e4e4e4; margin-left:50px; height:30px; margin-top:5px; } /* .ske-style-2 */ .ske-style-2 .ske-item{ height:60px; width:95%; margin:0 auto; display:flex; box-sizing: border-box; padding-top:10px; padding-bottom:10px; } .ske-style-2 .left-part{ float:left; width:70%; } .ske-style-2 .left-part .content1{ background:#e4e4e4; height:20px; width:100%; } .ske-style-2 .left-part .content2{ background:#e4e4e4; height:20px; width:80%; margin-top:5px; } .ske-style-2 .right-part{ background:#e4e4e4; flex:1; margin-left:20px; }
如果公司有自己的定制化骨架屏尺寸,可以根据ui要求去增加一些样式。