vue实现前台列表数据过滤搜索、分页效果

本文实例为大家分享了vue实现列表数据过滤搜索、分页效果的具体代码,供大家参考,具体内容如下

job.vue页面

<style lang="scss">
.job-wrapper {
 padding-top: 50px;
}
.job-left {
 float: left;
 margin-right: 20px;
 padding: 20px;
 width: 310px;
 background: #fff;
}
.job-serach-title {
 margin: 8px 0 10px 0;
 color: rgb(51, 51, 51);
 font-size: 16px;
}

.job-search-input {
 display: flex;
}
.job-keywords {
 width: 400px;
}
.job-search-btn {
 display: flex;
 align-items: center;
 justify-content: center;
 margin-left: 10px;
 width: 50px;
 height: 40px;
 border-radius: 4px;
 background-color: rgb(254, 62, 98);
}
.line {
 margin: 25px 0 0 0;
 width: 100%;
 height: 1px;
 background: #dfdfdf;
}

.halogg {
 margin-top: 30px;
 color: rgb(102, 102, 102);
 font-weight: 300;
 font-size: 14px;
}
.job-right {
 float: right;
 width: 870px;
 background: #fff;
}
</style>

<style lang="scss">
// 重置样式
#job-select-1,
#job-select-2 {
 margin-top: 20px;
 select {
 width: 100%;
 }
}
</style>
<template>
 <article class="job">

 <div class="job-content layout">
  <div class="job-wrapper">
  <div class="job-left">
   <div class="job-serach-title">搜索更多职位</div>
   <div class="job-search-input">
   <input v-model.trim="formData.keywords" @change="searchData" placeholder="搜索更多职位" class="job-keywords" />
   <div class="job-search-btn pointer" @click="searchData">
    搜
   </div>
   </div>
   <div class="line"></div>
   <div class="job-select" id="job-select-1">
   <select v-model="formData.address" @change="searchData">
    <option v-for="item,index in regionArr" :key="index">{{item.name}}</option>
   </select>
   </div>
   <div class="job-select" id="job-select-2">
   <select v-model="formData.title" @change="searchData">
    <option v-for="(item,index) in searchList" :key="index">{{item}}</option>
   </select>
   </div>
  </div>
  <div class="job-right">
   <joblist></joblist>
  </div>
  </div>

 </div>
 </article>
</template>
<script>
import joblist from 'src/components/job/list';
import { mapGetters, mapActions, mapMutations } from 'vuex';

export default {
 name: 'reportFormIndex',
 data() {
 return {
  formData: {
  title: '',
  address: '',
  keywords: '',
  },
 };
 },
 computed: {
 ...mapGetters(['searchList', 'regionArr', 'show']),
 },
 watch: {},
 title() {
 return '行业';
 },
 methods: {
 ...mapActions(['getData']),
 // select 选中后的回调数据
 searchData() {
  const payload = {
  formData: Object.assign({}, this.formData),
  pageIndex: 0, // 每次搜索后, 显示搜索结果的第一页
  };
  this.$store.commit('setState', payload);
 },
 },
 mounted() {
 this.$nextTick(() => {
  this.getData();
 });
 },
 components: {
 joblist,
 },
};
</script>

组件list.vue

<style lang="scss">
.list-header {
 position: relative;
 display: flex;
 padding: 25px 30px 20px 30px;
 color: rgb(153, 153, 153);
 font-size: 14px;
 &:after {
 position: absolute;
 right: 0;
 bottom: 0;
 left: 0;
 display: inline-block;
 width: 100%;
 height: 1px;
 background-color: #dfdfdf;
 content: '';
 }
}
.l-header-item-1 {
 padding-left: 20px;
 width: 37.3%;
}
.l-header-item-2 {
 padding-left: 10px;
 width: 32.7%;
}
.l-header-item-3 {
 padding-left: 10px;
 width: 18.7%;
}
.l-header-item-4 {
 display: flex;
 width: 11.3%;
 .open {
 color: #3e8bf5;
 text-decoration: underline;
 font-size: 14px;
 }
 .arrow-open {
 margin-top: 5px;
 margin-left: 5px;
 width: 11px;
 height: 7px;
 transition: all 0.5s linear;
 }
}
.inner-item {
 padding: 0 30px;
}
.inner-box {
 position: relative;
 display: flex;
 padding: 25px 0;
 color: rgb(51, 51, 51);
 font-size: 16px;
 transition: all 0.5s linear;
 &:after {
 position: absolute;
 right: 0px;
 bottom: 0;
 left: 0px;
 display: inline-block;
 height: 1px;
 background-color: #dfdfdf;
 content: '';
 }
}
//
.list-item {
 &.active {
 .list-show-detail {
  visibility: visible;
  padding: 0 50px;
  max-height: 1000px;
  transition: all 0.5s linear;
 }
 .inner-box {
  background: #f2f2f2;
  transition: all 0.5s linear;
  &:after {
  background-color: transparent;
  }
 }
 .arrow-open {
  transition: all 0.5s linear;
  transform: rotate(-180deg);
 }
 }
}
.list-show-detail {
 visibility: hidden;
 max-height: 0;
 transition: all 0.5s linear;
}
.list-task-title {
 margin: 25px 0 15px 0;
 color: rgb(51, 51, 51);
 font-size: 14px;
}

.list-task-item {
 color: rgb(102, 102, 102);
 font-size: 14px;
 line-height: 1.714;
}
.list-apply {
 display: flex;
 align-items: center;
 justify-content: center;
 margin: 25px 0 30px 0;
 width: 140px;
 height: 50px;
 border-radius: 4px;
 background-color: rgb(254, 62, 98);
 color: rgb(255, 255, 255);
 font-size: 16px;
}

/////pagination
.job-pagination {
 padding: 50px 0;
 .pagination-wrapper {
 display: flex;
 justify-content: center;
 margin: 0 auto;
 width: 100%;
 .subscript {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 5px;
  width: 28px;
  height: 28px;
  border: 1px solid rgb(223, 223, 223);
  border-radius: 4px;
  color: blue;
  color: rgb(102, 102, 102);
  text-align: center;
  font-size: 14px;

  &.active {
  border: 1px solid rgb(254, 62, 98);
  background-color: rgb(254, 62, 98);
  color: #fff;
  }
 }
 .pagination-page {
  display: inline-block;
  width: 7px;
  height: 11px;
  background-image: url('./images/arrow.png');
  &.pagination-next {
  transform: rotate(180deg);
  }
 }
 }
}
////
.job-no-data {
 padding: 100px 0;
 .job-no-data-img {
 margin: 0 auto;
 width: 170px;
 height: 170px;
 background-image: url('./images/job@2x.png');
 background-size: cover;
 background-repeat: no-repeat;
 }
 .job-no-data-msg {
 margin-top: 10px;
 color: rgb(51, 51, 51);
 text-align: center;
 font-size: 18px;
 line-height: 2.778;
 }
}

@media only screen and (max-width: 1200px) {
 .list-header {
 padding: 25px 30px 20px 30px;
 }
}

@media only screen and (max-width: 767px) {
 .list-header {
 padding: 20px 15px 15px 15px;
 }
 .inner-item {
 padding: 0px 15px 0 15px;
 &:after {
  right: 15px;
  left: 15px;
  transform: scaleY(0.5);
 }
 }

 .l-header-item-1 {
 padding-left: 10px;
 }
 .l-header-item-2 {
 padding-left: 10px;
 width: 28.7%;
 }
 .l-header-item-3 {
 padding-left: 10px;
 width: 19.7%;
 }
 .l-header-item-4 {
 width: 14.3%;
 }
}
</style>
<template>
 <article id="list">
 <ul class="list-wrapper">
  <li class="list-header">
  <div class="l-header-item-1">职位名称</div>
  <div class="l-header-item-2">职位分类</div>
  <div class="l-header-item-3">所在地区</div>
  <div class="l-header-item-4"></div>
  </li>
  <li class="list-item" v-for="(item,index) in curList" :key="index" :class="{'active':item.show}" v-show="curList.length">
  <div class="inner-item">
   <div class="inner-box">
   <div class="list-position l-header-item-1">{{item.position}}</div>
   <div class="list-title l-header-item-2">{{item.title}}</div>
   <div class="list-address l-header-item-3">{{item.address}}</div>
   <div class="list-action l-header-item-4 pointer" @click="showHandler(item.id)">
    <span class="open">展开</span>
    <img src="./images/arrow-open.png" alt="" class="arrow-open">
   </div>
   </div>
  </div>
  <transition name="el-zoom-in-top">
   <div class="list-show-detail" v-show="item.show">
   <div class="list-task-title">岗位职责:</div>
   <div class="list-task-wrapper">
    <div class="list-task-item" v-for="(item2,index2) in item.task" :key="index2">{{item2}}</div>
   </div>
   <div class="list-task-title">岗位要求:</div>
   <div class="list-task-wrapper">
    <div class="list-task-item" v-for="(item3,index3) in item.rule" :key="index3">{{item3}}</div>
   </div>
   </div>
  </transition>
  </li>
  <li class="job-no-data" v-show="!curList.length">
  <div class="job-no-data-img"></div>
  <div class="job-no-data-msg">暂未合适的职位</div>
  </li>
  <li class="job-pagination" v-show="curList.length">
  <div class="pagination-wrapper">
   <span class="subscript pointer" @click="prev">
   <span class="pagination-prev pagination-page"></span>
   </span>
   <span class="subscript pointer" @click="selectPageHandler(index - 1)" v-for="index in pageLength" :key="index" :class="{active: pageIndex === index - 1}">{{index}}</span>
   <span class="subscript pointer" @click="next">
   <span class="pagination-next pagination-page"></span>
   </span>
  </div>
  </li>
 </ul>

 </article>
</template>
<script>
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex';

const PER_PAGE = 8; // 每页显示多少个

export default {
 name: 'list',
 data() {
 return {};
 },
 computed: {
 ...mapState({
  // pageIndex: state => state.job.pageIndex,
 }),
 ...mapGetters(['filterJobList', 'pageIndex']),
 curList() {
  const { filterJobList, pageIndex } = this;
  const startIndex = pageIndex * PER_PAGE;
  const endIndex = startIndex + PER_PAGE;
  return filterJobList.slice(startIndex, endIndex);
 },
 pageLength() {
  const { filterJobList } = this;
  if (filterJobList.length) {
  return Math.ceil(filterJobList.length / PER_PAGE);
  }
  return 0;
 },
 },
 methods: {
 ...mapActions(['showAndHide']),
 // 操作 展开 隐藏
 showHandler(id) {
  this.showAndHide(id);
 },
 selectPageHandler(pageIndex) {
  this.$store.commit('setState', {
  pageIndex,
  });
  //同时关闭已经打开的职位详情页
  this.$store.commit('hideAllDetailMutations');
 },
 // 上一页
 prev() {
  this.$store.commit('prevMutations');
 },
 // 下一页
 next() {
  this.$store.commit('nextMutations', this.pageLength);
 },
 },
 mounted() {},
 components: {},
};
</script>

store/job.js

import { unique } from 'src/assets/script/util.js';
import jobData from 'src/views/job/data.js';

// 初始状态
const state = {
 realData: [],
 searchList: [],
 regionArr: [{
   name: '上海',
   id: 1,
  },
  {
   name: '武汉',
   id: 2,
  },
 ],
 // 右侧搜索,用户输入
 formData: {
  title: '', // 职位分类
  address: '', // 地区
  keywords: '', // 搜索更多职位
 },
 pageIndex: 0, // 第 0 页
 show: false, // 申请工作的 modal
 ApplyJobPosition: '' // 申请工作的职位
};

// 读取数据
const getters = {
 ApplyJobPosition: state => state.ApplyJobPosition,
 show: state => state.show,
 pageIndex: state => state.pageIndex,
 regionArr: state => state.regionArr,
 searchList: state => {
  const cache = [];
  state.realData.forEach(n => {
   cache.push(n.title);
  });
  return unique(cache);
 },
 // 符合条件的职位
 filterJobList({ realData, formData }) {
  const { title, address, keywords } = formData;

  return (
   realData
   // 职位筛选逻辑
   .filter(item => {
    let matchAddress = true; // 地区筛选
    let matchPosition = true; // 职位筛选
    let matchKeywrod = true; // 关键字 筛选
    if (title) {
     matchPosition = item.title === title;
    }
    if (address) {
     matchAddress = item.address === address;
    }
    if (keywords) {
     // 模糊搜索;
     const keys = keywords
      .toUpperCase() // 转大写
      .replace(' ', '') // 删掉空格
      .split(''); // 切割成 单个字

     matchKeywrod = keys.every(key => item.position.toUpperCase().includes(key));
    }
    return matchAddress && matchPosition && matchKeywrod;
   })
  );
 },
};

// 数据改变
const mutations = {

 // 从json文件直接获取元数据
 getDataMutations(state, jobData) {
  state.realData = jobData;
 },
 // 职位详情 显示/隐藏
 showAndHideMutations(state, id) {
  state.realData.forEach((n, i) => {
   if (id === n.id) {
    n.show = !n.show;
   }
  });
 },
 // 职位详情 全部隐藏
 hideAllDetailMutations(state) {
  state.realData.forEach((n, i) => {
   n.show = false;
  });
 },
 setState(state, payload = {}) {
  // console.log('payload', payload);
  Object.entries(payload).forEach(([key, value]) => {
   state[key] = value;
  });
 },
 // prev
 prevMutations(state, payload = {}) {
  if (!state.pageIndex) {
   return;
  }
  state.pageIndex--
 },
 // next
 nextMutations(state, payload = {}) {
  // console.info(state.pageIndex, payload)
  if (state.pageIndex < payload - 1) {
   state.pageIndex++
  }

 },
 // open modal
 openApplyJobModal(state, payload = {}) {
  state.show = true
  state.ApplyJobPosition = payload
 },
 //close modal
 closeApplyJobModal(state) {
  state.show = false
 },
};

// 逻辑响应
const actions = {
 getData({ commit }) {
  commit('getDataMutations', jobData);
 },
 // 显示 隐藏
 showAndHide({ commit }, id) {
  commit('showAndHideMutations', id);
 },
};

export default {
 state,
 getters,
 actions,
 mutations,
};

util.js

// 数组去重
export function unique(arr) {  
 var newArr = [arr[0]];  
 for (var i = 1; i < arr.length; i++) {    
  if (newArr.indexOf(arr[i]) == -1) {   newArr.push(arr[i]);   }
 }
 return newArr;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • vue实现搜索过滤效果

    本文实例为大家分享了vue实现搜索过滤效果的具体代码,供大家参考,具体内容如下 html: <table id="tfhover_1" class="tftable_1" border="1"> <tr> <th>名称</th> <th>链接状态</th> <th>IP</th> <th>特例类型</th> <th>

  • Vue 仿百度搜索功能实现代码

    无上下选择 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>jsonp</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, us

  • vue实现搜索功能

    本文实例为大家分享了vue实现搜索功能的具体代码,供大家参考,具体内容如下 methods (要有一定的触发条件才能执行,如点击事件) <template> <div class="safetyInfo"> <input type="text" name="" id="" placeholder="搜索" v-model="search"/> <

  • 基于Vue.js的表格分页组件

    一.Vue.js简介 1.Vue的主要特点: (1) 简洁 (2) 轻量 (3)快速 (4) 数据驱动 (5) 模块友好 (6) 组件化 (1) 简洁 下面看一段Angular的实现双向绑定的代码 // html <body ng-app="myApp"> <div ng-controller="myCtrl"> <p>{{ note }}</p> <input type="text" ng-

  • vue实现多条件和模糊搜索功能

    本文实例为大家分享了vue实现多条件和模糊搜索的具体代码,供大家参考,具体内容如下 html <div class="content"> <div class="right"> <select name="sex" width='100' v-model="formData.sex"> <option value="" selected>请选择</opt

  • 利用vue + element实现表格分页和前端搜索的方法

    前言 ElementUI是饿了么前端开源的一个基于Vue的前端框架,已经帮我们封装好了一系列功能性的组件,比如栅格系统.表格.表单.树形菜单.通知等.对于搞后台管理界面的项目,特别是不需要考虑兼容ie8.ie9以下的项目.ElementUI是一个不错的选择. 而且ElementUI的文档写得十分详尽,参照demo可以很快上手. 本文主要介绍了关于vue + element实现表格分页和前端搜索的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 实现思路 1.前端后台管理

  • vuejs通过filterBy、orderBy实现搜索筛选、降序排序数据

    直接贴代码了: 先上输入前的样子: <style> #example{margin:100px auto;width:600px;} .show{margin:10px;} #searchText{display: block;margin:0 auto 10px;height:24px;line-height: 24px;width:200px;} .content ul li{text-align: center;} .content ul li span{display: inline-

  • 基于Vue.js实现简单搜索框

    在github上看到的练习,看个遍代码后自己再练一遍,先放原址:https://github.com/lavyun/vue-demo-search 主要用到的知识很简单,简单的vuejs2.0的知识就够了.源码用了.vue构建和ES6,用了webpack打包等等.我资历还浅,先用一个简单的.js的写. 先看效果 这里有两个组件,一个组件是logo部分的,一个是搜索框部分的. html html很简单,就是引用两个组件. <div id="app"> <logo-pic

  • Vue.js实现分页查询功能

    本文实例为大家分享了Vue.js实现分页查询的具体代码,供大家参考,具体内容如下 vue.js的使用如下: 1.引入vue.js <script src="~/js/vue2.2.4.js"></script> a.分页条 <ul class="pagination" id="pagination1"></ul> b.分页条js.css <link href="~/css/page.

  • vue实现前台列表数据过滤搜索、分页效果

    本文实例为大家分享了vue实现列表数据过滤搜索.分页效果的具体代码,供大家参考,具体内容如下 job.vue页面 <style lang="scss"> .job-wrapper { padding-top: 50px; } .job-left { float: left; margin-right: 20px; padding: 20px; width: 310px; background: #fff; } .job-serach-title { margin: 8px

  • 基于Vue.js 2.0实现百度搜索框效果

    使用Vue.js 2.0 模仿百度搜索框效果,供大家参考,具体内容如下 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=2.0, maximum-scale=1.0, minimum

  • Zend Framework框架实现类似Google搜索分页效果

    本文实例讲述了Zend Framework框架实现类似Google搜索分页效果.分享给大家供大家参考,具体如下: /** * * @param unknown_type $model 表类型 * @param unknown_type $ncontroller 那个控制器提交的controller * @param unknown_type $naction 那个action提交的action */ public function fenyepage2($model,$ncontroller,$

  • Vue element商品列表的增删改功能实现

    目录 介绍 基本信息 上传主图 商品信息vue富文本编辑器的配置 最后提交数据 介绍 整体和用户列表 类似 功能步骤有: 面包屑导航 外部是大的卡片组件 搜索商品 添加商品 表格渲染数据 作用域插槽用于 操作按钮 分页器组件的使用 不一样的点:之前编辑信息 新增信息是 弹出对话框编辑 但商品信息内容较多 我们跳转到一个组件.并且进行商品编辑的时候要进行路由传参 来渲染初始数据 点击添加商品按钮时跳转到新增商品组件对应路径: addGoods(){ this.$router.push('/good

  • jQuery插件select2利用ajax高效查询大数据列表(可搜索、可分页)

    select2是一款jQuery插件,是普通form表单select组件的升级版. 可以定制搜索.远程数据集(Remote data,本篇主要介绍点).无限滚动(数据分页功能,这一点很妙).还有很多高端的参数设置(有需要的下次介绍). 内置了40种国际化语言,不过这里我们只需要用到中文. 同时支持现代和传统浏览器内置,甚至包括惹人不高兴的IE8. 那么,现在让我们开始一段select2的奇幻之旅吧! 一.惊艳的效果,来一睹为快吧 本地实战结果 二.导入css和js到网站上 1.使用CDN,节省自

  • DataTables+BootStrap组合使用Ajax来获取数据并且动态加载dom的方法(排序,过滤,分页等)

    Datatables是一款jquery表格插件.它是一个高度灵活的工具,可以将任何HTML表格添加高级的交互功能. 主要功能 分页,即时搜索和排序 几乎支持任何数据源:DOM, javascript, Ajax 和 服务器处理 支持不同主题 DataTables, jQuery UI, Bootstrap, Foundation 各式各样的扩展: Editor, TableTools, FixedColumns -- 丰富多样的option和强大的API 支持国际化 超过2900+个单元测试 免

  • vue主动刷新页面及列表数据删除后的刷新实例

    1.场景 在处理列表时,常常有删除一条数据或者新增数据之后需要重新刷新当前页面的需求. 2.遇到的问题 1. 用vue-router重新路由到当前页面,页面是不进行刷新的 2.采用window.reload(),或者router.go(0)刷新时,整个浏览器进行了重新加载,闪烁,体验不好 3.解决方法 provide / inject 组合 作用:允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效. App.vue: 声明reload方法,控制

  • vue列表数据发生变化指令没有更新问题及解决方法

    问题描述,在vue的for循环中使用了指令,然后对数据进行筛选的时候,发现指令没有起作用. 如图前面的图标是根据文件名的后缀名,返回响应图标的,通过指令实现的.然后我们在搜索框中删选以后,数据更新了,但是图标没有更新 分析原因 <div v-for="(item, index) in myDate" :key='index'> ... </div> 问题就出在了:key='index'因为vue中for循环是根据key的值的变化来更新vnode的,很显然我们经过

  • Vue组件库ElementUI实现表格列表分页效果

    ElementUI实现表格列表分页效果教程,供大家参考,具体内容如下 Element UI 是一套采用 Vue 2.0 作为基础框架实现的组件库,一套为开发者.设计师和产品经理准备的基于 Vue 2.0 的组件库,提供了配套设计资源,帮助网站快速成型 <el-pagination>加上@size-change="handleSizeChange.@current-change="handleCurrentChange"处理当前页和当前页数的改变事件 <!--

  • vue列表数据删除后主动刷新页面及刷新方法详解

    问题描述: 前端删除一条数据或者新增数据后,后端操作成功,但前端不会自动刷新,需要重新刷新当前页面 (用vue-router重新路由到当前页面,页面是不进行刷新的 ,采用window.reload(),或者router.go(0)刷新时,整个浏览器进行了重新加载) 解决: provide / inject 组合 作用:允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效. (声明reload方法,控制router-view的显示或隐藏,从而控制页

随机推荐