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


Posted in Javascript onMay 28, 2019

本文实例为大家分享了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;
}

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

Javascript 相关文章推荐
IE6与IE7中,innerHTML获取param的区别
Mar 15 Javascript
js判断登录与否并确定跳转页面的方法
Jan 30 Javascript
分享一个自己写的简单的javascript分页组件
Feb 15 Javascript
JQuery中$.each 和$(selector).each()的区别详解
Mar 13 Javascript
SuperSlide标签切换、焦点图多种组合插件
Mar 14 Javascript
JavaScript函数使用的基本教程
Jun 04 Javascript
bootstrap Table服务端处理分页(后台是.net)
Oct 19 Javascript
JS实现的集合去重,交集,并集,差集功能示例
Mar 13 Javascript
Vue 监听列表item渲染事件方法
Sep 06 Javascript
JSONP原理及应用实例详解
Sep 13 Javascript
webpack proxy 使用(代理的使用)
Jan 10 Javascript
JS图片预加载三种实现方法解析
May 08 Javascript
js 将线性数据转为树形的示例代码
May 28 #Javascript
React中使用外部样式的3种方式(小结)
May 28 #Javascript
vue实现多条件和模糊搜索功能
May 28 #Javascript
vue实现路由切换改变title功能
May 28 #Javascript
Vue 无限滚动加载指令实现方法
May 28 #Javascript
vue实现搜索过滤效果
May 28 #Javascript
微信小程序 image组件遇到的问题
May 28 #Javascript
You might like
PHP动态分页函数,PHP开发分页必备啦
2011/11/07 PHP
处理单名多值表单的详解
2013/06/08 PHP
PHP 9 大缓存技术总结
2015/09/17 PHP
[原创]PHP正则匹配中英文、数字及下划线的方法【用户名验证】
2017/08/01 PHP
js实现一个省市区三级联动选择框代码分享
2013/03/06 Javascript
jQuery回车实现登录简单实现
2013/08/20 Javascript
js实现点击左右按钮轮播图片效果实例
2015/01/29 Javascript
JavaScript中扩展Array contains方法实例
2020/08/23 Javascript
浅谈Javascript实现继承的方法
2015/07/06 Javascript
页面get请求 中文参数方法乱码问题的快速解决方法
2016/05/31 Javascript
原生JS简单实现ajax的方法示例
2016/11/29 Javascript
BootStrap中
2016/12/10 Javascript
Angular实现跨域(搜索框的下拉列表)
2017/02/16 Javascript
Angular.js中处理页面闪烁的方法详解
2017/03/09 Javascript
vue-cli3+ts+webpack实现多入口多出口功能
2019/05/30 Javascript
jQuery操作元素追加内容示例
2020/01/10 jQuery
[52:29]DOTA2上海特级锦标赛主赛事日 - 2 胜者组第一轮#3Secret VS OG第三局
2016/03/03 DOTA
[00:52]黑暗之门更新 新英雄孽主驾临DOTA2
2016/08/24 DOTA
Python的__builtin__模块中的一些要点知识
2015/05/02 Python
python开发之基于thread线程搜索本地文件的方法
2015/11/11 Python
详解python string类型 bytes类型 bytearray类型
2017/12/16 Python
Python全局变量与局部变量区别及用法分析
2018/09/03 Python
Python3对称加密算法AES、DES3实例详解
2018/12/06 Python
python 读取文件并把矩阵转成numpy的两种方法
2019/02/12 Python
Python+pyplot绘制带文本标注的柱状图方法
2019/07/08 Python
python编写softmax函数、交叉熵函数实例
2020/06/11 Python
使用CSS Grid布局实现网格的流动
2014/12/30 HTML / CSS
实例讲解CSS3中的border-radius属性
2015/08/18 HTML / CSS
介绍一下.NET构架下remoting和webservice
2014/05/08 面试题
高二地理教学反思
2014/01/24 职场文书
自我鉴定 电子商务专业
2014/01/30 职场文书
房屋公证委托书
2014/04/03 职场文书
电子信息工程专业自荐书
2014/06/24 职场文书
政府个人对照检查材料
2014/08/28 职场文书
社区五一劳动节活动总结
2015/02/09 职场文书
MySQL count(*)统计总数问题汇总
2022/09/23 MySQL