preface
To start!
Why encapsulate
- In line with the ES6 modular development philosophy
- Register global components, for better reuse, where you need to directly use the label name
Global components are registered as plugins in Vue3, and unified components in the project are added to the SRC/Components folder in a new carousel.vue file to write code
<template>
<div class="xtx-carousel" @mouseenter="stop" @mouseleave="start">
<ul class="carousel-body">
<li class="carousel-item" v-for="(item, i) in sliders" :key="i" :class="{ fade: index === i }">
<RouterLink to="/">
<img :src="item.imgUrl" alt="" />
</RouterLink>
</li>
</ul>
<! -- Left and right control buttons -->
<! -- Previous slide -->
<a @click="toggle(-1)" href="javascript:;" class="carousel-btn prev"><i class="iconfont icon-angle-left"></i></a>
<! -- Next slide -->
<a @click="toggle(1)" href="javascript:;" class="carousel-btn next"><i class="iconfont icon-angle-right"></i></a>
<! -- Pager -->
<div class="carousel-indicator">
<span v-for="(item, i) in sliders" :key="i" :class="{ active: index === i }"></span>
</div>
</div>
</template>
<script>
import { ref, watch } from 'vue'
export default {
name: 'XtxCarousel'.props: {
sliders: {
type: Array.default: () = >[]},duration: {
type: Number.default: 1000
},
autoplay: {
type: Boolean.default: false
}
},
setup (props) {
// Index of images displayed by default
const index = ref(0)
// Auto play
let timer = null
const autoPlayFn = () = > {
clearInterval(timer)
timer = setInterval(() = > {
index.value++
if (index.value >= props.sliders.length) {
index.value = 0
}
}, props.duration)
}
watch(
() = > props.sliders,
newVal= > {
// Automatic play function is called only when automatic play is enabled
if (newVal.length > 1 && props.autoplay) {
index.value = 0
autoPlayFn()
}
},
{ immediate: true})const stop = () = > {
if (timer) clearInterval(timer)
}
const start = () = > {
if (props.sliders.length && props.autoPlay) {
autoPlayFn()
}
}
// Go up, go down
const toggle = step= > {
index.value += step
if (index.value >= props.sliders.length) {
index.value = 0
return
}
if (index.value < 0) {
index.value = props.sliders.length - 1}}// Component consumption, clear timer
// onUnmounted(() => {
// if (timer.value) clearInterval(timer.value)
// })
return { index, start, stop, toggle }
}
}
</script>
<style scoped lang="less">
.xtx-carousel{:deep(.carousel-btn.prev) {
left: 270px;
}
:deep(.carousel-indicator) {
padding-left: 250px; }}.xtx-carousel {
width: 100%;
height: 100%;
min-width: 300px;
min-height: 150px;
position: relative;
.carousel {
&-body {
width: 100%;
height: 100%;
}
&-item {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
opacity: 0;
transition: opacity 0.5 s linear;
&.fade {
opacity: 1;
z-index: 1;
}
img {
width: 100%;
height: 100%;
}
}
&-indicator {
position: absolute;
left: 0;
bottom: 20px;
z-index: 2;
width: 100%;
text-align: center;
span {
display: inline-block;
width: 12px;
height: 12px;
background: rgba(0.0.0.0.2);
border-radius: 50%;
cursor: pointer;
~ span {
margin-left: 12px;
}
&.active {
background: #fff;
}
}
}
&-btn {
width: 44px;
height: 44px;
background: rgba(0.0.0.0.2);
color: #fff;
border-radius: 50%;
position: absolute;
top: 228px;
z-index: 2;
text-align: center;
line-height: 44px;
opacity: 0;
transition: all 0.5 s;
&.prev {
left: 20px;
}
&.next {
right: 20px; &}}}:hover {
.carousel-btn {
opacity: 1; }}}</style>
Copy the code
Registering global components
Create the index.js file in SRC/Components
// Extend vue's original functionality: global components, custom directives, mount prototype methods, note: no global filters.
// This is the plug-in
// Vue 2.0 plugin writing elements: export an object, install function, default passed in the Vue constructor, Vue based extension
// Vue3.0 plug-in writing elements: export an object, install function, default passed app application instance, app based on extension
import XtxCarousel from './xtx-carousel.vue'
export default {
install (app) {
// Extend on app, which provides component directive functions
/ / if you want to mount a prototype app. Config. GlobalProperties way
app.component(XtxCarousel.name, XtxCarousel)
}
}
Copy the code
thenmain.js
File registration
import {
createApp
} from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// Import the reset style
import 'normalize.css'
// Import the global style
import '@/style/common.css'
// Font icon
import '@/assets/icon/iconfont.css'
// A custom plug-in
import XtxUI from '@/components/library'
createApp(App).use(store).use(router).use(XtxUI).mount('#app')
Copy the code
Using the demonstration
Pass in custom attributes as required by the global component, using fixed data to simulate this. You can wrap a div element around the global component to control the size of the multicast diagram component
The code is as follows:
<template>
<div class="home-banner">
<XtxCarousel :list="sliders" class="xtx-carousel" />
</div>
</template>
<script>
import { ref } from 'vue'
import { findBanner } from '@/api/home'
export default {
name: 'HomeBanner',
setup () {
const sliders = ref([])
findBanner().then(data= > {
sliders.value = data.result
})
console.log(sliders)
return { sliders }
}
}
</script>
<style scoped lang="less">
.home-banner {
width: 1240px;
height: 500px;
position: absolute;
left: 0;
top: 0;
z-index: 98;
}
.xtx-carousel{:deep(.carousel-btn.prev) {
left: 270px;
}
:deep(.carousel-indicator) {
padding-left: 250px; }}</style>
Copy the code