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 相关文章推荐
JavaScript 使用技巧精萃(.net html
Apr 25 Javascript
Prototype Function对象 学习
Jul 12 Javascript
JavaScript DOM学习第六章 表单实例
Feb 19 Javascript
设置jsf的选择框h:selectOneMenu为不可编辑状态的方法
Jan 07 Javascript
jquery实现仿JqueryUi可拖动的DIV实例
Jul 31 Javascript
jQuery获取Table某列的值(推荐)
Mar 03 Javascript
Angular4的输入属性与输出属性实例详解
Nov 29 Javascript
Vue将页面导出为图片或者PDF
Aug 17 Javascript
使用JavaScript获取Django模板指定键值数据
May 27 Javascript
微信小程序将页面按钮悬浮固定在底部的实现代码
Oct 29 Javascript
利用JavaScript模拟京东按键输入功能
Dec 01 Javascript
vue二选一tab栏切换新做法实现
Jan 19 Vue.js
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
ip签名探针
2006/10/09 PHP
PHP统计nginx访问日志中的搜索引擎抓取404链接页面路径
2014/06/30 PHP
PHP函数eval()介绍和使用示例
2014/08/20 PHP
php生成4位数字验证码的实现代码
2015/11/23 PHP
取得一定长度的内容,处理中文
2006/12/20 Javascript
javascript 全选与全取消功能的实现代码
2012/12/23 Javascript
关于scrollLeft,scrollTop的浏览器兼容性测试
2013/03/19 Javascript
使用javascipt---实现二分查找法
2013/04/10 Javascript
js的[defer]和[async]属性
2014/11/24 Javascript
jQuery中:password选择器用法实例
2015/01/03 Javascript
用js实现放大镜的效果的简单实例
2016/05/23 Javascript
javascript实现的全国省市县无刷新多级关联菜单效果代码
2016/08/01 Javascript
layui分页效果实现代码
2017/05/19 Javascript
微信小程序checkbox组件使用详解
2018/01/31 Javascript
实例解析Vue.js下载方式及基本概念
2018/05/11 Javascript
element-ui表格列金额显示两位小数的方法
2018/08/24 Javascript
VUE解决微信签名及SPA微信invalid signature问题(完美处理)
2019/03/29 Javascript
深入学习TypeScript 、React、 Redux和Ant-Design的最佳实践
2019/06/17 Javascript
解决antd Form 表单校验方法无响应的问题
2020/10/27 Javascript
Python实现程序的单一实例用法分析
2015/06/03 Python
Python Json序列化与反序列化的示例
2018/01/31 Python
Linux下python制作名片示例
2018/07/20 Python
PYTHON实现SIGN签名的过程解析
2019/10/28 Python
Python Web静态服务器非堵塞模式实现方法示例
2019/11/21 Python
canvas需要在标签里直接定义宽高
2014/12/17 HTML / CSS
浅谈基于Canvas的手绘风格图形库Rough.js
2018/03/19 HTML / CSS
马来西亚最好的婴儿商店:Motherhood
2017/09/14 全球购物
伦敦一卡通:The London Pass
2018/11/30 全球购物
欧洲最大的预定车位市场:JustPark
2020/01/06 全球购物
教师师德教育的自我评价
2013/10/31 职场文书
高二地理教学反思
2014/01/24 职场文书
致1500米运动员广播稿
2014/02/07 职场文书
语文教研活动总结
2014/07/02 职场文书
如何写好一份优秀的工作总结?
2019/06/21 职场文书
MybatisPlus EntityWrapper如何自定义SQL
2022/03/22 Java/Android
python处理json数据文件
2022/04/11 Python