I have learned vue.js for a while and used it to make 2 widgets and practice it.
I use webpack to package it, so I'm familiar with its use.
The source code is placed on 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 content... </article> <div id='main'> <app></app> </div> </div> <script type="text/javascript" src='bundle.js'></script></body></html>I put the app component in <div id='main'></div>
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 }});Next, let's 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 2 child components, namely comment.vue and page.vue. By dynamically binding data, it conducts parent-child component communication. I think so, for the page currently on which page should be passed to app.vue, so here we use two-way binding, the rest such as params, url, isSync, that is, things that request data from the background and whether to operate synchronously or asynchronously <Of course, I have not tested the background data here, and currently generate static data 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 }} Comments</h3> <div></div> <div v-for="comment of commentArr"> <div> <img src='{{ comment.avatar }}'/> </div> <div> <p>{{ comment.name }}</p> <p> {{ comment.context }} </p> </div> <div></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 meaning is to load a 0.5 transparency mask for the current comment when the page number is loaded, and then ajax will cancel the mask through its callback function. Now this cannot be implemented, so you can only write it down by force, but it is useless..
hasComment: When the comment component is loaded for the first time, we request to obtain the total data length. If there is no data, the comment component layout content will not be displayed.
・curPageIndex・: Passed through the parent component app, using props
We set a default value and type of these data.
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> <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 a use of component events, = the most common click event, and the binding between class and style. Compare it according to curPageIndex and this.pageIndex to determine whether you have this class. Use computed to calculate the attributes to obtain the page number array because it will change according to the current page, and calculate the total page number when created.
The last one is the currently generated js file that gets static data.
// let data = {// avatar: '', avatar// name: '', username// 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