【VUE】用vue写一个轮播图组件(一)
背景手写个组件算是基础操作,懂得原理后可以自己手写或者拿别人的组件进行修改。思路用vue写轮播图主要就是靠vue动画。轮播效果靠v-if与设置下一个div的位置。流程先建立基本的框架,swiper.vue swiperItem.vue App.vueApp.vue中写用户自己的内容,swiperItem为swiper.vue的子组件,用来放轮播项。App.vue<...
·
背景
- 手写个组件算是基础操作,懂得原理后可以自己手写或者拿别人的组件进行修改。
思路
- 用vue写轮播图主要就是靠vue动画。轮播效果靠v-if与设置下一个div的位置。
流程
- 先建立基本的框架,swiper.vue swiperItem.vue App.vue
- App.vue中写用户自己的内容,swiperItem为swiper.vue的子组件,用来放轮播项。
App.vue
<template>
<swiper>
<swiperItem>
<div class="content">页面1</div>
</swiperItem>
<swiperItem>
<div class="content">页面2</div>
</swiperItem>
<swiperItem>
<div class="content">页面3</div>
</swiperItem>
</swiper>
</template>
<script>
import swiperItem from './components/SwiperItem'
import swiper from './components/Swiper'
export default {
components: {
swiper,
swiperItem
}
};
</script>
<style lang="stylus"></style>
swiper.vue
<template>
<div class="swiper">
<div class="viewport">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
}
</script>
swiperItem.vue
<template>
<div class="swiper-item">
<slot></slot>
</div>
</template>
<script>
export default {
}
</script>
- 这样基本骨架就有了,页面中会显示3段文字。
- 下一步要使得页面只显示一项,我们需要加属性,使得条件渲染。
<template>
<swiper v-model="selected">
<swiperItem name = "box1">
<div class="content">页面1</div>
</swiperItem>
<swiperItem name = "box2">
<div class="content">页面2</div>
</swiperItem>
<swiperItem name = "box3">
<div class="content">页面3</div>
</swiperItem>
</swiper>
</template>
<script>
import swiperItem from './components/SwiperItem'
import swiper from './components/Swiper'
export default {
data:()=>{
return {selected:'box3'}
},
components: {
swiper,
swiperItem
}
};
</script>
<style lang="stylus"></style>
<template>
<div class="swiper">
<div class="viewport" >
<slot></slot>
</div>
</div>
</template>
<script>
export default {
props:{
value:{
type:String,
default:''
}
},
mounted(){
this.$children.forEach(vm => {
vm.selected = this.value
});
}
}
</script>
<template>
<div class="swiper-item" v-if="name===selected?true:false" >
<slot></slot>
</div>
</template>
<script>
export default {
props:{
name:{
type:String,
required:true
}
},
data(){
return {selected:''}
},
mounted(){
}
}
</script>
- 这样就可以进行条件渲染了,变动App.vue的selected属性可以改变渲染的页面。
- 然后稍微修改一下,增加点样式。试着去在App.vue中改变selected的值,如果颜色变了说明成功。
- 由于swiper的value在mount下只调用一次,所以需要在watch里进行监控,如果值变了就更新。
<template>
<swiper v-model="selected" >
<swiperItem name = "box1">
<div class="content" style="background:red">页面1</div>
</swiperItem>
<swiperItem name = "box2">
<div class="content" style="background:green">页面2</div>
</swiperItem>
<swiperItem name = "box3">
<div class="content" style="background:yellow">页面3</div>
</swiperItem>
</swiper>
</template>
<script>
import swiperItem from './components/SwiperItem'
import swiper from './components/Swiper'
export default {
data:()=>{
return {selected:'box3'}
},
components: {
swiper,
swiperItem
},
mounted(){
setTimeout(() => {
this.selected='box1'
}, 1000);
}
};
</script>
<style lang="stylus">
.content
width 300px
height 300px
text-align center
margin auto
</style>
<template>
<div class="swiper">
<div class="viewport" >
<slot></slot>
</div>
</div>
</template>
<script>
export default {
props:{
value:{
type:String,
default:''
}
},
methods:{
showChild(){
let currentName = this.value||this.$children[0].name
this.$children.forEach(vm => {
vm.selected = currentName
});
}
},
watch:{
value(){
this.showChild()
}
},
mounted(){
this.showChild()
}
}
</script>
<style lang="stylus">
.swiper
border 5px solid black
width 300px
height 300px
margin auto
text-align center
</style>
- 然后设置定时器用触发v-model的input来改变父组件的selected值。
- 在swiper里通过this.$children拿到列表项名字。
- 在列表项里用v-enter v-leave来设置动画。
- vue的动画的离开和进入实际就是元素的离开和进入动画。这里需要元素移动,进入时候在swiper框右边一个身位,出来时候在swiper框左边一个身位。
<template>
<transition>
<div class="swiper-item" v-if="isShow">
<slot></slot>
</div>
</transition>
</template>
<script>
export default {
props: {
name: {
type: String,
required: true
}
},
data() {
return { selected: "" };
},
mounted() {},
computed: {
isShow() {
return this.name === this.selected;
}
}
};
</script>
<style lang="stylus">
.v-enter-active,.v-leave-active
transition all 1s linear
position absolute
.v-leave-to
transform translate(-100%)
.v-enter
transform translate(100%)
</style>
<template>
<div class="swiper">
<div class="viewport">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
props: {
value: {
type: String,
default: ""
},
autoplay:{
type:Boolean,
default:true
}
},
methods: {
showChild() {
this.currentName = this.value || this.$children[0].name;
this.$children.forEach(vm => {
vm.selected = this.currentName;
});
},
autoShow(){
if(this.autoplay){
let timer = setInterval(() => {
let index = this.names.indexOf(this.currentName)
let newIndex = ++index
if(newIndex===this.names.length){
newIndex=0
}
if(newIndex===-1)newIndex=this.names.length-1
this.$emit('input',this.names[newIndex])
},2000);
}
}
},
watch: {
value() {
this.showChild();
}
},
beforeDestroy(){
clearInterval(this.timer)
},
data(){
return {currentName:''}
},
mounted() {
this.names = this.$children.map((vm)=>vm.name)
this.showChild();
this.autoShow()
}
};
</script>
<style lang="stylus">
.swiper
border 5px solid black
width 300px
height 300px
margin auto
text-align center
overflow hidden
.viewport
position relative
</style>
<template>
<swiper v-model="selected" autoplay>
<swiperItem name="box1">
<div class="content" style="background:red">页面1</div>
</swiperItem>
<swiperItem name="box2">
<div class="content" style="background:green">页面2</div>
</swiperItem>
<swiperItem name="box3">
<div class="content" style="background:yellow">页面3</div>
</swiperItem>
</swiper>
</template>
<script>
import swiperItem from "./components/SwiperItem";
import swiper from "./components/Swiper";
export default {
data: () => {
return { selected: "box3" };
},
components: {
swiper,
swiperItem
},
mounted() {
}
};
</script>
<style lang="stylus">
.content {
width: 300px
height: 300px
text-align: center
margin: auto
}
</style>
- 这样简易轮播图基本完成,下一篇再对这个进行优化。
更多推荐
已为社区贡献2条内容
所有评论(0)