Commit 65c64ce93580dd05c4fed50496443324d8c5e63e

Authored by Rijn
1 parent 41f83010

carousel basic position

src/components/carousel/carousel-item.vue
1 1 <template>
2   - <div :class="prefixCls"><slot></slot></div>
  2 + <div :class="prefixCls" v-bind:style="styles">{{width}}<slot></slot></div>
3 3 </template>
4 4 <script>
5 5 const prefixCls = 'ivu-carousel-item';
6 6  
7 7 export default {
8   - name: 'CarouselItem'
  8 + componentName: 'carousel-item',
  9 +
  10 + data () {
  11 + return {
  12 + prefixCls: prefixCls,
  13 + width: 0,
  14 + left: 0
  15 + };
  16 + },
  17 + computed: {
  18 + styles () {
  19 + return {
  20 + width: `${this.width}px`,
  21 + left: `${this.left}px`
  22 + }
  23 + }
  24 + },
9 25 };
10 26 </script>
... ...
src/components/carousel/carousel.vue
1 1 <template>
2 2 <div :class="classes">
3   - <slot></slot>
  3 + <!-- button -->
  4 + <div :class="[prefixCls + '-list']">
  5 + <div :class="[prefixCls + '-track']" :style="trackStyles" v-el:slides>
  6 + <!-- opacity: 1; width: 4480px; transform: translate3d(-1120px, 0px, 0px); -->
  7 + <slot></slot>
  8 + </div>
  9 + </div>
  10 + <!-- button -->
4 11 </div>
5 12 </template>
6 13 <script>
7 14 import Icon from '../icon/icon.vue';
  15 + import { oneOf, getStyle, deepCopy, getScrollBarSize } from '../../utils/assist';
8 16  
9 17 const prefixCls = 'ivu-carousel';
10 18  
... ... @@ -40,6 +48,15 @@
40 48 default: false
41 49 }
42 50 },
  51 + data () {
  52 + return {
  53 + prefixCls: prefixCls,
  54 + listWidth: 0,
  55 + trackWidth: 0,
  56 + slides: [],
  57 + slideInstances: []
  58 + }
  59 + },
43 60 // events: before-change(from, to), after-change(current, from)
44 61 computed: {
45 62 classes () {
... ... @@ -49,7 +66,99 @@
49 66 [`${prefixCls}-vertical`]: this.vertical
50 67 }
51 68 ];
  69 + },
  70 + trackStyles () {
  71 + return {
  72 + width: `${this.trackWidth}px`
  73 + };
  74 + }
  75 + },
  76 + methods: {
  77 + // find option component
  78 + findChild (cb) {
  79 + const find = function (child) {
  80 + const name = child.$options.componentName;
  81 +
  82 + if (name) {
  83 + cb(child);
  84 + } else if (child.$children.length) {
  85 + child.$children.forEach((innerChild) => {
  86 + find(innerChild, cb);
  87 + });
  88 + }
  89 + };
  90 +
  91 + if (this.slideInstances.length) {
  92 + this.slideInstances.forEach((child) => {
  93 + find(child);
  94 + });
  95 + } else {
  96 + this.$children.forEach((child) => {
  97 + find(child);
  98 + });
  99 + }
  100 + },
  101 + updateSlides (init, slot = false) {
  102 + let slides = [];
  103 + let index = 1;
  104 +
  105 + this.findChild((child) => {
  106 + slides.push({
  107 + $el: child.$el
  108 + });
  109 + child.index = index++;
  110 +
  111 + if (init) {
  112 + this.slideInstances.push(child);
  113 + }
  114 + });
  115 +
  116 + this.slides = slides;
  117 +
  118 + // this.updateSlideWidth();
  119 + },
  120 + updatePos () {
  121 + this.findChild((child) => {
  122 + child.width = this.listWidth;
  123 + });
  124 +
  125 + this.trackWidth = (this.slides.length || 0) * this.listWidth;
  126 + },
  127 + // use when slot changed
  128 + slotChange () {
  129 + this.slides = [];
  130 + this.slideInstances = [];
  131 + },
  132 + handleResize () {
  133 + this.$nextTick(() => {
  134 + this.listWidth = parseInt(getStyle(this.$el, 'width'));
  135 + this.updatePos();
  136 + });
52 137 }
  138 + },
  139 + compiled () {
  140 + this.updateSlides(true);
  141 +
  142 + // watch slot changed
  143 + if (MutationObserver) {
  144 + this.observer = new MutationObserver(() => {
  145 + this.slotChange();
  146 + this.updateSlides(true, true);
  147 + });
  148 +
  149 + this.observer.observe(this.$els.slides, {
  150 + childList: true,
  151 + characterData: true,
  152 + subtree: true
  153 + });
  154 + }
  155 + },
  156 + ready () {
  157 + this.handleResize();
  158 + window.addEventListener('resize', this.handleResize, false);
  159 + },
  160 + beforeDestroy () {
  161 + window.removeEventListener('resize', this.handleResize, false);
53 162 }
54 163 };
55 164 </script>
... ...
src/styles/components/carousel.less
... ... @@ -8,4 +8,30 @@
8 8 user-select: none;
9 9 touch-action: pan-y;
10 10 -webkit-tap-highlight-color: transparent;
  11 +
  12 + &-track, &-list {
  13 + transform: translate3d(0, 0, 0);
  14 + }
  15 +
  16 + &-list {
  17 + position: relative;
  18 + display: block;
  19 + overflow: hidden;
  20 +
  21 + margin: 0;
  22 + padding: 0;
  23 + }
  24 +
  25 + &-track {
  26 + position: relative;
  27 + top: 0;
  28 + left: 0;
  29 + display: block;
  30 + }
  31 +
  32 + &-item {
  33 + float: left;
  34 + height: 100%;
  35 + min-height: 1px;
  36 + }
11 37 }
... ...
test/routers/carousel.vue
1 1 <template>
2   - <Carousel>
  2 + <Carousel style="width: 400px">
3 3 <Carousel-item>test1</Carousel-item>
4 4 <Carousel-item>test2</Carousel-item>
5 5 <Carousel-item>test3</Carousel-item>
... ...