pagination.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. import Pager from './pager.vue';
  2. import ElSelect from 'element-ui/packages/select';
  3. import ElOption from 'element-ui/packages/option';
  4. import Migrating from 'element-ui/src/mixins/migrating';
  5. import { $t } from 'element-ui/src/locale';
  6. export default {
  7. name: 'ElPagination',
  8. mixins: [Migrating],
  9. props: {
  10. pageSize: {
  11. type: Number,
  12. default: 10
  13. },
  14. small: Boolean,
  15. total: Number,
  16. pageCount: Number,
  17. currentPage: {
  18. type: Number,
  19. default: 1
  20. },
  21. layout: {
  22. default: 'prev, pager, next, jumper, ->, total'
  23. },
  24. pageSizes: {
  25. type: Array,
  26. default() {
  27. return [10, 20, 30, 40, 50, 100];
  28. }
  29. }
  30. },
  31. data() {
  32. return {
  33. internalCurrentPage: 1,
  34. internalPageSize: 0
  35. };
  36. },
  37. render(h) {
  38. let template = <div class='el-pagination'></div>;
  39. const layout = this.layout || '';
  40. if (!layout) return;
  41. const TEMPLATE_MAP = {
  42. prev: <prev></prev>,
  43. jumper: <jumper></jumper>,
  44. pager: <pager currentPage={ this.internalCurrentPage } pageCount={ this.internalPageCount } on-change={ this.handleCurrentChange }></pager>,
  45. next: <next></next>,
  46. sizes: <sizes></sizes>,
  47. slot: <slot></slot>,
  48. total: <total></total>
  49. };
  50. const components = layout.split(',').map((item) => item.trim());
  51. const rightWrapper = <div class="el-pagination__rightwrapper"></div>;
  52. let haveRightWrapper = false;
  53. if (this.small) {
  54. template.data.class += ' el-pagination--small';
  55. }
  56. components.forEach(compo => {
  57. if (compo === '->') {
  58. haveRightWrapper = true;
  59. return;
  60. }
  61. if (!haveRightWrapper) {
  62. template.children.push(TEMPLATE_MAP[compo]);
  63. } else {
  64. rightWrapper.children.push(TEMPLATE_MAP[compo]);
  65. }
  66. });
  67. if (haveRightWrapper) {
  68. template.children.push(rightWrapper);
  69. }
  70. return template;
  71. },
  72. components: {
  73. Prev: {
  74. render(h) {
  75. return (
  76. <button
  77. class={['btn-prev', { disabled: this.$parent.internalCurrentPage <= 1 }]}
  78. on-click={ this.$parent.prev }>
  79. <i class="el-icon el-icon-arrow-left"></i>
  80. </button>
  81. );
  82. }
  83. },
  84. Next: {
  85. render(h) {
  86. return (
  87. <button
  88. class={
  89. [
  90. 'btn-next',
  91. { disabled: this.$parent.internalCurrentPage === this.$parent.internalPageCount || this.$parent.internalPageCount === 0 }
  92. ]
  93. }
  94. on-click={ this.$parent.next }>
  95. <i class="el-icon el-icon-arrow-right"></i>
  96. </button>
  97. );
  98. }
  99. },
  100. Sizes: {
  101. created() {
  102. if (Array.isArray(this.$parent.pageSizes)) {
  103. this.$parent.internalPageSize = this.$parent.pageSizes.indexOf(this.$parent.pageSize) > -1
  104. ? this.$parent.pageSize
  105. : this.$parent.pageSizes[0];
  106. }
  107. },
  108. render(h) {
  109. return (
  110. <span class="el-pagination__sizes">
  111. <el-select
  112. size="small"
  113. value={ this.$parent.internalPageSize }
  114. on-change={ this.handleChange }
  115. width={ 110 }>
  116. {
  117. this.$parent.pageSizes.map(item =>
  118. <el-option
  119. value={ item }
  120. label={ item + ' ' + $t('el.pagination.pagesize') }>
  121. </el-option>
  122. )
  123. }
  124. </el-select>
  125. </span>
  126. );
  127. },
  128. components: {
  129. ElSelect,
  130. ElOption
  131. },
  132. methods: {
  133. handleChange(val) {
  134. if (val !== this.$parent.internalPageSize) {
  135. this.$parent.internalPageSize = val = parseInt(val, 10);
  136. this.$parent.$emit('size-change', val);
  137. }
  138. }
  139. }
  140. },
  141. Jumper: {
  142. data() {
  143. return {
  144. oldValue: null
  145. };
  146. },
  147. methods: {
  148. handleFocus(event) {
  149. this.oldValue = event.target.value;
  150. },
  151. handleChange({ target }) {
  152. this.$parent.internalCurrentPage = this.$parent.getValidCurrentPage(target.value);
  153. this.$parent.$emit('current-change', this.$parent.internalCurrentPage);
  154. this.oldValue = null;
  155. }
  156. },
  157. render(h) {
  158. return (
  159. <span class="el-pagination__jump">
  160. { $t('el.pagination.goto') }
  161. <input
  162. class="el-pagination__editor"
  163. type="number"
  164. min={ 1 }
  165. max={ this.internalPageCount }
  166. domProps-value={ this.$parent.internalCurrentPage }
  167. on-change={ this.handleChange }
  168. on-focus={ this.handleFocus }
  169. style={{ width: '30px' }}
  170. number/>
  171. { $t('el.pagination.pageClassifier') }
  172. </span>
  173. );
  174. }
  175. },
  176. Total: {
  177. render(h) {
  178. return (
  179. typeof this.$parent.total === 'number'
  180. ? <span class="el-pagination__total">{ $t('el.pagination.total', { total: this.$parent.total }) }</span>
  181. : ''
  182. );
  183. }
  184. },
  185. Pager
  186. },
  187. methods: {
  188. getMigratingConfig() {
  189. return {
  190. props: {},
  191. events: {
  192. 'currentchange': 'Pagination: currentchange has been renamed to current-change',
  193. 'sizechange': 'Pagination: sizechange has been renamed to size-change'
  194. }
  195. };
  196. },
  197. handleCurrentChange(val) {
  198. this.internalCurrentPage = this.getValidCurrentPage(val);
  199. this.$emit('current-change', this.internalCurrentPage);
  200. },
  201. prev() {
  202. const oldPage = this.internalCurrentPage;
  203. const newVal = this.internalCurrentPage - 1;
  204. this.internalCurrentPage = this.getValidCurrentPage(newVal);
  205. if (this.internalCurrentPage !== oldPage) {
  206. this.$emit('current-change', this.internalCurrentPage);
  207. }
  208. },
  209. next() {
  210. const oldPage = this.internalCurrentPage;
  211. const newVal = this.internalCurrentPage + 1;
  212. this.internalCurrentPage = this.getValidCurrentPage(newVal);
  213. if (this.internalCurrentPage !== oldPage) {
  214. this.$emit('current-change', this.internalCurrentPage);
  215. }
  216. },
  217. getValidCurrentPage(value) {
  218. value = parseInt(value, 10);
  219. const havePageCount = typeof this.internalPageCount === 'number';
  220. let resetValue;
  221. if (!havePageCount) {
  222. if (isNaN(value) || value < 1) resetValue = 1;
  223. } else {
  224. if (value < 1) {
  225. resetValue = 1;
  226. } else if (value > this.internalPageCount) {
  227. resetValue = this.internalPageCount;
  228. }
  229. }
  230. if (resetValue === undefined && isNaN(value)) {
  231. resetValue = 1;
  232. } else if (resetValue === 0) {
  233. resetValue = 1;
  234. }
  235. return resetValue === undefined ? value : resetValue;
  236. }
  237. },
  238. computed: {
  239. internalPageCount() {
  240. if (typeof this.total === 'number') {
  241. return Math.ceil(this.total / this.internalPageSize);
  242. } else if (typeof this.pageCount === 'number') {
  243. return this.pageCount;
  244. }
  245. return null;
  246. }
  247. },
  248. watch: {
  249. internalPageCount(newVal) {
  250. /* istanbul ignore if */
  251. if (newVal > 0 && this.internalCurrentPage === 0) {
  252. this.internalCurrentPage = 1;
  253. this.$emit('current-change', 1);
  254. } else if (this.internalCurrentPage > newVal) {
  255. this.internalCurrentPage = newVal;
  256. this.$emit('current-change', newVal);
  257. }
  258. },
  259. currentPage: {
  260. immediate: true,
  261. handler(val) {
  262. this.internalCurrentPage = val;
  263. }
  264. },
  265. pageSize: {
  266. immediate: true,
  267. handler(val) {
  268. this.internalPageSize = val;
  269. }
  270. },
  271. internalCurrentPage(newVal, oldVal) {
  272. newVal = parseInt(newVal, 10);
  273. /* istanbul ignore if */
  274. if (isNaN(newVal)) {
  275. newVal = oldVal || 1;
  276. } else {
  277. newVal = this.getValidCurrentPage(newVal);
  278. }
  279. if (newVal !== undefined) {
  280. this.$nextTick(() => {
  281. this.internalCurrentPage = newVal;
  282. });
  283. }
  284. }
  285. }
  286. };