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要求去增加一些样式。

 

posted @ 2020-07-27 16:43  熊猫程序员  阅读(410)  评论(0编辑  收藏  举报