[vue] 实现多条件筛选
大体效果图是这样的:一、涉及的知识点:vue 组件化开发,不懂的可以参考vue 组件基础 ==》https://cn.vuejs.org/v2/guide/components.htmles6 promise 模拟数据,参考 ==》http://es6.ruanyifeng.com/#docs/promise其他:1.可把组件单独放一个js文件里,通过script 引入即可。...
·
彩蛋:后台管理系统一站式平台模板
大体效果图是这样的:
一、涉及的知识点:
- vue 组件化开发,不懂的可以参考vue 组件基础 ==》https://cn.vuejs.org/v2/guide/components.html
- es6 promise 模拟数据,参考 ==》http://es6.ruanyifeng.com/#docs/promise
其他:
1.可把组件单独放一个js文件里,通过script 引入即可。
2.全部写在一个页面是为了更加直观的理解,开发代码时,个人不建议用此方法
3.第一次写文章,有什么不对的,希望大家别见怪!谢谢
<script src="js/demo-filter.js"></script>
二、实现:
- 主逻辑部分
const vm = new Vue({
el: '#view',
data() {
return {
viewList: [],
viewTime: {
time: true,
msg: '数据拼命加载中...'
},
param: {},
filterList: [],
filterSelData: [] // 过滤选中的数据
}
},
created() {
// 请求数据
this.setRequest('json/demo2.json', this.param, 'get').then(res => {
this.viewList = [...res.list]
return this.setRequest('json/demo3.json', this.param, 'get')
}).then(res => {
this.filterList = [...res.list]
})
},
mounted() {
this.setTime(1000, 0, false)
},
methods: {
// 封装 axios
setRequest(url, data = {}, method = 'get') {
return new Promise((resolve, reject) => {
axios({
url,
method,
data
}).then(res => {
resolve(res.data)
}).catch(err => {
reject(err)
})
})
},
// 获取筛选组件选中的值
getFilterSelData(data) {
this.filterSelData = data
},
// 模拟延时显示数据视图
setTime(startTime, endTime, bool) {
setTimeout(() => {
this.viewTime.time = bool
setTimeout(() => {
this.viewTime.time = false
}, endTime)
}, startTime)
}
}
})
- 过滤筛选组件
// 过滤组件
Vue.component('demo-filter', {
template: `
<div class="demo">
<div class="demo-warp">
<div class="demo-flex" v-for="(v,k) in getList" :key="k">
<span class="demo-title">{{v.title}}</span>
<div class="demo-content">
<div class="demo-tab" :class="isShow ? 'demo-hide' : ''">
<span v-for="(val, key) in v.childer" :key="key"
:class="{'demo-active': val.active}"
@click="tabClick(val,key,k)">{{val.value}}</span>
</div>
</div>
<div class="demo-more" @click="isShow = !isShow" v-if="v.childer.length >= 14">更多</div>
</div>
</div>
</div>
`,
data() {
return {
isShow: false
}
},
props: {
getList: {
type: Array,
default: () => []
}
},
methods: {
tabClick(data, key, k) {
// 添加 active ==> true 显示 `active样式`
this.getList[k].childer.map(item => {
item.active = false
})
this.getList[k].childer[key].active = true
// 选中的数据
let newArray = []
this.getList.map(data => {
data.childer.map(item => {
if (item.active == true) {
newArray.push(item)
}
})
})
this.$emit('get-sel-data', newArray)
this.$emit('set-time', 0, 1000, true)
}
}
})
- 布局组件
Vue.component('view-layout', {
template: `<div class="view-warp">
<div class="view-box" v-if="!viewTime.time">
<div class="view-flex" v-for="(v,k) in viewData" :key="k" :style="style">
<div class="view-item">
<span>{{v.title}}</span>
</div>
</div>
</div>
<div class="view-no-data" v-else>{{viewTime.msg}}</div>
</div>`,
props: {
viewData: {
type: Array,
default: () => []
},
width: {
type: String,
default: "25%"
},
height: {
type: String,
default: "300px"
},
viewTime: {
type: Object,
default: {
time: true,
msg: '数据加载中...'
}
}
},
computed: {
style() {
return {
width: `${this.width.replace(/%+/, '')}%`,
height: `${this.height.replace(/px+/, '')}px`
}
}
}
})
- 页面调用
<demo-filter :get-list="filterList" @get-sel-data="getFilterSelData" @set-time="setTime"></demo-filter>
<view-layout :view-data="viewList" width="25%" height="300px" :view-time="viewTime"></view-layout>
- json数据
1.布局组件json ==> 路径: json/demo2.json
{
"list": [{
"title": "11"
},
{
"title": "22"
},
{
"title": "33"
},
{
"title": "44"
},
{
"title": "55"
},
{
"title": "66"
}
]
}
2. 过滤筛选组件json ==> 路径: json/demo3.json
{
"list": [{
"title": "分类:",
"childer": [{
"value": "全部",
"active": true
},
{
"value": "漂浮素材",
"active": false
},
{
"value": "效果元素",
"active": false
},
{
"value": "卡通手绘",
"active": false
},
{
"value": "装饰图案",
"active": false
},
{
"value": "图标元素",
"active": false
},
{
"value": "促销标签",
"active": false
},
{
"value": "边框纹理",
"active": false
},
{
"value": "不规则图形",
"active": false
},
{
"value": "表情包213123",
"active": false
},
{
"value": "表情包2323",
"active": false
},
{
"value": "表情包1111",
"active": false
},
{
"value": "表情包3333",
"active": false
},
{
"value": "表情包444",
"active": false
}
]
},
{
"title": "格式:",
"childer": [{
"value": "全部",
"active": true
},
{
"value": "PSD",
"active": false
},
{
"value": "AI",
"active": false
},
{
"value": "EPS",
"active": false
}
]
},
{
"title": "排序:",
"childer": [{
"value": "推荐",
"active": true
},
{
"value": "昨日热门",
"active": false
},
{
"value": "最新上传",
"active": false
},
{
"value": "热门下载",
"active": false
},
{
"value": "热门收藏",
"active": false
}
]
}
]
}
- css 样式
/* 布局组件:start */
.view-warp {
flex: 1;
overflow: hidden;
margin: auto;
display: flex;
}
.view-box {
overflow: auto;
width: 1220px;
height: 100%;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
margin: 0 -10px;
}
.view-flex {
padding: 10px;
cursor: pointer;
transition: ease .5s;
transform-style: preserve-3d;
}
.view-flex:hover {
transform: translateY(-10px);
transition: ease .5s;
}
.view-item {
height: 100%;
border: 1px solid red;
display: flex;
}
.view-item>span {
margin: auto;
}
.view-no-data {
margin: auto;
}
/* 布局组件:end */
/* 过滤列表:start */
.demo {
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
margin-bottom: 15px;
min-height: 140px;
height: auto !important;
height: 140px;
}
.demo-warp {
display: flex;
max-width: 1200px;
margin: auto;
height: 100%;
flex-direction: column;
padding: 15px 0;
}
.demo-flex {
display: flex;
margin-bottom: 15px;
}
.demo-flex:last-of-type {
margin-bottom: 0;
}
.demo-title {
flex-basis: 70px;
margin-top: 5px;
}
.demo-content {
display: flex;
flex: 1;
}
.demo-tab {
flex: 1;
margin-right: 15px;
height: 35px;
overflow: hidden;
}
.demo-tab span {
display: inline-block;
margin: 0 5px 15px 5px;
cursor: pointer;
padding: 5px 10px;
color: #999999;
}
.demo-more {
margin-top: 5px;
cursor: pointer;
}
.demo-active {
background-color: #09F;
color: white !important;
border-radius: 3px;
}
.demo-tab span:hover {
background-color: #09F;
color: white;
border-radius: 3px;
}
.demo-hide {
min-height: 35px;
height: auto !important;
}
/* 过滤列表:end */
三、全部html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<style type="text/css">
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body,
section {
width: 100%;
height: 100%;
}
[v-clock] {
display: none;
}
section {
display: flex;
flex-direction: column;
}
/* 布局组件:start */
.view-warp {
flex: 1;
overflow: hidden;
margin: auto;
display: flex;
}
.view-box {
overflow: auto;
width: 1220px;
height: 100%;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
margin: 0 -10px;
}
.view-flex {
padding: 10px;
cursor: pointer;
transition: ease .5s;
transform-style: preserve-3d;
}
.view-flex:hover {
transform: translateY(-10px);
transition: ease .5s;
}
.view-item {
height: 100%;
border: 1px solid red;
display: flex;
}
.view-item>span {
margin: auto;
}
.view-no-data {
margin: auto;
}
/* 布局组件:end */
/* 过滤列表:start */
.demo {
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
margin-bottom: 15px;
min-height: 140px;
height: auto !important;
height: 140px;
}
.demo-warp {
display: flex;
max-width: 1200px;
margin: auto;
height: 100%;
flex-direction: column;
padding: 15px 0;
}
.demo-flex {
display: flex;
margin-bottom: 15px;
}
.demo-flex:last-of-type {
margin-bottom: 0;
}
.demo-title {
flex-basis: 70px;
margin-top: 5px;
}
.demo-content {
display: flex;
flex: 1;
}
.demo-tab {
flex: 1;
margin-right: 15px;
height: 35px;
overflow: hidden;
}
.demo-tab span {
display: inline-block;
margin: 0 5px 15px 5px;
cursor: pointer;
padding: 5px 10px;
color: #999999;
}
.demo-more {
margin-top: 5px;
cursor: pointer;
}
.demo-active {
background-color: #09F;
color: white !important;
border-radius: 3px;
}
.demo-tab span:hover {
background-color: #09F;
color: white;
border-radius: 3px;
}
.demo-hide {
min-height: 35px;
height: auto !important;
}
/* 过滤列表:end */
</style>
</head>
<body>
<section id="view" clock>
<demo-filter :get-list="filterList" @get-sel-data="getFilterSelData" @set-time="setTime"></demo-filter>
<view-layout :view-data="viewList" width="25%" height="300px" :view-time="viewTime"></view-layout>
<pre>
选中的数据:{{filterSelData}}
</pre>
</section>
<script type="text/javascript">
// 过滤筛选组件
Vue.component('demo-filter', {
template: `
<div class="demo">
<div class="demo-warp">
<div class="demo-flex" v-for="(v,k) in getList" :key="k">
<span class="demo-title">{{v.title}}</span>
<div class="demo-content">
<div class="demo-tab" :class="isShow ? 'demo-hide' : ''">
<span v-for="(val, key) in v.childer" :key="key" :class="{'demo-active': val.active}" @click="tabClick(val,key,k)">{{val.value}}</span>
</div>
</div>
<div class="demo-more" @click="isShow = !isShow" v-if="v.childer.length >= 14">更多</div>
</div>
</div>
</div>
`,
data() {
return {
isShow: false
}
},
props: {
getList: {
type: Array,
default: () => []
}
},
methods: {
tabClick(data, key, k) {
// 添加 active ==> true 显示 `active样式`
this.getList[k].childer.map(item => {
item.active = false
})
this.getList[k].childer[key].active = true
// 选中的数据
let newArray = []
this.getList.map(data => {
data.childer.map(item => {
if (item.active == true) {
newArray.push(item)
}
})
})
this.$emit('get-sel-data', newArray)
this.$emit('set-time', 0, 1000, true)
}
}
})
// 布局组件
Vue.component('view-layout', {
template: `<div class="view-warp">
<div class="view-box" v-if="!viewTime.time">
<div class="view-flex" v-for="(v,k) in viewData" :key="k" :style="style">
<div class="view-item">
<span>{{v.title}}</span>
</div>
</div>
</div>
<div class="view-no-data" v-else>{{viewTime.msg}}</div>
</div>`,
props: {
viewData: {
type: Array,
default: () => []
},
width: {
type: String,
default: "25%"
},
height: {
type: String,
default: "300px"
},
viewTime: {
type: Object,
default: {
time: true,
msg: '数据加载中...'
}
}
},
computed: {
style() {
return {
width: `${this.width.replace(/%+/, '')}%`,
height: `${this.height.replace(/px+/, '')}px`
}
}
}
})
</script>
<script type="text/javascript">
const vm = new Vue({
el: '#view',
data() {
return {
viewList: [],
viewTime: {
time: true,
msg: '数据拼命加载中...'
},
param: {},
filterList: [],
filterSelData: [] // 过滤选中的数据
}
},
created() {
// 请求数据
this.setRequest('json/demo2.json', this.param, 'get').then(res => {
this.viewList = [...res.list]
return this.setRequest('json/demo3.json', this.param, 'get')
}).then(res => {
this.filterList = [...res.list]
})
},
mounted() {
this.setTime(1000, 0, false)
},
methods: {
// 封装 axios
setRequest(url, data = {}, method = 'get') {
return new Promise((resolve, reject) => {
axios({
url,
method,
data
}).then(res => {
resolve(res.data)
}).catch(err => {
reject(err)
})
})
},
// 获取筛选组件选中的值
getFilterSelData(data) {
this.filterSelData = data
},
// 模拟延时显示数据视图
setTime(startTime, endTime, bool) {
setTimeout(() => {
this.viewTime.time = bool
setTimeout(() => {
this.viewTime.time = false
}, endTime)
}, startTime)
}
}
})
</script>
</body>
</html>
更多推荐
已为社区贡献6条内容
所有评论(0)