您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關如何使用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; }
關于“如何使用vue實現前臺列表數據過濾搜索、分頁效果”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。