Making paging components with vue. js

  • 2021-07-01 06:11:25
  • OfStack

Learn vue. js1 period of time, take it to do 2 small components, practice 1.
I use webpack to package here, and I am familiar with its application.
The source code is placed at the github address at the end of the text.

The 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>
    Content of the article ...
  </article>
  <div id='main'>
   <app></app>  
  </div>
 </div>
 <script type="text/javascript" src='bundle.js'></script>
</body>
</html>

I put the app component in the < div id='main' > < /div > Inside
After being packaged by webpack, the entry js file is entry. js, which is used to introduce app. vue components
entry.js


let Vue = require('vue');

import App from './components/app';

let app_vue = new Vue({
 el: '#main',
 components: {
  app: App
 }
});

Next, take a look at this 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, comment. vue and page. vue, through dynamic binding of data, component communication between father and son, I think so, for the current page should be passed from page. vue to app. vue, so here we use bidirectional binding, the rest such as params, url, isSync, that is, to request data from the background and whether synchronous or asynchronous operation < Of course, I haven't tested the backstage data yet. At present, the static data is generated directly by js > .

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 }}  A comment </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>

Here, getData. js, which will be mentioned below, is where we get the data.
loading: The original intention is to load a mask of 0.5 transparency for the current comment when loading the comment by jumping page number, and then ajax cancels the mask through its callback function. Now this can't be realized, but it can only be written by force, but it is useless.
hasComment: When the comment component is loaded for the first time, we ask for the total data length. If there is no data, the layout content of comment component will not be displayed
• curPageIndex •: Passed down through the parent component app, using props
For these data, we all set a default value with a better 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>

It is mainly the application of component events, = the most common click events, and the binding between class and style. According to the comparison between curPageIndex and this. pageIndex, judge whether you have this class, and calculate the attribute through computed to obtain the page number array because it will change according to the current page. When created, calculate the total page number.
The last one is the js file that is currently generated to obtain static data.


// let data = {
//  avatar: '',  Head portrait 
//  name: '',  User name 
//  context: '',  Comment content 
// }
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.

github Address


Related articles: