Forráskód Böngészése

锚点公共组件

洪海涛 4 éve
szülő
commit
9d838c2117
3 módosított fájl, 167 hozzáadás és 0 törlés
  1. 1 0
      package.json
  2. 147 0
      src/components/affix/affix.vue
  3. 19 0
      src/components/affix/utils.js

+ 1 - 0
package.json

@@ -28,6 +28,7 @@
     "@tinymce/tinymce-vue": "^3.2.2",
     "animate.css": "^3.7.2",
     "axios": "^0.19.2",
+    "add-dom-event-listener": "^1.1.0",
     "browserslist": "^4.12.0",
     "caniuse-lite": "^1.0.30001084",
     "cnpm": "^6.1.1",

+ 147 - 0
src/components/affix/affix.vue

@@ -0,0 +1,147 @@
+<template>
+  <div ref="placeholderNode" :style="{ ...placeholderNodeStyle }">
+    <div ref="fixedNode" :style="{ ...fixedNodeStyle }">
+      <slot />
+    </div>
+  </div>
+</template>
+
+<script>
+import { TRIGGER_EVENTS, getDefaultTarget } from './utils'
+import addDOMEventListener from 'add-dom-event-listener'
+
+import _ from 'lodash'
+
+export default {
+  name: 'Affix',
+  props: {
+    /**
+     * 距离窗口顶部达到指定偏移量后触发
+     */
+    offsetTop: {
+      type: Number,
+      required: false,
+      default: () => null
+    },
+    offset: {
+      type: Number,
+      required: false,
+      default: () => null
+    },
+    /** 距离窗口底部达到指定偏移量后触发 */
+    offsetBottom: {
+      type: Number,
+      required: false,
+      default: () => null
+    },
+    /** 固定状态改变时触发的回调函数 */
+    // onChange?: (_Affixed?: boolean) => void;
+    /** 设置 _Affix 需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 */
+    target: {
+      type: Function,
+      required: false,
+      default: () => getDefaultTarget()
+    },
+    prefixCls: {
+      type: String,
+      required: false,
+      default: () => null
+    }
+  },
+  data() {
+    this.lazyUpdatePosition = _.throttle(this.lazyUpdatePosition, 300)
+    return {
+      placeholderNodeStyle: '',
+      fixedNodeStyle: '',
+      entity: {
+        target: null,
+        affixList: [],
+        eventHandlers: {}
+      }
+    }
+  },
+  mounted() {
+    // console.log(this.target().Target)
+    this.init()
+  },
+  // 销毁事件
+  destroyed() {
+    this.unInit()
+  },
+  methods: {
+    init() {
+      const { entity } = this
+      const targetNode = this.target()
+      TRIGGER_EVENTS.forEach((eventName) => {
+        // targetNode.addEventListener(eventName, () => {
+        //   this.lazyUpdatePosition()
+        // })
+        entity.eventHandlers[eventName] = addDOMEventListener(
+          targetNode,
+          eventName,
+          () => {
+            this.lazyUpdatePosition()
+          }
+        )
+      })
+    },
+    // @ts-ignore TS6133
+    prepareMeasure() {
+      this.fixedNodeStyle = null
+      this.placeholderNodeStyle = null
+      this.$forceUpdate()
+    },
+    getOffsetTop() {
+      const { offset, offsetBottom } = this
+      let { offsetTop } = this
+      if (typeof offsetTop === 'undefined') {
+        offsetTop = offset
+      }
+
+      if (offsetBottom === undefined && offsetTop === undefined) {
+        offsetTop = 0
+      }
+      return offsetTop
+    },
+    lazyUpdatePosition() {
+      const targetNode = this.target()
+      const offsetTop = this.getOffsetTop()
+      // console.log(102, this.$refs, targetNode.scrollTop)
+      if (targetNode.scrollTop < offsetTop) {
+        this.prepareMeasure()
+        return
+      }
+
+      const placeholderReact = this.$refs.placeholderNode
+      this.fixedNodeStyle = {
+        position: 'fixed',
+        top: `${offsetTop}px`,
+        zIndex: 999,
+        width: placeholderReact.offsetWidth + 'px',
+        height: placeholderReact.offsetHeight + 'px'
+      }
+      this.placeholderNodeStyle = {
+        width: placeholderReact.offsetWidth + 'px',
+        height: placeholderReact.offsetHeight + 'px'
+      }
+    },
+    unInit() {
+      const { entity } = this
+      // const targetNode = this.target()
+      // console.log(123, targetNode)
+      TRIGGER_EVENTS.forEach((eventName) => {
+        // targetNode.removeEventListener(eventName, () => {
+        //   this.lazyUpdatePosition()
+        // })
+        // entity.eventHandlers[eventName]
+        const handler = entity.eventHandlers[eventName]
+        if (handler && handler.remove) {
+          handler.remove()
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style scoped lang="less"></style>

+ 19 - 0
src/components/affix/utils.js

@@ -0,0 +1,19 @@
+/**
+ * @author 洪海涛
+ * @date 2021年04月02日 6:26 下午
+ */
+
+// ======================== Observer ========================
+export const TRIGGER_EVENTS = [
+  'resize',
+  'scroll',
+  'touchstart',
+  'touchmove',
+  'touchend',
+  'pageshow',
+  'load'
+]
+
+export function getDefaultTarget() {
+  return typeof window !== 'undefined' ? window : null
+}