Vue2.0进阶组件篇2 解析饿了么(spinner组件)

做者 混元霹雳手-ziksangjavascript

前两天一个同窗问我想叫我写了一个spinner组件,那OK我就是那么能知足你们的口味,若是写一个spinner组件,别看一个小小的组件如何去写,不少人问我vuex,vue-router怎么玩,这东西有什么好玩的,看看api文档就能够去玩了,而后我就看看了饿了么spinner组件的写法,他是如何去组织本身的代码结构的
由于饿了么的spinner组件本质上是基于px来写的,我常常会遇到一个问题,我用的是rem怎么办,px毕竟仍是不适配,那只有拿出个人开山釜本身打造一个rem版本的,若是有饿了么开发人员看到我这文章,虽然小弟我没办法和大家肩并肩一块儿打造组件,那我就借鉴一下,人在江湖走那有不被抄。css


接下来仍是按着咱们约定的来
关于组件篇我就直接拿demo再进行细化分析给你们讲一些细节的知识点,我相信会更有意思一点,为何我要把基础给你们讲的那么详细呢,由于基础打的好组件才写的好
1.本文分享 解析饿了么(spinner组件)

2.代码运行vue-cli 2.1版本html

3.组件代码都在components文件夹里前端

4.主代码逻辑都在 App.vue文件夹里vue

我什么都不要我只要java

css3

饿了么向外爆露出三个接口
color : 颜色 size : 大小 type : 样式类型web

首先index.html,先用rem布局,原理略知一二,就很少说了,反正就是移动端给你作适配vue-router

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>y</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <script>
        (function(doc, win) {
            var docEl = doc.documentElement,
                resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
                recalc = function() {
                    var clientWidth = docEl.clientWidth;
                    if (!clientWidth) return;
                    if (clientWidth >= 640) {
                        docEl.style.fontSize = '100px';
                    } else {
                        docEl.style.fontSize = 100 * (clientWidth / 640) + 'px';
                    }
                };

            if (!doc.addEventListener) return;
            win.addEventListener(resizeEvt, recalc, false);
            doc.addEventListener('DOMContentLoaded', recalc, false);
        })(document, window);
    </script>
</head>

<body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
</body>

</html>复制代码

接下来咱们在components写spinner组件,这里我就写两个组件一个是snake,和double-bouncevuex

首先咱们在components先写一个snake,咱们先建立一个spinner文件夹,就单个type形式的如何写,既然教你们了,就一步一步来写,写的麻烦点就麻烦点。

个人文件目录是在components里创了一个=》zk-spinner文件夹=》又建立了一个src文件夹=>又建立了一个snake.vue文件
components/zk-spinner/src/snake.vue

<template>
    <div class='snake' :style="{
        'border-top-color' : spinnerColor,
        'border-left-color' : spinnerColor,
        'border-bottom-color' : spinnerColor,
        'height' : spinnerSize,
        'width' : spinnerSize
    }">
    </div>
</template>
<script>
export default {
    name : 'snake',
    computed : {
        spinnerColor () {
            return this.color || this.$parent.color || 'red'
        },
        spinnerSize () {
            return (this.size || this.$parent.size || .44)+'rem'
        }
    },
    props : {
        color : String,
        size :  Number
    }
}
</script>
<style>
.snake {
    animation : ziksang-spinner-rotate 0.8s infinite linear;
    border : 4px solid transparent;
    border-radius : 50%;
}
@keyframes  ziksang-spinner-rotate {
    0% {
        transform : rotate(0deg);
        transform : rotate(360deg)
    }
}

</style>复制代码

App.vue

<template>
    <snake></snake>
</template>

<script>
import snake from './components/zk-spinner/src/snake.vue'
export default {
    components : {
        snake
    }
}
</script>

<style>
</style>复制代码

你会发现一个小蛇就在来回的转啊转,很漂亮,这里只用到了向外暴露的两处一个是color,一个是颜色,这里用的是compunted来计算返回给template模板里,这时好处是什么呢,能够用默认样式,还能够用本身定样式
this.color || this.$parent.color || 'red'
(this.size || this.$parent.size || .44)+'rem'
这里表明若是本身没有设定样式则用父元素的样式,父元素没有样式,则用默认样式,你后续会发现 this.color 和 this.size和默认就是根本没有任何用的东西,这里设计的就是一个并句,回头看到后面我再给你们分析

咱们再来写一个double-bounce样式
components/zk-spinner/src/double-bounce.vue

<template>
    <div class="double-bounce" :style='{
        width:spinnerSize,
        height:spinnerSize
    }'>
        <div class="double-bounce1" :style='{backgroundColor : spinnerColor}'></div>
        <div class="double-bounce2" :style='{backgroundColor : spinnerColor}'></div>
    </div>
</template>

<script>
export default {
    name : 'double-bounce',
    computed : {
        spinnerColor () {
            return this.color || this.$parent.color || 'red'
        },
        spinnerSize () {
            return (this.size || this.$parent.size || .44)+'rem'
        }
    },
    props : {
        color : String,
        size :  Number
    }
}
</script>

<style>
.double-bounce {
  position: relative;
}

.double-bounce1, .double-bounce2 {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background-color: #67CF22;
  opacity: 0.6;
  position: absolute;
  top: 0;
  left: 0;

  -webkit-animation: bounce 2.0s infinite ease-in-out;
  animation: bounce 2.0s infinite ease-in-out;
}

.double-bounce2 {
  -webkit-animation-delay: -1.0s;
  animation-delay: -1.0s;
}

@-webkit-keyframes bounce {
  0%, 100% { -webkit-transform: scale(0.0) }
  50% { -webkit-transform: scale(1.0) }
}

@keyframes bounce {
  0%, 100% { 
    transform: scale(0.0);
    -webkit-transform: scale(0.0);
  } 50% { 
    transform: scale(1.0);
    -webkit-transform: scale(1.0);
  }
}
</style>复制代码

App.vue

<template>
    <div>
        <snake></snake>
        <double-bounce></double-bounce>
    </div>
</template>

<script>
import snake from './components/zk-spinner/src/snake.vue'
import doubleBounce from './components/zk-spinner/src/double-bounce.vue'
export default {
    components : {
        snake,
        doubleBounce
    }
}
</script>

<style>
</style>复制代码

此时你会发现一个东西,其实本质上,作再多样spinner样式,只要去基于css3写一些东西,就能够了,咱们能够借鉴前两天掘进里有一我的发的什么7种loading样式,个人收藏夹里有,大家能够去找一下,按照里面的样式,你能够作更多spinner
里面不少东西都是换汤不要药,从两个spinner里能够发现computed和props里面共用的都是一样的,那如今我有只有两个spinner,若是我如今有十个spinner可提供给你们用的,那启不是要写十下,基于编程思想,我要仍是要抽取出来,咱们提取到common.vue里

components/zk-spinner/src/common.js

export default {
    computed: {
        spinnerColor() {
            return this.color || this.$parent.color || 'red'
        },
        spinnerSize() {
            return (this.size || this.$parent.size || .6) + 'rem'
        }
    },
    props: {
        color: String,
        size: Number
    }
}复制代码

如今问题来了,咱们如今有两个组件,一个是snack,和 double-bounce,咱们要更完善一点,再把他们两个挂到一个组件上,那就用到了动态组件,is来进行改造

<template>
     <component :is="spinner"></component>
</template>

<script>
    const SPINNERS= [
        'snake',         //第一段
        'double-bounce'
    ]
    const parseSpinner = function(index){
        if(Object.prototype.toString.call(index) == '[object Number]'){
            if(index >= SPINNERS.length){
                console.warn(`'${index}' spinner not found, use the default spinner.`);
                index = 0   //第二段
            }
            return SPINNERS[index]
        }
        if(SPINNERS.indexOf(index) === -1){
            console.warn(`'${index}' spinner not found, use the default spinner.`);
            index = SPINNERS[0]  //第三段
        }
        return index
    }

    export default {
        name : 'zk-spinner',
        computed : {
            spinner () {
                return `spinner-${parseSpinner(this.type)}`
            }    //第四段
        },
        components: {   //第五段
            SpinnerSnake: require('./src/snake.vue'),
            SpinnerDoubleBounce : require('./src/double-bounce.vue')
        },
        props: {
            type: {
                default: 0    //第六段
            },
            size: {
                type: Number,
                default: .6
            },
            color: {
                type: String,
                default: 'red'
            }
        }
    }
</script>复制代码

App.vue

<template>
    <div> <zk-spinner :type='1' color='#000' ></zk-spinner> <zk-spinner :type='0' color='#000' ></zk-spinner> </div> </template> <script> import zkSpinner from './components/zk-spinner/zk-spinner.vue' export default { components : { zkSpinner } } </script> <style> </style>复制代码

我对这里进行详细的解释一下,以上我分了六段,我以为按着顺序讲不必定是好事,咱们按着我所学习的想法和大家说,
1.我先从props里的将要从父组件接收的数据,我在common.js里把this.color,this.size 和默认的都删除了,由于不管snake仍是double-bounce他们的父组件是谁,是这个动态组件,本质上这个动态组件也就是他们一个挂载的地点,没有必要再进行数据传递,咱们只要进行继承父组件接收的数据便可。因此this.color和this.size都没有没有用的,由于咱们根本不传递数据,默认数据咱们也在动态组件里进行设了default
2.咱们再看看components里面,咱们进行两个组件引入
3.咱们再看看computed,咱们经过计算属性,经过不一样的计算返回不一样的组件
4.咱们再看看SPINNERS变量里,咱们对组件名进行了定议
5.在第二段里当咱们在type里传入的是一个数字的话,若是数字大于PINNERS变量的总长度,咱们则默认给第一个样式,咱们再给出提醒
6.在第三段里另外一种传法,传入一个字符传,先对看SPINNERS变量进行一个匹配,若是匹配到则用这个,没有的话仍是默认用snake这个样式,再给出warn提示

最后咱们都明白了这三个用法了,type是如何封装出来的,size和color又是如何封装出来的,其实若是你真的能把组件系统搞明白了,对你的逻辑思惟和封装一些js的能力也是一种提高,大型项目又有几个能作,因此vuex这东西你们只要没事看看api文档本身手动试试就没有什么问题了,若是有空的话,若是我够精通的话,我会给你们进行分享的,支持混元霹雳手ziksang,感谢你们!!!

渣渣前端开发工程师,喜欢钻研,热爱分享和讲解教学, 微信 zzx1994428 QQ494755899

支持我继续创做和感到有收获的话,请向我打赏点吧

若是转载请标注出自@混元霹雳手ziksang

相关文章
相关标签/搜索