Skip to content

Commit b4fe8b8

Browse files
committed
refactor: Carousel use script setup
1 parent 430f896 commit b4fe8b8

File tree

5 files changed

+202
-206
lines changed

5 files changed

+202
-206
lines changed

docs/.vitepress/components/carousel/example.vue

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,20 @@
3838
</form>
3939
</section>
4040
</template>
41-
<script>
42-
export default {
43-
data() {
44-
return {
45-
interval: 5000,
46-
indicators: true,
47-
controls: true,
48-
slides: [
49-
{ title: 'Slide 1' },
50-
{ title: 'Slide 2' },
51-
{ title: 'Slide 3' },
52-
{ title: 'Slide 4' },
53-
],
54-
};
55-
},
56-
methods: {
57-
pushSlide() {
58-
this.slides.push({ title: `Slide ${this.slides.length + 1}` });
59-
},
60-
},
61-
};
41+
<script setup>
42+
import { reactive, ref } from 'vue';
43+
44+
const interval = ref(5000);
45+
const indicators = ref(true);
46+
const controls = ref(true);
47+
const slides = reactive([
48+
{ title: 'Slide 1' },
49+
{ title: 'Slide 2' },
50+
{ title: 'Slide 3' },
51+
{ title: 'Slide 4' },
52+
]);
53+
54+
function pushSlide() {
55+
slides.push({ title: `Slide ${slides.length + 1}` });
56+
}
6257
</script>

docs/.vitepress/components/carousel/icons.vue

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,15 @@
1616
</carousel>
1717
</div>
1818
</template>
19-
<script>
20-
export default {
21-
data() {
22-
return {
23-
slides: [
24-
{ title: 'Slide 1' },
25-
{ title: 'Slide 2' },
26-
{ title: 'Slide 3' },
27-
{ title: 'Slide 4' },
28-
],
29-
};
30-
},
31-
};
19+
<script setup>
20+
import { reactive } from 'vue';
21+
22+
const slides = reactive([
23+
{ title: 'Slide 1' },
24+
{ title: 'Slide 2' },
25+
{ title: 'Slide 3' },
26+
{ title: 'Slide 4' },
27+
]);
3228
</script>
3329
<style>
3430
/* Using custom icons may require some additional CSS declarations */

docs/.vitepress/components/carousel/override-indicators.vue

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,22 @@
2727
</div>
2828
</template>
2929

30-
<script>
31-
export default {
32-
data() {
33-
return {
34-
slides: [
35-
{ title: 'Slide 1' },
36-
{ title: 'Slide 2' },
37-
{ title: 'Slide 3' },
38-
{ title: 'Slide 4' },
39-
],
40-
};
41-
},
42-
};
30+
<script setup>
31+
import { reactive } from 'vue';
32+
33+
const slides = reactive([
34+
{ title: 'Slide 1' },
35+
{ title: 'Slide 2' },
36+
{ title: 'Slide 3' },
37+
{ title: 'Slide 4' },
38+
]);
4339
</script>
4440
<style>
4541
.uiv .custom-carousel-indicators li,
4642
.uiv .custom-carousel-indicators li.active {
47-
width: 50px;
48-
height: 8px;
49-
margin: 0 3px;
50-
border-radius: 0;
43+
width: 50px !important;
44+
height: 8px !important;
45+
margin: 0 3px !important;
46+
border-radius: 0 !important;
5147
}
5248
</style>

src/components/carousel/Carousel.vue

Lines changed: 136 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -46,139 +46,145 @@
4646
</div>
4747
</template>
4848

49-
<script>
49+
<script setup>
5050
import { isExist } from '../../utils/object.utils';
51+
import {
52+
onBeforeUnmount,
53+
onMounted,
54+
reactive,
55+
ref,
56+
watch,
57+
nextTick,
58+
} from 'vue';
5159
52-
export default {
53-
props: {
54-
modelValue: {
55-
type: Number,
56-
default: undefined,
57-
},
58-
indicators: {
59-
type: Boolean,
60-
default: true,
61-
},
62-
controls: {
63-
type: Boolean,
64-
default: true,
65-
},
66-
interval: {
67-
type: Number,
68-
default: 5000,
69-
},
70-
iconControlLeft: {
71-
type: String,
72-
default: 'glyphicon glyphicon-chevron-left',
73-
},
74-
iconControlRight: {
75-
type: String,
76-
default: 'glyphicon glyphicon-chevron-right',
77-
},
60+
const props = defineProps({
61+
modelValue: { type: Number, default: undefined },
62+
indicators: { type: Boolean, default: true },
63+
controls: { type: Boolean, default: true },
64+
interval: { type: Number, default: 5000 },
65+
iconControlLeft: {
66+
type: String,
67+
default: 'glyphicon glyphicon-chevron-left',
7868
},
79-
emits: ['update:modelValue', 'change'],
80-
data() {
81-
return {
82-
slides: [],
83-
activeIndex: 0, // Make v-model not required
84-
timeoutId: 0,
85-
intervalId: 0,
86-
};
69+
iconControlRight: {
70+
type: String,
71+
default: 'glyphicon glyphicon-chevron-right',
8772
},
88-
watch: {
89-
interval() {
90-
this.startInterval();
91-
},
92-
modelValue(index, oldValue) {
93-
this.run(index, oldValue);
94-
this.activeIndex = index;
95-
},
96-
},
97-
mounted() {
98-
if (isExist(this.modelValue)) {
99-
this.activeIndex = this.modelValue;
100-
}
101-
if (this.slides.length > 0) {
102-
this.$select(this.activeIndex);
103-
}
104-
this.startInterval();
105-
},
106-
beforeUnmount() {
107-
this.stopInterval();
108-
},
109-
methods: {
110-
run(newIndex, oldIndex) {
111-
const currentActiveIndex = oldIndex || 0;
112-
let direction;
113-
if (newIndex > currentActiveIndex) {
114-
direction = ['next', 'left'];
115-
} else {
116-
direction = ['prev', 'right'];
117-
}
118-
this.slides[newIndex].slideClass[direction[0]] = true;
119-
this.$nextTick(() => {
120-
this.slides[newIndex].$el.offsetHeight;
121-
this.slides.forEach((slide, i) => {
122-
if (i === currentActiveIndex) {
123-
slide.slideClass.active = true;
124-
slide.slideClass[direction[1]] = true;
125-
} else if (i === newIndex) {
126-
slide.slideClass[direction[1]] = true;
127-
}
128-
});
129-
this.timeoutId = setTimeout(() => {
130-
this.$select(newIndex);
131-
this.$emit('change', newIndex);
132-
this.timeoutId = 0;
133-
}, 600);
134-
});
135-
},
136-
startInterval() {
137-
this.stopInterval();
138-
if (this.interval > 0) {
139-
this.intervalId = setInterval(() => {
140-
this.next();
141-
}, this.interval);
142-
}
143-
},
144-
stopInterval() {
145-
clearInterval(this.intervalId);
146-
this.intervalId = 0;
147-
},
148-
resetAllSlideClass() {
149-
this.slides.forEach((slide) => {
150-
slide.slideClass.active = false;
151-
slide.slideClass.left = false;
152-
slide.slideClass.right = false;
153-
slide.slideClass.next = false;
154-
slide.slideClass.prev = false;
155-
});
156-
},
157-
$select(index) {
158-
this.resetAllSlideClass();
159-
this.slides[index].slideClass.active = true;
160-
},
161-
select(index) {
162-
if (this.timeoutId !== 0 || index === this.activeIndex) {
163-
return;
164-
}
165-
if (isExist(this.modelValue)) {
166-
this.$emit('update:modelValue', index);
167-
} else {
168-
this.run(index, this.activeIndex);
169-
this.activeIndex = index;
73+
});
74+
75+
const emit = defineEmits(['update:modelValue', 'change']);
76+
77+
let activeIndex = ref(0);
78+
let timeoutId = 0;
79+
let intervalId = 0;
80+
const slides = reactive([]);
81+
82+
function run(newIndex, oldIndex) {
83+
const currentActiveIndex = oldIndex || 0;
84+
let direction;
85+
if (newIndex > currentActiveIndex) {
86+
direction = ['next', 'left'];
87+
} else {
88+
direction = ['prev', 'right'];
89+
}
90+
slides[newIndex].exposed.slideClass[direction[0]] = true;
91+
nextTick(() => {
92+
slides[newIndex].vnode.el.offsetHeight;
93+
slides.forEach((slide, i) => {
94+
if (i === currentActiveIndex) {
95+
slide.exposed.slideClass.active = true;
96+
slide.exposed.slideClass[direction[1]] = true;
97+
} else if (i === newIndex) {
98+
slide.exposed.slideClass[direction[1]] = true;
17099
}
171-
},
172-
prev() {
173-
this.select(
174-
this.activeIndex === 0 ? this.slides.length - 1 : this.activeIndex - 1
175-
);
176-
},
177-
next() {
178-
this.select(
179-
this.activeIndex === this.slides.length - 1 ? 0 : this.activeIndex + 1
180-
);
181-
},
182-
},
183-
};
100+
});
101+
timeoutId = setTimeout(() => {
102+
_select(newIndex);
103+
emit('change', newIndex);
104+
timeoutId = 0;
105+
}, 600);
106+
});
107+
}
108+
109+
function startInterval() {
110+
stopInterval();
111+
if (props.interval > 0) {
112+
intervalId = setInterval(() => {
113+
next();
114+
}, props.interval);
115+
}
116+
}
117+
118+
function stopInterval() {
119+
clearInterval(intervalId);
120+
intervalId = 0;
121+
}
122+
123+
function resetAllSlideClass() {
124+
slides.forEach((slide) => {
125+
slide.exposed.slideClass.active = false;
126+
slide.exposed.slideClass.left = false;
127+
slide.exposed.slideClass.right = false;
128+
slide.exposed.slideClass.next = false;
129+
slide.exposed.slideClass.prev = false;
130+
});
131+
}
132+
133+
function _select(index) {
134+
resetAllSlideClass();
135+
slides[index].exposed.slideClass.active = true;
136+
}
137+
138+
function select(index) {
139+
if (timeoutId !== 0 || index === activeIndex.value) {
140+
return;
141+
}
142+
if (isExist(props.modelValue)) {
143+
emit('update:modelValue', index);
144+
} else {
145+
run(index, activeIndex.value);
146+
activeIndex.value = index;
147+
}
148+
}
149+
150+
function prev() {
151+
select(activeIndex.value === 0 ? slides.length - 1 : activeIndex.value - 1);
152+
}
153+
154+
function next() {
155+
select(activeIndex.value === slides.length - 1 ? 0 : activeIndex.value + 1);
156+
}
157+
158+
watch(
159+
() => props.interval,
160+
() => {
161+
startInterval();
162+
}
163+
);
164+
165+
watch(
166+
() => props.modelValue,
167+
(index, oldValue) => {
168+
run(index, oldValue);
169+
activeIndex.value = index;
170+
}
171+
);
172+
173+
onMounted(() => {
174+
if (isExist(props.modelValue)) {
175+
activeIndex.value = props.modelValue;
176+
}
177+
if (slides.length > 0) {
178+
_select(activeIndex.value);
179+
}
180+
startInterval();
181+
});
182+
183+
onBeforeUnmount(() => {
184+
stopInterval();
185+
});
186+
187+
defineExpose({
188+
slides,
189+
});
184190
</script>

0 commit comments

Comments
 (0)