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 相关文章推荐
在Linux上用forever实现Node.js项目自启动
Jul 09 Javascript
ztree获取当前选中节点子节点id集合的方法
Feb 12 Javascript
解决jQuery ajax请求在IE6中莫名中断的问题
Jun 20 Javascript
老生常谈JQuery data方法的使用
Sep 09 Javascript
浅谈js中用$(#ID)来作为选择器的问题(id重复的时候)
Feb 14 Javascript
JS实现根据密码长度显示安全条功能
Mar 08 Javascript
详解vue.js+UEditor集成 [前后端分离项目]
Jul 07 Javascript
jQuery实现手势解锁密码特效
Aug 14 jQuery
Vue-cli 使用json server在本地模拟请求数据的示例代码
Nov 02 Javascript
vue中动态设置meta标签和title标签的方法
Jul 11 Javascript
用原生 JS 实现 innerHTML 功能实例详解
Apr 03 Javascript
vue表单验证你真的会了吗?vue表单验证(form)validate
Apr 07 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下使用curl模拟用户登陆的代码
2010/09/10 PHP
PHP实现微信发红包程序
2015/08/24 PHP
8个必备的PHP功能开发
2015/10/02 PHP
基于Laravel(5.4版本)的基本增删改查操作方法
2019/10/11 PHP
JQuery onload、ready概念介绍及使用方法
2013/04/27 Javascript
js特效,页面下雪的小例子
2013/06/17 Javascript
createTextRange()的使用示例含文本框选中部分文字内容
2014/02/24 Javascript
ExtJS4给Combobox设置列表中的默认值示例
2014/05/02 Javascript
上传文件返回的json数据会被提示下载问题解决方案
2014/12/03 Javascript
学做Bootstrap的第一个页面
2016/05/15 HTML / CSS
详解vue服务端渲染(SSR)初探
2017/06/19 Javascript
详解vue 配合vue-resource调用接口获取数据
2017/06/22 Javascript
Vue组件通信之Bus的具体使用
2017/12/28 Javascript
微信小程序自定义组件之可清除的input组件
2018/07/17 Javascript
详解微信小程序的 request 封装示例
2018/08/21 Javascript
Vue中常用rules校验规则(实例代码)
2019/11/14 Javascript
[00:31]DOTA2上海特级锦标赛 Fnatic战队宣传片
2016/03/04 DOTA
python 队列详解及实例代码
2016/10/18 Python
Python 专题五 列表基础知识(二维list排序、获取下标和处理txt文本实例)
2017/03/20 Python
Python实现将罗马数字转换成普通阿拉伯数字的方法
2017/04/19 Python
python去除扩展名的实例讲解
2018/04/23 Python
python开发准备工作之配置虚拟环境(非常重要)
2019/02/11 Python
python提取照片坐标信息的实例代码
2019/08/14 Python
pytorch 共享参数的示例
2019/08/17 Python
python之yield和Generator深入解析
2019/09/18 Python
python爬虫学习笔记之Beautifulsoup模块用法详解
2020/04/09 Python
Python的PIL库中getpixel方法的使用
2020/04/09 Python
Python如何截图保存的三种方法(小结)
2020/09/01 Python
canvas学习笔记之绘制简单路径
2019/01/28 HTML / CSS
Pretty Little Thing爱尔兰:时尚女性服饰
2017/03/27 全球购物
小学开学寄语
2014/01/19 职场文书
《望洞庭》教学反思
2014/02/16 职场文书
《北大荒的秋天》教学反思
2014/04/14 职场文书
2015年学校安全管理工作总结
2015/05/11 职场文书
获奖感言一句话
2015/07/31 职场文书
药品销售员2015年终工作总结
2015/10/22 职场文书