Skip to content

다른 뷰를 가지는 슬라이드 컴포넌트

Yongku cho edited this page Nov 25, 2019 · 3 revisions

슬라이드 컴포넌트 두개가 있는 데, 상태와 로직이 모두 동일하다. 하지만 각자 다른 뷰를 가지고 있다.

추상화 대상은 무엇?

  • 두개의 컴포넌트
  • 컴포넌트의 상태와 로직
  • 뷰에 사용되는 비교연산
컴포넌트 코드
<button
  type="button"
  :class="{ disabled: currentSlide === MIN }"
  @click="prevSlide()"
>이전</button>
<button
  type="button"
  :class="{ disabled: currentSlide === max }"
  @click="nextSlide()"
>다음</button>
class HomeSlidePagination extends Vue {
  readonly MIN = 1
  readonly STEP = 1

  @Prop() currentSlide!: number
  @Prop() max!: number

  @Emit('on-change')
  handleChange(currentSlide): number {
    return currentSlide
  }

  nextSlide(): void {
    const currentSlide = this.currentSlide + this.STEP
    this.handleChange(currentSlide > this.max ? this.max : currentSlide)
  }

  prevSlide(): void {
    const currentSlide = this.currentSlide - this.STEP
    this.handleChange(currentSlide < this.MIN ? this.MIN : currentSlide)
  }
}

추상화 전략은 어떻게?

  • 불필요한 설계를 제거한다.
    • MIN, STEP불필요한 설계이다.
    • 슬라이드의 동작에 대한 대전재는 첫번째 페이지가 1일 것이고, 한 페이지씩 이동되기 때문이다.
  • 같은 코드라도 특수성을 가지는 부분은 유지한다.
    • Prop, Emit은 중복이라고 볼 수 없다.
    • 컴포넌트가 부모와 통신하기 위한 인터페이스이다.
  • 숫자 범위를 가지고 이동하는 로직을 일반화 가능한 부분이다.
    • 이유는 특정 컴포넌트에 특수성을 가지지 않고, 숫자범위에 따른 이동하는 로직이다.
    • 상태와 로직을 일반화해야 함으로 클래스로 구현해야 한다.

근거는?

결론

클래스 사용
<button
  type="button"
  :class="{ disabled: stepper.isMin }"
  @click="prevSlide()"
>이전</button>
<button
  type="button"
  :class="{ disabled: stepper.isMax }"
  @click="nextSlide()"
>다음</button>
class HomeSlidePagination extends Vue {
  @Prop() currentSlide!: number
  @Prop() max!: number

  @Emit('on-change')
  handleChange(): number {
    return this.stepper.currentPosition
  }

  stepper = Stepper.create(this.max)

  nextSlide(): void {
    this.stepper.next()
    this.handleChange()
  }

  prevSlide(): void {
    this.stepper.prev()
    this.handleChange()
  }

  @Watch('currentSlide')
  handleChangeCurrentSlide(): void {
    this.stepper.moveTo(this.currentSlide)
  }
}
클래스 생성
export class Stepper {
  readonly min: number
  readonly max: number
  readonly step: number
  private position: number

  private constructor(min: number, max: number, step: number, position: number) {
    this.min = min
    this.max = max
    this.step = step
    this.position = position
  }

  get isMax(): boolean {
    return this.position === this.max
  }
  get isMin(): boolean {
    return this.position === this.min
  }
  get currentPosition(): number {
    return this.position
  }

  next(): void {
    this.changePosition(this.position + this.step)
  }
  prev(): void {
    this.changePosition(this.position - this.step)
  }
  moveTo(position: number): void {
    this.changePosition(position)
  }

  private changePosition(position: number): void {
    this.position = this.calibratePosition(position)
  }
  private calibratePosition(position: number): number {
    return position > this.max
      ? this.max
      : position < this.min
        ? this.min
        : position
  }

  static create(max: number): Stepper {
    return new Stepper(1, max, 1, 1)
  }
}
Clone this wiki locally