Element Plus Affix 고정 못 실현

구성 요소 소개
Affix 구성 요 소 는 페이지 요 소 를 특정 시각 영역 에 고정 시 키 는 데 사 용 됩 니 다.
1.1 속성
  • position:고정 못 의 위 치 를 지정 하고 top 또는 bottom 으로 설정 할 수 있 으 며 기본 값 은 top
  • 입 니 다.
  • offset:오프셋 거 리 를 설정 합 니 다.기본 값 은 0
  • 입 니 다.
  • target:용기(CSS 선택 기)를 지정 하여 고정 못 을 용기 안에 계속 유지 하고 범 위 를 초과 하면 숨 깁 니 다.기본 용 기 는 document.documentElement 입 니 다.
  • z-index:고정 못 의 등급,기본 100
  • 1.2 이벤트
  • scroll:용기 가 굴 러 갈 때 이벤트 가 발생 합 니 다.매개 변 수 는 고정 못 의 scroll Top 값 과 상태(fixed 여부)
  • 입 니 다.
  • change:고정 못 상태 가 바 뀌 었 을 때 촉발 합 니 다.매개 변 수 는 고정 못 이 현재 fixed 상태 에 있 는 지 여부
  • 2.소스 코드 분석
    2.1 template
    
    <template>
      <div ref="root" class="el-affix" :style="rootStyle">
        <div :class="{'el-affix--fixed': state.fixed}" :style="affixStyle">
          <slot></slot>
        </div>
      </div>
    </template>
    
    template 부분 은 간단 합 니 다.slot 를 통 해 내용 을 받 습 니 다.
    2.2 script
    
    //       ,        
    setup(props, { emit }) {
        // target   ref
        const target = ref(null) 
        //   ref, template  ref    ,  HTML  
        const root = ref(null)
        //     ref
        const scrollContainer = ref(null)
        
        //     
        const state = reactive({
          fixed: false,
          height: 0, // height of root
          width: 0, // width of root
          scrollTop: 0, // scrollTop of documentElement
          clientHeight: 0, // clientHeight of documentElement
          transform: 0,
        })
        
        onMounted(() => {
          //      target   target  
          if (props.target) {
            target.value = document.querySelector(props.target)
            if (!target.value) {
              throw new Error(`target is not existed: ${props.target}`)
            }
          } else {
            target.value = document.documentElement
          }
          
          //       ,        
          scrollContainer.value = getScrollContainer(root.value)
          //        scroll  
          on(scrollContainer.value, 'scroll', onScroll)
          //        resize  
          addResizeListener(root.value, updateState)
        })
        
        //      scroll       
        const onScroll = () => {
          //       
          updateState()
          
          emit('scroll', {
            scrollTop: state.scrollTop,
            fixed: state.fixed,
          })
        }
        
        //         
        const updateState = () => {
          const rootRect = root.value.getBoundingClientRect()
          const targetRect = target.value.getBoundingClientRect()
          state.height = rootRect.height
          state.width = rootRect.width
          state.scrollTop = scrollContainer.value === window ? document.documentElement.scrollTop : scrollContainer.value.scrollTop
          state.clientHeight = document.documentElement.clientHeight
    
          if (props.position === 'top') {
            if (props.target) {
              const difference = targetRect.bottom - props.offset - state.height
              // targetRect.bottom > 0                ,       
              state.fixed = props.offset > rootRect.top && targetRect.bottom > 0
              //       :     ,target               ,        ,     
              state.transform = difference < 0 ? difference : 0
            } else {
              state.fixed = props.offset > rootRect.top
            }
          } else {
            if (props.target) {
              const difference = state.clientHeight - targetRect.top - props.offset - state.height
              state.fixed = state.clientHeight - props.offset < rootRect.bottom && state.clientHeight > targetRect.top
              state.transform = difference < 0 ? -difference : 0
            } else {
              state.fixed = state.clientHeight - props.offset < rootRect.bottom
            }
          }
        }
        //     fixed    ,   emit change  
        watch(() => state.fixed, () => {
          emit('change', state.fixed)
        })
        
        //     ,                
        const affixStyle = computed(() => {
          if (!state.fixed) {
            return
          }
          const offset = props.offset ? `${props.offset}px` : 0
          const transform = state.transform ? `translateY(${state.transform}px)` : ''
    
          return {
            height: `${state.height}px`,
            width: `${state.width}px`,
            top: props.position === 'top' ? offset : '',
            bottom: props.position === 'bottom' ? offset : '',
            transform: transform,
            zIndex: props.zIndex,
          }
        })
    }
    2.3 총 결 실현:
  • 스크롤 용기 의 scroll 이벤트(및 고정 못 자체 의 resize 이벤트)를 감청 합 니 다.
  • 이벤트 응답 함수 에서 고정 못 및 target 용기 의 DOM 속성 을 동적 으로 가 져 와 고정 못 의 상 태 를 계산 합 니 다.
  • 계산 속성 을 이용 하여 고정 못 의 스타일 을 자동 으로 업데이트 합 니 다.
  • Element Plus 가 Affix 고정 못 을 실현 하 는 것 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 Element Affix 고정 못 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 저 희 를 많이 사랑 해 주세요!

    좋은 웹페이지 즐겨찾기