zoukankan      html  css  js  c++  java
  • 基于vue2.0实现仿百度前端分页效果(二)

    前言

    上篇文章中,已经使用vue实现前端分页效果,这篇文章我们单独将分页抽离出来实现一个分页组件

    先看实现效果图

    代码实现

    按照惯例,我们在冻手实现的时候还是先想一想vue实现组件的思路

    1、需要提前设定哪些参数需要暴露出来给父组件传递

    <Paging 
          :name="name"
          @change="onPageChange"
          :page-size="size"
          :total="total"
          layout="jumper,total"
          :current-page="curPage"
        />
    
    
    方法及参数说明
    属性 
    page-size 每页显示条目个数
    total 总条目数
    current-page 当前页数
    layout 布局 默认不显示 jumper,total
    
    事件
    change 当前页改变时触发
    

    2、再一个就是涉及到的父子组件通信

    这里主要通过props向子组件传递参数
    在子组件中使用emit自定义事件返回数据给父组件

    a.字符串数组形式props

    props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
    或者指定每个prop的值类型
    props: {
      title: String,
      likes: Number,
      isPublished: Boolean,
      commentIds: Array,
      author: Object
    }
    

    b.props验证

    props: {
        // 基础的类型检查 (`null` 匹配任何类型)
        propA: Number,
        // 多个可能的类型
        propB: [String, Number],
        // 必填的字符串
        propC: {
          type: String,
          required: true
        },
        // 带有默认值的数字
        propD: {
          type: Number,
          default: 100
        },
        // 带有默认值的对象
        propE: {
          type: Object,
          // 对象或数组默认值必须从一个工厂函数获取
          default: function () {
            return { message: 'hello' }
          }
        },
        // 自定义验证函数
        propF: {
          validator: function (value) {
            // 这个值必须匹配下列字符串中的一个
            return ['success', 'warning', 'danger'].indexOf(value) !== -1
          }
        }
      }
    

    使用props传递数据给子组件 ,子组件主要有三种形式来接收到父组件传递过来的参数
    props字符串数组、指定每个prop值类型以及props验证,通常我们会使用props验证

    分析完之后,接下来我们可以冻手实现了

    1、这里我们用vue-cli先创建一个vue项目

    安装vue-cli
    $npm install -g vue-cli
    
    创建vue项目
    $vue init webpack my-project
    
    项目运行
    $cd my-project
    $npm run dev
    

    2、在components文件下创建一个Paging组件

    <template>
      <div class="paging clearfix">
      	 <div class="page-size fl" v-if="isShowTotal">共{{total}}条</div>
    	   <ul class="page-list fl clearfix">
    			<li @click="changePage(currentPage-1)">上一页</li>
    			<li :class="{'active':currentPage==item.val}" v-for="item in pagelist" v-text="item.text" @click="changePage(item.val)">1</li>
    			<li @click="changePage(currentPage+1)">下一页</li>
    		</ul>
    		<div class="page-jump fl" v-if="isShowJumper">
    			前往<input class="input" type="text" v-model="toPage" @keydown="submit(toPage,$event)">页
    			<!-- <button  @click="changePage(toPage)">确定</button> -->
    		</div>
      </div>
    </template>
    
    <script>
    export default {
      name: 'Paging',
      // props:[
      // 	'name'
      // ],
      // prop验证
      props:{
      	name:String,
      	pageSize: {
          type: Number,
          default: 10
        },
        total: {
          type: Number,
          default: 0
        },
        currentPage: {
          type: Number,
          default: 1
        },
        layout:{
        	type: String
        }
      },
      data () {
        return {
    			isShowJumper:false,
    			isShowTotal:false,
      		toPage:'',//跳转到x页
    			pageGroup:10//可见分页数量 默认10个分页数
        }
      },
      created: function () {
    		console.log('created');
    		this.isShowTotal = this.layout.indexOf('total')!==-1;
    		this.isShowJumper = this.layout.indexOf('jumper')!==-1;
    	},
    	mounted: function () {
    		console.log('mounted',this.layout);
    	},
    	computed:{
    		totalPage:function(){
    			return Math.ceil(this.total / this.pageSize)
    		},
    		pagelist:function(){
    			var list = [];
    			var count = Math.floor(this.pageGroup/2), center = this.currentPage;
    			var left = 1,right = this.totalPage;
    
    			if(this.totalPage>this.pageGroup){
    				if(this.currentPage>count+1){
    					if(this.currentPage < this.totalPage - count){
    						left = this.currentPage - count;
    						right = this.currentPage + count-1;
    					}else{
    						left = this.totalPage - this.pageGroup+1;
    					}
    				}else{
    					right = this.pageGroup;
    				}
    			}
    
    			// 遍历添加到数组里
    			while(left<=right){
    				list.push({
    					text:left,
    					val:left
    				});
    				left++;
    			}
    			return list;
    		}
    	},
      methods:{
      	// 回车事件
      	submit(toPage,e){
      		// console.log('e.keyCode',toPage,e.keyCode)
            // key.Code === 13表示回车键 
            if(e.keyCode === 13){
                //逻辑处理
                this.changePage(toPage);
            }
        },
      	changePage:function(idx){
      		if(idx!=this.currentPage && idx>0 && idx<=this.totalPage){
    	  		// 触发父组件事件  pageChange会转换成小写pagechange
    	  		this.$emit('change',{curPage:Number(idx)});
    			}
      	}
    	}
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    *{
    		padding: 0;
    		margin: 0;
    }
    .fl{
    	float: left;
    }
    .clearfix:after{
    	display: block;
    	content: '';
    	clear: both;
    }
    .page-size{
    	    height: 26px;
        line-height: 26px;
    }
    .page-list{
    
    }
    .page-jump{
    	    height: 26px;
        line-height: 26px;
        margin-left: 20px;
    }
    .page-jump .input{
    	 32px;
    	    padding: 4px 2px;
        border-radius: 2px;
        border: 1px solid #dcdfe6;
        margin: 0 4px;
    }
    	ul{
    		list-style: none;
    	}
    	ul li{
    		float: left;
    		color: #606266;
    		background: #f4f4f5;
    		padding: 2px 8px;
    		cursor: pointer;
    		border-radius: 2px;
    		margin: 0 5px;
    	}
    	ul>li.active{
    		background: #409eff;
    		color:#fff;
    	}
    </style>
    

    3、在父组件中引入并使用组件

    <template>
      <div>
        <!-- 分页组件 -->
        <Paging 
          :name="name"
          @change="onPageChange"
          :page-size="size"
          :total="total"
          layout="jumper,total"
          :current-page="curPage"
        />
      </div>
    </template>
    
    
    <!-- 
    Paging属性 
    page-size 每页显示条目个数
    total 总条目数
    current-page 当前页数
    layout 布局 默认不显示 jumper,total
    
    Paging事件
    change 当前页改变时触发
     -->
    <script>
    
    import Paging from '@/components/Paging';
    export default {
      name: 'Index',
      components:{
      	Paging
      },
      data () {
        return {
          msg: 'hello',
          name:'阿健a',
          size:10,
          total:201,
          curPage:1
        }
      },
      methods:{
        onPageChange:function(page){
          this.curPage = page.curPage;
        }
      }
    }
    </script>
    

    遇到的问题

    1、在子组件中修改currentPage时报错

    Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders
    

    在使用组件时,传入的prop,被组件内部又做了一次修改
    避免直接修改prop,因为当父组件重新呈现时,值将被覆盖

    changePage:function(idx){
      		if(idx!=this.currentPage && idx>0 && idx<=this.totalPage){
      			this.currentPage = idx;
    	  		// 触发父组件事件  pageChange会转换成小写pagechange
    	  		this.$emit('change');
    			}
      	}
    

    解决
    修改代码,通过emit传递curPage给父组件,让父组件修改

    changePage:function(idx){
      		if(idx!=this.currentPage && idx>0 && idx<=this.totalPage){
    	  		// 触发父组件事件  pageChange会转换成小写pagechange
    	  		this.$emit('change',{curPage:idx});
    			}
      	}
    

    父组件监听事件更新curPage

    onPageChange:function(page){
          this.curPage = page.curPage;
        }
    

    最后

    以上就是分页组件的整个实现过程 ,其实只要搞清楚父子组件是如何传参的,以及我们实现一个组件需要暴露哪些参数给父组件,整个实现过程还是不难的

  • 相关阅读:
    01-复杂度2. Maximum Subsequence Sum (25)
    11136-Hoax or what
    VS2010/MFC常用控件:图片控件Picture Control
    VS2010/MFC对话框:向导对话框的创建及显示
    VS2010/MFC对话框:一般属性页对话框的创建及显示
    VS2010/MFC字体和文本输出:文本输出
    VS2010/MFC对话框:颜色对话框
    VS2010/MFC对话框:字体对话框
    VS2010/MFC对话框:文件对话框
    VS2010/MFC对话框:消息对话框
  • 原文地址:https://www.cnblogs.com/fozero/p/9874334.html
Copyright © 2011-2022 走看看