• 2/5 Vue.js 简单轮播组件


      以前刚接触Vue的时候手撸了一个 轮播图 效果还是不错的

      但是在学习过程中,越发发现组件的用处

      所以在书上源码的加持下 添油加醋 写了一个轮播组件

      注释很清晰 供有缘人查看

      1 <template>
      2   <div class="swiper-container">
      3     <!-- 用动态样式换图片 -->
      4     <!-- 通过div的方式展示图片可以减轻浏览器负担 -->
      5 
      6     <!-- 进行过渡 -->
      7     <transition-group name="images" tag="div" class="swiper-images">
      8       <!-- 通过v-for来实现多个盒子的注入 -->
      9       <div
     10         v-for="(slide, index) in slides"
     11         :key="slides.indexOf(slide)"
     12         :style="{ backgroundImage: 'url(' + slide + ')' }"
     13         class="swiper-image"
     14         v-show="index === value"
     15         @mouseover="toggleIndex(index)"
     16         @mouseout="initTimer"
     17       ></div>
     18     </transition-group>
     19 
     20     <!-- 切换按钮 -->
     21     <div class="swiper-paginator">
     22       <!-- slides 是父组件传入的参数 -->
     23 
     24       <span
     25         v-for="(slide, index) in slides"
     26         :key="index"
     27         class="paginator-item"
     28         :class="{ 'paginator-current': index === value }"
     29         @mouseover="toggleIndex(index)"
     30         @mouseout="initTimer"
     31       ></span>
     32     </div>
     33 
     34     <div
     35       class="arrow arrow_left"
     36       @click="onLeft"
     37       @mouseover="toggleIndex()"
     38       @mouseout="initTimer"
     39     >
     40       <div></div>
     41     </div>
     42     <div
     43       class="arrow arrow_right"
     44       @click="onRight"
     45       @mouseover="toggleIndex()"
     46       @mouseout="initTimer"
     47     >
     48       <div></div>
     49     </div>
     50   </div>
     51 </template>
     52  
     53 <script>
     54 // 制造组件的第一部分 其实就是想清楚 变量
     55 // 要得到相应的 变量 ; 要从上级组件得到的 参数
     56 // 这里 因为是 轮播图 所以
     57 //  1 存放图片路径的图片数组 slides
     58 //  2 当前的图片标志 (页码) value
     59 //  3 自动轮播的时间间隔 interval
     60 // 这些我们都可以从上级的组件里面得到
     61 
     62 export default {
     63   name: "Swiper",
     64   props: {
     65     slides: {
     66       type: Array,
     67       validator(value) {
     68         //  判断是否每一个元素 都是 满足String 的条件
     69         return value.every(
     70           (item) => Object.prototype.toString.call(item) === "[object String]"
     71         );
     72       },
     73     },
     74     value: {
     75       //  Value 标志当前的图片 默认是从 0 开始 ( props 里面的 value 属性默认接受父组件的v-model值 )
     76       type: Number,
     77       default: 0,
     78     },
     79     interval: {
     80       //  间隔也是一个 数字类型的变量 默认从 4 开始
     81       type: Number,
     82       default: 4,
     83     },
     84   },
     85   data() {
     86     return {
     87       //  在 data 里面设置一个 计时器 还未被初始化
     88       timer: null,
     89     };
     90   },
     91 
     92   mounted() {
     93     // 每次挂载好了 就开启计时器
     94     this.initTimer();
     95   },
     96   methods: {
     97     //  初始化计时器
     98     initTimer() {
     99       this.timer = setInterval(() => {
    100         //  父组件的 input 的参数
    101         this.$emit("input", (this.value + 1) % this.slides.length);
    102       }, this.interval * 1000);
    103     },
    104     //  每当 hover 和 点击到了 按钮 就开始 执行下面的操作
    105     toggleIndex(index) {
    106       // 父组件的index 为当前的的index 如果 没有参数 则就是原来的数值 注意0也是没得
    107       this.$emit("input", index >= 0 ? index : this.value);
    108       clearInterval(this.timer); // 清除计时器
    109     },
    110     // 箭头点击
    111     // 左箭头
    112     onLeft() {
    113       // 自己做一下数学运算
    114       this.$emit(
    115         "input",
    116         this.value - 1 >= 0
    117           ? (this.value - 1) % this.slides.length
    118           : (this.slides.length - Math.abs(this.value - 1)) % this.slides.length
    119       );
    120       clearInterval(this.timer); // 清除计时器
    121     },
    122     // 右箭头
    123     onRight() {
    124       this.$emit("input", (this.value + 1) % this.slides.length);
    125       clearInterval(this.timer); // 清除计时器
    126     },
    127   },
    128 };
    129 </script>
    130  
    131 <style scoped>
    132 /* scoped 表明该 css 仅仅只适用于 本组件 */
    133 .swiper-container {
    134   /* 容纳的大盒子 子绝 父相 */
    135   position: relative;
    136   width: 100%;
    137   height: 100%;
    138 }
    139 .swiper-images {
    140   height: 100%;
    141   width: 100%;
    142 }
    143 .swiper-image {
    144   height: 100%;
    145   width: 100%;
    146   background-size: cover;
    147   background-repeat: no-repeat;
    148   /* 让几个 image 盒子重叠 */
    149   position: absolute;
    150 }
    151 .swiper-paginator {
    152   margin-top: -30px;
    153   padding-right: 5px;
    154   text-align: right;
    155   list-style: none;
    156 }
    157 .paginator-item {
    158   cursor: pointer;
    159   display: inline-block;
    160   width: 16px;
    161   height: 16px;
    162   margin-left: 5px;
    163   border-radius: 50%;
    164   background-color: #000;
    165   opacity: 0.3;
    166 }
    167 .paginator-current {
    168   background-color: #fff; /* 当前激活的幻灯片切换按钮样式 */
    169   opacity: 0.6;
    170 }
    171 
    172 /* 箭头 */
    173 .arrow {
    174   display: block;
    175   width: 45px;
    176   height: 108px;
    177   position: absolute;
    178   top: 35%;
    179   cursor: pointer;
    180   right: -20%;
    181   background: linear-gradient(
    182     to left,
    183     rgba(0, 0, 0, 0.3) 5%,
    184     rgba(0, 0, 0, 0) 95%
    185   );
    186   transition: all 0.5s;
    187 }
    188 .arrow_left {
    189   /*//左边距离父盒子边框*/
    190   left: -45px;
    191   background: linear-gradient(
    192     to right,
    193     rgba(0, 0, 0, 0.3) 5%,
    194     rgba(0, 0, 0, 0) 95%
    195   );
    196 }
    197 .arrow_right {
    198   /*//右边距离父盒子边框*/
    199   right: -45px;
    200   background: linear-gradient(
    201     to left,
    202     rgba(0, 0, 0, 0.3) 5%,
    203     rgba(0, 0, 0, 0) 95%
    204   );
    205 }
    206 .arrow:hover {
    207   background: linear-gradient(
    208     to left,
    209     rgba(171, 218, 244, 0.3) 5%,
    210     rgba(171, 218, 244, 0) 95%
    211   );
    212 }
    213 
    214 .arrow div {
    215   display: block;
    216   /* 箭头图片的路径 */
    217   background-image: url(/static/images/arrow.png);
    218   background-repeat: no-repeat;
    219   height: 36px;
    220   width: 23px;
    221   margin: 36px auto;
    222 }
    223 
    224 .arrow_left div {
    225   background-position: -23px 0px;
    226 }
    227 .arrow_right div {
    228   background-position: 0px 0px;
    229 }
    230 
    231 /* 过渡效果 */
    232 .images-enter,
    233 .images-leave-to {
    234   opacity: 0;
    235   /* transform:translateX(30px) */
    236 }
    237 .images-enter-active,
    238 .images-leave-active {
    239   transition-property: all;
    240   /* transition-delay: 100ms; */
    241   transition-duration: 500ms;
    242   transition-timing-function: linear;
    243 }
    244 .images-leave,
    245 .images-enter-to {
    246   /* transform:translateX(0px); */
    247   opacity: 1;
    248 }
    249 </style>

      当然这个组件应该怎么用呢,

      如下图

      


      接着是我写这个组件的时候遇到的问题

      1.trasnsition-group 没有只套用在 v-for 的一个标签上

        当时是这样的,v-for那个div 外层还有一个 大div , 我给套在大盒子上了,结果就出错了

      2.js 表示假值的一般来说 就是没得的东西 0 也是假值

        加了注释的地方就是我出错的地方

        

         当时没有想到这个,原来的代码是 框起来的那个部分

        

           如果 传入 0 的时候,如果参数 index 为 0 的话,就会发生意想不到的事情 

        表现在这个组件里面就是没办法点击到第一个小圆点,因为传到的参数是 0 

        3.还有一个错误,就是

          

        transition-group提示key值没有弄对,其实这里直接 这样就能解决 或者 :key ="slide"

          

        最后呢

        对比原来写的一个代码,我发现现在这个组件的代码更加美观,原来那个太小孩子了 感觉

          原来写的 https://www.cnblogs.com/WaterMealone/articles/14332704.html

        注:

          可能有朋友在用的时候会发现,小圆点有点奇怪,这个我也不知道怎么去处理,因为 span 的规定范围太小了,导致了快速滑动的时候 判定老是更新

          所以 会有一种反应不过来的 现象

          然后这个是箭头的图片

          

          这个是整个项目的图片

          

       总结

        每天进步一点点

        今天再撸一下代码

        

    Let it roll
  • 相关阅读:
    setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key
    Kinect 骨骼追踪数据的处理方法
    了解与建设有中国特色的Android M&N(Android6.0和7.0新特性分析)
    【计算机视觉】深度相机(一)--TOF总结
    A million requests per second with Python
    buf.fill()
    buf.slice()
    buf.toJSON()
    buf.toString()
    Buffer.compare()
  • 原文地址:https://www.cnblogs.com/WaterMealone/p/14379544.html
Copyright © 2020-2023  润新知