|
89 | 89 | </nav> |
90 | 90 | </template> |
91 | 91 |
|
92 | | -<script> |
| 92 | +<script setup> |
93 | 93 | import { range } from '../../utils/array.utils'; |
| 94 | +import { computed, ref, watch } from 'vue'; |
94 | 95 |
|
95 | | -export default { |
96 | | - props: { |
97 | | - modelValue: { |
98 | | - type: Number, |
99 | | - required: true, |
100 | | - validator: (v) => v >= 1, |
101 | | - }, |
102 | | - boundaryLinks: { |
103 | | - type: Boolean, |
104 | | - default: false, |
105 | | - }, |
106 | | - directionLinks: { |
107 | | - type: Boolean, |
108 | | - default: true, |
109 | | - }, |
110 | | - size: { type: String, default: undefined }, |
111 | | - align: { type: String, default: undefined }, |
112 | | - totalPage: { |
113 | | - type: Number, |
114 | | - required: true, |
115 | | - validator: (v) => v >= 0, |
116 | | - }, |
117 | | - maxSize: { |
118 | | - type: Number, |
119 | | - default: 5, |
120 | | - validator: (v) => v >= 0, |
121 | | - }, |
122 | | - disabled: Boolean, |
123 | | - }, |
124 | | - emits: ['update:modelValue', 'change'], |
125 | | - data() { |
126 | | - return { |
127 | | - sliceStart: 0, |
128 | | - }; |
129 | | - }, |
130 | | - computed: { |
131 | | - navClasses() { |
132 | | - return { |
133 | | - [`text-${this.align}`]: Boolean(this.align), |
134 | | - }; |
135 | | - }, |
136 | | - classes() { |
137 | | - return { |
138 | | - [`pagination-${this.size}`]: Boolean(this.size), |
139 | | - }; |
140 | | - }, |
141 | | - sliceArray() { |
142 | | - return range(this.totalPage).slice( |
143 | | - this.sliceStart, |
144 | | - this.sliceStart + this.maxSize |
145 | | - ); |
146 | | - }, |
147 | | - }, |
148 | | - created() { |
149 | | - this.$watch( |
150 | | - (vm) => [vm.modelValue, vm.maxSize, vm.totalPage].join(), |
151 | | - this.calculateSliceStart, |
152 | | - { |
153 | | - immediate: true, |
154 | | - } |
155 | | - ); |
156 | | - }, |
157 | | - methods: { |
158 | | - calculateSliceStart() { |
159 | | - const currentPage = this.modelValue; |
160 | | - const chunkSize = this.maxSize; |
161 | | - const currentChunkStart = this.sliceStart; |
162 | | - const currentChunkEnd = currentChunkStart + chunkSize; |
163 | | - if (currentPage > currentChunkEnd) { |
164 | | - const lastChunkStart = this.totalPage - chunkSize; |
165 | | - if (currentPage > lastChunkStart) { |
166 | | - this.sliceStart = lastChunkStart; |
167 | | - } else { |
168 | | - this.sliceStart = currentPage - 1; |
169 | | - } |
170 | | - } else if (currentPage < currentChunkStart + 1) { |
171 | | - if (currentPage > chunkSize) { |
172 | | - this.sliceStart = currentPage - chunkSize; |
173 | | - } else { |
174 | | - this.sliceStart = 0; |
175 | | - } |
176 | | - } |
177 | | - }, |
178 | | - onPageChange(page) { |
179 | | - if ( |
180 | | - !this.disabled && |
181 | | - page > 0 && |
182 | | - page <= this.totalPage && |
183 | | - page !== this.modelValue |
184 | | - ) { |
185 | | - this.$emit('update:modelValue', page); |
186 | | - this.$emit('change', page); |
187 | | - } |
188 | | - }, |
189 | | - toPage(pre) { |
190 | | - if (this.disabled) { |
191 | | - return; |
192 | | - } |
193 | | - const chunkSize = this.maxSize; |
194 | | - const currentChunkStart = this.sliceStart; |
195 | | - const lastChunkStart = this.totalPage - chunkSize; |
196 | | - const start = pre |
197 | | - ? currentChunkStart - chunkSize |
198 | | - : currentChunkStart + chunkSize; |
199 | | - if (start < 0) { |
200 | | - this.sliceStart = 0; |
201 | | - } else if (start > lastChunkStart) { |
202 | | - this.sliceStart = lastChunkStart; |
203 | | - } else { |
204 | | - this.sliceStart = start; |
205 | | - } |
206 | | - }, |
| 96 | +const props = defineProps({ |
| 97 | + modelValue: { type: Number, required: true, validator: (v) => v >= 1 }, |
| 98 | + boundaryLinks: { type: Boolean, default: false }, |
| 99 | + directionLinks: { type: Boolean, default: true }, |
| 100 | + size: { type: String, default: undefined }, |
| 101 | + align: { type: String, default: undefined }, |
| 102 | + totalPage: { type: Number, required: true, validator: (v) => v >= 0 }, |
| 103 | + maxSize: { type: Number, default: 5, validator: (v) => v >= 0 }, |
| 104 | + disabled: Boolean, |
| 105 | +}); |
| 106 | +const emit = defineEmits(['update:modelValue', 'change']); |
| 107 | +
|
| 108 | +const sliceStart = ref(0); |
| 109 | +
|
| 110 | +const navClasses = computed(() => ({ |
| 111 | + [`text-${props.align}`]: Boolean(props.align), |
| 112 | +})); |
| 113 | +const classes = computed(() => ({ |
| 114 | + [`pagination-${props.size}`]: Boolean(props.size), |
| 115 | +})); |
| 116 | +const sliceArray = computed(() => |
| 117 | + range(props.totalPage).slice( |
| 118 | + sliceStart.value, |
| 119 | + sliceStart.value + props.maxSize |
| 120 | + ) |
| 121 | +); |
| 122 | +
|
| 123 | +watch( |
| 124 | + () => [props.modelValue, props.maxSize, props.totalPage], |
| 125 | + () => { |
| 126 | + calculateSliceStart(); |
207 | 127 | }, |
208 | | -}; |
| 128 | + { |
| 129 | + immediate: true, |
| 130 | + } |
| 131 | +); |
| 132 | +
|
| 133 | +function calculateSliceStart() { |
| 134 | + const currentPage = props.modelValue; |
| 135 | + const chunkSize = props.maxSize; |
| 136 | + const currentChunkStart = sliceStart.value; |
| 137 | + const currentChunkEnd = currentChunkStart + chunkSize; |
| 138 | + if (currentPage > currentChunkEnd) { |
| 139 | + const lastChunkStart = props.totalPage - chunkSize; |
| 140 | + if (currentPage > lastChunkStart) { |
| 141 | + sliceStart.value = lastChunkStart; |
| 142 | + } else { |
| 143 | + sliceStart.value = currentPage - 1; |
| 144 | + } |
| 145 | + } else if (currentPage < currentChunkStart + 1) { |
| 146 | + if (currentPage > chunkSize) { |
| 147 | + sliceStart.value = currentPage - chunkSize; |
| 148 | + } else { |
| 149 | + sliceStart.value = 0; |
| 150 | + } |
| 151 | + } |
| 152 | +} |
| 153 | +
|
| 154 | +function onPageChange(page) { |
| 155 | + if ( |
| 156 | + !props.disabled && |
| 157 | + page > 0 && |
| 158 | + page <= props.totalPage && |
| 159 | + page !== props.modelValue |
| 160 | + ) { |
| 161 | + emit('update:modelValue', page); |
| 162 | + emit('change', page); |
| 163 | + } |
| 164 | +} |
| 165 | +
|
| 166 | +function toPage(pre) { |
| 167 | + if (props.disabled) { |
| 168 | + return; |
| 169 | + } |
| 170 | + const chunkSize = props.maxSize; |
| 171 | + const currentChunkStart = sliceStart.value; |
| 172 | + const lastChunkStart = props.totalPage - chunkSize; |
| 173 | + const start = pre |
| 174 | + ? currentChunkStart - chunkSize |
| 175 | + : currentChunkStart + chunkSize; |
| 176 | + if (start < 0) { |
| 177 | + sliceStart.value = 0; |
| 178 | + } else if (start > lastChunkStart) { |
| 179 | + sliceStart.value = lastChunkStart; |
| 180 | + } else { |
| 181 | + sliceStart.value = start; |
| 182 | + } |
| 183 | +} |
209 | 184 | </script> |
0 commit comments