vue实践动态轮播图组件

vue实践动态轮播图组件

数据更改【=>dom diff -> 把虚拟dom传化为真实的dom ->$nextTick(在回调函数后真实) -> 告知浏览器绘制】

分割成3个件,BannerButton,BannerPagination,BannerPlugin

  • 注意:组件命名采用驼峰式写法
  • 解析关键词作用:template:每一个组件都有一个template,没有template也必须有rand,最起码要指定出我们的视图来
  • data>return : 视图有了,就有数据,为了防止组件之间的数据冲突,把data用闭包包起来,
  • template:`
    :每一个组件只能有一个根节点,加上div,将button里面的内容加进来

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
    <link rel="stylesheet" href="css/reset.min.css">
    <link rel="stylesheet" href="css/banner.css">
    <link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
head>

<body>
    
    
    

    <div id="app">
        <banner-plugin v-if='bannerData' :data='bannerData' :interval='2000' :transitionend='transitionend' :speed='500'
            :pagination='false'>banner-plugin>
        <p>切换到<span v-text='temp'>span>张了
        p>
    div>
body>
<script src="../node_modules/vue/dist/vue.min.js">script>
<script src="../node_modules/axios/dist/axios.min.js">script>
<script src="axios.defaults.js">script>
<script src="banner-plugin.js">script>
<script>
    let vm = new Vue({
        el: '#app',

        data: {
            //=>
            bannerData: [],
            temp:0
        },
        components: {
            BannerPlugin
        },
        created() {
            //=>get请求banner,result从服务器获取结果
            axios.get('/banner').then(result => {
                if (parseInt(result.code) === 0) {
                    this.bannerData = result.data;
                }
            });
        },
        methods: {
            transitionend(example) {
                this.temp = example.activeIndex + 1;
            }
        }
    });
script>

html>

banner-plugin.js

//分割成3个组件,BannerButton,BannerPagination,BannerPlugin
/*
 * 注意:组件命名采用驼峰式写法
 * 解析关键词作用:template:每一个组件都有一个template,没有template也必须有rand,最起码要指定出我们的视图来
 * data>return : 视图有了,就有数据,为了防止组件之间的数据冲突,把data用闭包包起来,
 * template:`
:每一个组件只能有一个根节点,加上div,将button里面的内容加进来 */ //=>左右切换按钮小组件 const BannerButton = { template: `
`
, data() { return {} }, methods:{ change(dir){ this.$emit('handle',dir) } } }; //=>分页器小组件 const BannerPagination = { template: `
`
, //=>注册组件 props:['total','index'], data(){ return { //=>.fill填充null arr : new Array (this.total).fill(null) } }, methods:{ activeHandle(){ //=>i是当前循环这一项的索引 //this.index:当前展示slide的索引 let temp = this.index === this.total ? 0 : this.index; return i === temp; }, change(i){ this.$emit('pagination',i); } } }; //=>轮播图大组件 const BannerPlugin = { template: `
`
, //=>传递属性的校验(当前轮播图组件支持的参数配置) props: { //=>data轮播图的数据 [{id:1,pic:'xxx.png',content:''},...] data: { type: Array, require: true }, //=>初始展示索引 initialsilde: { type: Number, default: 0 }, //=>运动间隔(如果值为0,则不开启自动轮播) interval: { type: Number, default: 3000 }, //=>每一次运动动画的时间 speed: { type: Number, default: 200 }, //=>是否设置分页器(默认一旦设定分页器,点击分页器也能是实现切换) pagination: { type: Boolean, default: true }, //=>是否设置左右导航 button: { type: Boolean, default: true }, //=>初始化成功的钩子函数 init: { type: Function, default: Function.prototype }, //=>切换完成后的钩子函数 transitionend: { type: Function, default: Function.prototype } }, components: { BannerPagination, BannerButton }, data() { //=>[...this.data]指的是把传递进来的数据克隆一份放在末尾 let bannerData = [...this.data, this.data[0]], //=>initialslide是当前选中的select索引值 activeIndex = this.initialslide; return { bannerData, activeIndex, //=>wrapper的样式 sty: { width: bannerData * 1000 + 'px', left: -activeIndex * 1000 + 'px', transition: `left ${this.speed}ms liner` } } }, methods: { autoMove() { this.activeIndex++; if (this.activeIndex >= this.bannerData.length) { this.sty.transition = `left 0ms liner`; this.sty.left = '0px'; //=>回调函数会在本次修改数据后,DOM数据渲染完成过后执行 this.$nextTick(() => { this.$refs.wrapper.offsetLeft; this.activeIndex = 1; this.sty.transition = `left ${this.speed}ms liner`; this.sty.left = -this.activeIndex * 1000 + 'px'; }); return; } this.sty.transition = `left ${this.speed}ms liner`; this.sty.left = -this.activeIndex * 1000 + 'px'; }, stopTimer(lx) { if (lx) { clearInterval(this.autoTimer); //清楚定时器 this.autoTimer = null; return; } this.$autoTimer = setInterval(this.autoMove, this.interval); }, //=>左右按钮切换 handleButton(dir) { if (dir === 'right') { this.autoMove(); return; } this.activeIndex--; if (this.activeIndex < 0) { this.sty.transition = `left 0ms liner`; this.sty.left = -(this.bannerData.length - 1) * 1000 + 'px'; //=>回调函数会在本次修改数据后,DOM数据渲染完成过后执行 this.$nextTick(() => { this.$refs.wrapper.offsetLeft; this.activeIndex = this.bannerData.length - 2; this.sty.transition = `left ${this.speed}ms liner`; this.sty.left = -this.activeIndex * 1000 + 'px'; }); return; } this.sty.transition = `left ${this.speed}ms liner`; this.sty.left = -this.activeIndex * 1000 + 'px'; }, handlePagination(i){ this.activeIndex = i; this.sty.transition = `left ${this.speed}ms liner`; this.sty.left = -this.activeIndex * 1000 + 'px'; } }, created() { // console.log(this) }, //=>第一次渲染完成,开始自动轮播 mounted() { this.$autoTimer = setInterval(this.autoMove, this.interval); //=>触发init钩子函数 this.init(this); }, updated() { //=>触发切换完的钩子函数 this.transitionend(this); } };

banner.css

.container {
    box-sizing:border-box;
    position:relative;
    margin:20px auto;
    width:1000px;
    height:270px;
    overflow:hidden;
}

.container .wrapper {
    position: absolute;
    top:0;
    left:0;
    display:flex;
     width:400%;
     height:100%;
  
}

.container .wrapper .slide {
    box-sizing :border-box;
    width:1000px;
    height:100%;
}

.container .wrapper .slide img {
    width: 100%;
    height:100%;
}

.container .pagination {
     position: absolute;
     right:20px;
     bottom:20px;
     z-index:999;
     font-size:0;

}

.container .pagination span{
    display:inline-block;
    margin:0 4px;
    width:6px;
    height:6px;
    background: rgba(0,0,0,4);
    border: 2px solid rgba(255, 255, 255,4);
    border-radius:50%;
    cursor :pointer;
}

.container .pagination span.active {
    background: rgba(255, 255, 255,4);
    border-color:rgba(0,0,0,4);

}

.container .button-prev,
.container .button-next {
    position: absolute;
    top:50%;
    margin-top:-35px;
    z-index:999;
    width:40px;
    height:70px;
    background: url("../images/icon.png") no-repeat;
}
.container .button-prev {
    left:0;
    background-position: -83px 0;
}
.container .button-prev:hover {
   
    background-position: 0 0;
}

.container .button-next {
    right:0;
    background-position: -124px 0;
}
.container .button-next:hover {
   
    background-position: -41px 0;
}

你可能感兴趣的:(实践真题系列,Vue系列,js系列,vue实践动态轮播图组件,轮播图组件)