Home > Article > Web Front-end > Use vue.js to create paging components
I have been studying vue.js for a while and used it to make two small components for practice.
I use webpack for packaging here, so I am familiar with its use.
The source code is placed at the github address at the end of the article.
First is index.html
<!DOCTYPE html> <html> <head> <title>Page</title> <style type="text/css"> * { margin: 0; padding: 0; font-family: 'Open Sans', Arial, sans-serif; } .contianer { width: 50%; height: auto; margin: 20px auto; } article { margin-bottom: 50px; } </style> </head> <body> <div class='contianer'> <article> 文章内容... </article> <div id='main'> <app></app> </div> </div> <script type="text/javascript" src='bundle.js'></script> </body> </html>
I put the app component inside c0d5f5130fcd018cc117943bd2c43ff616b28748ea4df4d9c2150843fecfba68
After packaging through webpack, the entry js file is entry.js, which is used to introduce the app.vue component
entry.js
let Vue = require('vue'); import App from './components/app'; let app_vue = new Vue({ el: '#main', components: { app: App } });
Let’s take a look at the app component
<style type="text/css" scoped> </style> <template> <comment :cur-page-index="curPageIndex" :each-page-size="eachPageSize" :comment-url="commentUrl" :comment-params="commentParams" :comment-is-sync="commentIsSync"> </comment> <page :cur-page-index.sync="curPageIndex" :each-page-size="eachPageSize" :page-url="pageUrl" :page-params="pageParams" :page-is-sync="pageIsSync"> </page> </template> <script type="text/javascript"> import Comment from './comment'; import Page from './page'; export default { data () { return { curPageIndex: 1, eachPageSize: 7, } }, components: { comment: Comment, page: Page }, } </script>
It has two sub-components, namely comment.vue and page.vue. Through dynamic binding of data, component communication between father and son is carried out. I think so, The current page should be passed from page.vue to app.vue, so here we use two-way binding, and the rest such as params, url, isSync, which is what requests data from the background and whether to operate synchronously or asynchronously
Next, take a look at the comment.vue comment component
<style type="text/css" scoped> .comt-mask { opacity: 0.5; } .comt-title { } .comt-line { width: 100%; height: 2px; background-color: #CCC; margin: 10px 0; } .comt-wrap { } .comt-user { float: left; } .comt-img { width: 34px; height: 34px; border-radius: 17px; } .comt-context { margin: 0 0 0 60px; } .comt-name { color: #2B879E; margin-bottom: 10px; font-size: 18px; } </style> <template> <div v-if="hasComment" :class="{'comt-mask': loading}"> <h3 class='comt-title'>{{ totalCommentCount }} 条评论</h3> <div class="comt-line"></div> <div class="comt-wrap" v-for="comment of commentArr"> <div class="comt-user"> <img src='{{ comment.avatar }}' class="comt-img"/> </div> <div class="comt-context"> <p class="comt-name">{{ comment.name }}</p> <p> {{ comment.context }} </p> </div> <div class="comt-line"></div> </div> </div> </template> <script type="text/javascript"> import {getCommentData, getTotalCommentCount} from './getData'; export default { props: { curPageIndex: { type: Number, default: 1, }, eachPageSize: { type: Number, default: 7, }, commentUrl: { type: String, default: '', }, commentParams: { type: Object, default: null, }, commentIsSync: { type: Boolean, default: true, }, }, data () { return { totalCommentCount: 0, hasComment: false, loading: true, } }, computed: { commentArr () { this.loading = true; let res = getCommentData(this.commentUrl, this.commentParams, this.commentIsSync, this.curPageIndex, this.eachPageSize); this.loading = false; return res; }, }, created () { let cnt = getTotalCommentCount(this.commentUrl, this.commentParams); this.totalCommentCount = cnt; this.hasComment = cnt > 0; } } </script>
The getData.js here will be mentioned below, which is where we get the data.
loading: The original intention is to load a mask with a transparency of 0.5 for the current comment when jumping to the page number to load comments, and then ajax cancels the mask through its callback function. Now this cannot be achieved and can only be forced to write , however it is useless..
hasComment: When the comment component is loaded for the first time, we will request the total data length. If there is no data, the comment component layout content will not be displayed
·curPageIndex·: It is passed down through the parent component app and uses props
. It is better for us to set a default value and type.
page.vue
<style type="text/css" scoped> .page { text-align: center; margin: 30px; } .page-btn { color: gray; background-color: white; border: white; width: 30px; height: 30px; margin: 5px; font-size: 18px; outline: none; } .page-btn-link { cursor: Crosshair; } .page-btn-active { border: 1px solid gray; border-radius: 15px; } </style> <template> <div class="page"> <button v-for="pageIndex of pageArr" track-by='$index' :class="{'page-btn': true, 'page-btn-active': this.curPageIndex === pageIndex, 'page-btn-link': checkNum(pageIndex)}" @click="clickPage(pageIndex)" > {{ pageIndex }} </button> </div> </template> <script type="text/javascript"> import {getTotalPageCount} from './getData'; export default { props: { totalPageCount: { type: Number, default: 0, }, curPageIndex: { type: Number, default: 1, }, eachPageSize: { type: Number, default: 7, }, pageAjcn: { type: Number, default: 4, }, pageUrl: { type: String, default: '', }, pageParams: { type: Object, default: null, }, pageIsSync: { type: Boolean, default: true, } }, data () { return { } }, computed: { pageArr () { let st = 1, end = this.totalPageCount, cur = this.curPageIndex, ajcn = this.pageAjcn, arr = [], left = Math.floor(ajcn / 2), right = ajcn - left; if (end == 0 || cur == 0) { return arr; } else { console.log(st, end, cur, left, right); arr.push(st); console.log(st+1, cur-left); if (st + 1 < cur - left) { arr.push('...'); } for (let i = Math.max(cur - left, st + 1); i <= cur - 1; ++i) { arr.push(i); } if (cur != st) { arr.push(cur); } for (let i = cur + 1; i <= cur + right && i <= end - 1 ; ++i) { arr.push(i); } if (cur + right < end - 1) { arr.push('...'); } if (end != cur) { arr.push(end); } return arr; } } }, methods: { clickPage (curIndex) { if (Number.isInteger(curIndex)) { this.curPageIndex = curIndex; } }, checkNum (curIndex) { return Number.isInteger(curIndex); } }, created () { this.totalPageCount = getTotalPageCount(this.pageUrl, this.pageParams, this.pageIsSync, this.eachPageSiz); } } </script>
is mainly the use of component events, = the most common click event, and the binding of class and style, compared according to curPageIndex and this.pageIndex , determine whether you have this class, and obtain the page number array through computed properties. Because it will change according to the current page, the total page number is calculated when created.
The last one is the js file currently generated to obtain static data.
// let data = { // avatar: '', 头像 // name: '', 用户名 // context: '', 评论内容 // } let dataArr = []; function randomStr (len) { return Math.random().toString(36).substr(len); } function initData () { for (var i = 0; i<45 ; ++i) { let _avator = "./resources/" + i%7 + ".jpg"; let _name = randomStr(20); let _context = randomStr(2); dataArr.push({ avatar: _avator, name: _name, context: _context }); } } if (!dataArr.length) { initData(); } export function getCommentData (url = '', params = null, isSync = true, curPageIndex = 1, eachPageSize = 7) { /* ajax */ let st = (curPageIndex - 1) * eachPageSize; let end = st + eachPageSize; return dataArr.slice(st, end); } export function getTotalCommentCount(url = '', params = null, isSync = true) { /* ajax */ return dataArr.length; } export function getTotalPageCount(url = '', params = null, isSync = true, eachPageSize = 7) { /* ajax */ return Math.floor((dataArr.length + eachPageSize -1 ) / eachPageSize); }
That’s it.
For more articles related to using vue.js to create paging components, please pay attention to the PHP Chinese website!