Showing
7 changed files
with
227 additions
and
90 deletions
1 | <div id="product-list"> | 1 | <div id="product-list"> |
2 | - <Sort></Sort> | ||
3 | - <List url="/product/list" :query='{a:1}'></List> | 2 | + <Sort :config.once="sortConfig" :val="sort"> |
3 | + </Sort> | ||
4 | + <List :data="productList"></List> | ||
4 | <Drawer> | 5 | <Drawer> |
5 | <Filter></Filter> | 6 | <Filter></Filter> |
6 | </Drawer> | 7 | </Drawer> |
7 | -</div> | ||
8 | +</div> | ||
9 | +<script> | ||
10 | + var sortConfig = [ | ||
11 | + {txt: '默认', val: 1 }, | ||
12 | + {txt: '最新', val: 2 }, | ||
13 | + {type: 'updown', txt: '价格', val: [3, 4] }, //[up, down] | ||
14 | + {type: 'updown', txt: '折扣', val: [5, 6] } | ||
15 | +]; | ||
16 | +</script> |
1 | const Vue = require('yoho-vue'); | 1 | const Vue = require('yoho-vue'); |
2 | const lazyload = require('yoho-vue-lazyload'); | 2 | const lazyload = require('yoho-vue-lazyload'); |
3 | const infinitScroll = require('yoho-vue-infinite-scroll'); | 3 | const infinitScroll = require('yoho-vue-infinite-scroll'); |
4 | +const bus = require('common/vue-bus'); | ||
4 | const sort = require('product/sort.vue'); | 5 | const sort = require('product/sort.vue'); |
5 | const list = require('product/list.vue'); | 6 | const list = require('product/list.vue'); |
6 | const drawer = require('product/drawer.vue'); | 7 | const drawer = require('product/drawer.vue'); |
@@ -11,9 +12,104 @@ Vue.use(infinitScroll); | @@ -11,9 +12,104 @@ Vue.use(infinitScroll); | ||
11 | 12 | ||
12 | require('common/vue-filter'); | 13 | require('common/vue-filter'); |
13 | 14 | ||
14 | -new Vue({ | 15 | +const app = new Vue({ |
15 | el: '#product-list', | 16 | el: '#product-list', |
17 | + data: function() { | ||
18 | + return { | ||
19 | + sortConfig: global.sortConfig, | ||
20 | + filterConfig: [], | ||
21 | + | ||
22 | + // query | ||
23 | + url: 'list', | ||
24 | + sort: 3, | ||
25 | + filter: [], | ||
26 | + page: 0, // page= 0 未搜索, 1 并且productList.length =0 没有数据, page = page_total 全部加载完 | ||
27 | + totalPage: 0, | ||
28 | + | ||
29 | + // 产品列表 | ||
30 | + productList: [], | ||
31 | + | ||
32 | + // state: | ||
33 | + inSearching: false | ||
34 | + }; | ||
35 | + }, | ||
16 | components: { | 36 | components: { |
17 | - list, sort, filter, drawer | 37 | + list, |
38 | + sort, | ||
39 | + filter, | ||
40 | + drawer | ||
41 | + }, | ||
42 | + methods: { | ||
43 | + search: function() { | ||
44 | + if (this.inSearching) { | ||
45 | + return; | ||
46 | + } | ||
47 | + const self = this; | ||
48 | + | ||
49 | + this.inSearching = true; | ||
50 | + $.post(this.url, { | ||
51 | + sort: this.sort, | ||
52 | + filter: this.filter, | ||
53 | + page: this.page | ||
54 | + }) | ||
55 | + .done(res => { | ||
56 | + self.$set('productList', self.productList.concat(res.data.productList)); | ||
57 | + }) | ||
58 | + .fail(error => { | ||
59 | + self.page--; | ||
60 | + }) | ||
61 | + .always(()=>{ | ||
62 | + self.inSearching = false; | ||
63 | + }); | ||
64 | + }, | ||
65 | + | ||
66 | + pageState: function() { | ||
67 | + | ||
68 | + }, | ||
69 | + | ||
70 | + /** | ||
71 | + * | ||
72 | + */ | ||
73 | + research: function() { | ||
74 | + | ||
75 | + } | ||
76 | + }, | ||
77 | + watch: { | ||
78 | + /* sort 和 filter 改变 都会触发 重新搜索 (想象成清空所有分页) */ | ||
79 | + sort: function() { | ||
80 | + this.page = 0; | ||
81 | + }, | ||
82 | + filter: function() { | ||
83 | + this.page = 0; | ||
84 | + }, | ||
85 | + | ||
86 | + page: function(newVal, oldVal) { | ||
87 | + if (newVal === 0) { | ||
88 | + // when research | ||
89 | + this.$set('productList', []); | ||
90 | + this.search(); | ||
91 | + } else if (newVal > oldVal && newVal > this.totalPage) { | ||
92 | + // when fetch | ||
93 | + this.search(); | ||
94 | + } | ||
95 | + } | ||
96 | + }, | ||
97 | + | ||
98 | + created: function() { | ||
99 | + this.search(); | ||
18 | } | 100 | } |
19 | }); | 101 | }); |
102 | + | ||
103 | +bus.$on('list.paging', function() { | ||
104 | + app.page++; | ||
105 | +}); | ||
106 | + | ||
107 | +bus.$on('sort.change', function({ val}) { | ||
108 | + console.log(val); | ||
109 | + app.sort = val; | ||
110 | +}); | ||
111 | + | ||
112 | +bus.$on('filter.change', function({ val}) { | ||
113 | + console.log(val); | ||
114 | + app.filter = val; | ||
115 | +}); |
public/vue/product/index.vue
0 → 100644
1 | <template> | 1 | <template> |
2 | <div class="goods-box" v-infinite-scroll="fetch()" infinite-scroll-disable="disableFetch"> | 2 | <div class="goods-box" v-infinite-scroll="fetch()" infinite-scroll-disable="disableFetch"> |
3 | <ul class="cardlist card-large clearfix"> | 3 | <ul class="cardlist card-large clearfix"> |
4 | - <li class="card" v-for="item in products"> | 4 | + <li class="card" v-for="item in data"> |
5 | <div class="card-pic"> | 5 | <div class="card-pic"> |
6 | <a href=""> | 6 | <a href=""> |
7 | <img v-lazy="item.goodsList[0].imagesUrl | resize 372 499" alt="{{item.productName}}"> | 7 | <img v-lazy="item.goodsList[0].imagesUrl | resize 372 499" alt="{{item.productName}}"> |
@@ -21,75 +21,21 @@ | @@ -21,75 +21,21 @@ | ||
21 | </div> | 21 | </div> |
22 | </template> | 22 | </template> |
23 | <script> | 23 | <script> |
24 | -let $ = require('yoho-jquery'); | ||
25 | - | ||
26 | -/** | ||
27 | - * @example | ||
28 | - * <List url='' :query='{}' disable-fetch></List> | ||
29 | - * <List :init-data='{}'></List> | ||
30 | - */ | 24 | +let bus = require('common/vue-bus'); |
31 | 25 | ||
32 | module.exports = { | 26 | module.exports = { |
33 | props: { | 27 | props: { |
34 | - | ||
35 | - /* 请求地址 */ | ||
36 | - url: { | ||
37 | - type: String, | ||
38 | - required: true | ||
39 | - }, | ||
40 | - | ||
41 | - /* 初始数据, 应该只单次绑定, 然后fetch数据全靠url */ | ||
42 | - initData: Array, | ||
43 | - | ||
44 | - /* 请求参数 */ | ||
45 | - query: Object, | ||
46 | - | ||
47 | /* 开启滚动加载 */ | 28 | /* 开启滚动加载 */ |
48 | - disableFetch: Boolean | ||
49 | - }, | ||
50 | - data: function() { | ||
51 | - return { | ||
52 | - state: { | ||
53 | - curPage: 0, | ||
54 | - totalPage: 10 | ||
55 | - }, | ||
56 | - products: [], | ||
57 | - inLoading: false, | ||
58 | - atEnd: false | ||
59 | - }; | 29 | + disableFetch: Boolean, |
30 | + | ||
31 | + //数据 | ||
32 | + data: Array | ||
60 | }, | 33 | }, |
61 | methods: { | 34 | methods: { |
62 | fetch: function() { | 35 | fetch: function() { |
63 | - if (this.atEnd) { | ||
64 | - return; | ||
65 | - } | ||
66 | - let self = this; | ||
67 | - | ||
68 | - this.state.curPage++; | ||
69 | - this.inLoading = true; | ||
70 | - $.ajax({ | ||
71 | - url: this.url, | ||
72 | - type: 'POST', | ||
73 | - }) | ||
74 | - .done(result => { | ||
75 | - self.$set('products', self.products.concat(result.data.productList)); | ||
76 | - }) | ||
77 | - .always(() => { | ||
78 | - self.inLoading = false; | ||
79 | - self.atEnd = self.state.curPage === self.state.totalPage; | ||
80 | - }); | ||
81 | - | ||
82 | - } | ||
83 | - }, | ||
84 | - created: function() { | ||
85 | - // 有初始数据,用初始数据 | ||
86 | - if (this.initData) { | ||
87 | - this.$set('products', this.products.concat(this.initData)); | ||
88 | - this.atEnd = true; | ||
89 | - } else if (this.url) { | ||
90 | - this.fetch(); | 36 | + bus.$emit('list.paging'); |
91 | } | 37 | } |
92 | - }, | 38 | + } |
93 | }; | 39 | }; |
94 | </script> | 40 | </script> |
95 | <style> | 41 | <style> |
1 | <template> | 1 | <template> |
2 | <ul class="sort-navs clearfix"> | 2 | <ul class="sort-navs clearfix"> |
3 | - <li class="sort-item active"><span>默认</span></li> | ||
4 | - <li class="sort-item"> | ||
5 | - <span class="sort-name">最新</span> | ||
6 | - <span class="sort-icon"> | ||
7 | - <i class="icon icon-sort-asc"></i> | ||
8 | - <i class="icon icon-sort-desc"></i> | ||
9 | - </span> | ||
10 | - </li> | ||
11 | - <li class="sort-item"> | ||
12 | - <span class="sort-name">价格</span> | ||
13 | - </li> | ||
14 | - <li class="sort-item"> | ||
15 | - <span class="sort-name">折扣</span> | ||
16 | - <span class="sort-icon"> | ||
17 | - <i class="icon icon-sort-asc"></i> | ||
18 | - <i class="icon icon-sort-desc"></i> | ||
19 | - </span> | ||
20 | - </li> | 3 | + <template v-for="item in config"> |
4 | + <simple v-if="(item.type || 'simple') === 'simple'" :txt="item.txt" :val="item.val"> | ||
5 | + </simple> | ||
6 | + <updown v-if="item.type === 'updown'" :txt="item.txt" :vals="item.val"> | ||
7 | + </updown> | ||
8 | + </template> | ||
21 | </ul> | 9 | </ul> |
22 | </template> | 10 | </template> |
23 | <script> | 11 | <script> |
12 | +const $ = require('yoho-jquery'); | ||
13 | +const bus = require('common/vue-bus'); | ||
14 | +const simple = require('./sort/simple.vue'); | ||
15 | +const updown = require('./sort/updown.vue'); | ||
16 | + | ||
24 | module.exports = { | 17 | module.exports = { |
18 | + props: { | ||
19 | + /** | ||
20 | + * sort 配置 | ||
21 | + * @type {Array} [{type, txt, val}] | ||
22 | + * type: 类型 simple, updown | ||
23 | + * txt: 文字, | ||
24 | + * val: 值 | ||
25 | + */ | ||
26 | + config: Array, | ||
25 | 27 | ||
28 | + //初始值 可以进行双向绑定 | ||
29 | + val: Number | ||
30 | + }, | ||
31 | + components: { | ||
32 | + simple, | ||
33 | + updown | ||
34 | + }, | ||
35 | + methods: {}, | ||
36 | + watch: { | ||
37 | + 'val': function(newVal, oldVal) { | ||
38 | + bus.$emit('sort.change', { | ||
39 | + val: newVal, | ||
40 | + ref: this._uid | ||
41 | + }); | ||
42 | + } | ||
43 | + } | ||
26 | }; | 44 | }; |
27 | </script> | 45 | </script> |
28 | <style> | 46 | <style> |
@@ -41,7 +59,6 @@ module.exports = { | @@ -41,7 +59,6 @@ module.exports = { | ||
41 | width: 25%; | 59 | width: 25%; |
42 | float: left; | 60 | float: left; |
43 | text-align: center; | 61 | text-align: center; |
44 | - | ||
45 | &:after { | 62 | &:after { |
46 | content: "|"; | 63 | content: "|"; |
47 | position: absolute; | 64 | position: absolute; |
@@ -52,15 +69,12 @@ module.exports = { | @@ -52,15 +69,12 @@ module.exports = { | ||
52 | &:last-of-type:after { | 69 | &:last-of-type:after { |
53 | display: none; | 70 | display: none; |
54 | } | 71 | } |
55 | - | ||
56 | .sort-name { | 72 | .sort-name { |
57 | font-size: 28px; | 73 | font-size: 28px; |
58 | } | 74 | } |
59 | - | ||
60 | .sort-icon { | 75 | .sort-icon { |
61 | position: relative; | 76 | position: relative; |
62 | margin-left: 10px; | 77 | margin-left: 10px; |
63 | - | ||
64 | .icon-sort-asc, | 78 | .icon-sort-asc, |
65 | .icon-sort-desc { | 79 | .icon-sort-desc { |
66 | position: absolute; | 80 | position: absolute; |
@@ -68,7 +82,6 @@ module.exports = { | @@ -68,7 +82,6 @@ module.exports = { | ||
68 | top: 0; | 82 | top: 0; |
69 | } | 83 | } |
70 | } | 84 | } |
71 | - | ||
72 | &.active { | 85 | &.active { |
73 | color: $black; | 86 | color: $black; |
74 | } | 87 | } |
public/vue/product/sort/simple.vue
0 → 100644
1 | +<template> | ||
2 | + <li class="sort-item" :class="active" @click="click"> | ||
3 | + <span class="sort-name">{{txt}}</span> | ||
4 | + </li> | ||
5 | +</template> | ||
6 | +<script> | ||
7 | +module.exports = { | ||
8 | + props: ['txt', 'val'], | ||
9 | + computed: { | ||
10 | + active: function() { | ||
11 | + if (this.val === this.$parent.val) { | ||
12 | + return 'active'; | ||
13 | + } | ||
14 | + } | ||
15 | + }, | ||
16 | + methods: { | ||
17 | + click: function() { | ||
18 | + this.$parent.val = this.val; | ||
19 | + } | ||
20 | + } | ||
21 | +}; | ||
22 | +</script> |
public/vue/product/sort/updown.vue
0 → 100644
1 | +<template> | ||
2 | + <li class="sort-item" :class="active" @click="clickHandler"> | ||
3 | + <span class="sort-name">{{txt}}</span> | ||
4 | + <span class="sort-icon"> | ||
5 | + <i class="icon icon-sort-asc" :class="{active: $parent.val === vals[0]}"></i> | ||
6 | + <i class="icon icon-sort-desc" :class="{active: $parent.val === vals[1]}"></i> | ||
7 | + </span> | ||
8 | + </li> | ||
9 | +</template> | ||
10 | +<style> | ||
11 | +.sort-item .icon { | ||
12 | + color: #b0b0b0; | ||
13 | + &.active { | ||
14 | + color: #000; | ||
15 | + } | ||
16 | +} | ||
17 | +</style> | ||
18 | +<script> | ||
19 | +module.exports = { | ||
20 | + props: { | ||
21 | + txt: String, | ||
22 | + vals: Array //[asc, desc] | ||
23 | + }, | ||
24 | + data: function() { | ||
25 | + return {}; | ||
26 | + }, | ||
27 | + computed: { | ||
28 | + active: function() { | ||
29 | + const index = this.vals.indexOf(this.$parent.val); | ||
30 | + | ||
31 | + if (index >= 0) { | ||
32 | + return { | ||
33 | + 'active': true, | ||
34 | + }; | ||
35 | + } | ||
36 | + } | ||
37 | + }, | ||
38 | + methods: { | ||
39 | + clickHandler: function() { | ||
40 | + let index = this.vals.indexOf(this.$parent.val); | ||
41 | + | ||
42 | + if (index === -1) { | ||
43 | + this.$parent.val = this.vals[0]; | ||
44 | + } else { | ||
45 | + index = index === 0 ? 1 : 0; | ||
46 | + this.$parent.val = this.vals[index]; | ||
47 | + } | ||
48 | + } | ||
49 | + } | ||
50 | +}; | ||
51 | +</script> |
-
Please register or login to post a comment