Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <script lang="ts">
- import Vue, { CreateElement, VNode, RenderContext } from "vue"
- import {DefaultProps} from "vue/types/options";
- export default Vue.extend({
- name: "Visible",
- props: {
- threshold: {
- type: [Array, Number],
- default: 0
- },
- rootMargin: {
- type: String,
- default: '0px 0px 0px 0px'
- }
- },
- data() {
- return {
- visible: false,
- observer: null as IntersectionObserver|null,
- rootElement: null,
- }
- },
- mounted() {
- this.updateRootElement()
- this.initObserver()
- },
- updated() {
- this.updateRootElement()
- },
- beforeDestroy() {
- this.destroyObserver()
- },
- methods: {
- destroyObserver() {
- if (this.observer) {
- this.observer.disconnect()
- this.observer = null
- }
- },
- initObserver() {
- this.destroyObserver()
- if (!this.$isServer) {
- this.observer = new IntersectionObserver(async (entries: IntersectionObserverEntry[], observer: IntersectionObserver) => {
- console.log('hit', arguments);
- this.visible = entries.some(entry => entry.intersectionRatio > 0)
- }, {threshold: this.threshold, rootMargin: this.rootMargin})
- this.observe()
- }
- },
- isElement(element) {
- return typeof Element !== 'undefined' && element instanceof Element
- },
- updateRootElement() {
- this.rootElement = this.$el
- },
- observe(element = this.observing) {
- if (this.isElement(element)) this.observer.observe(element)
- },
- unobserve(element) {
- if (this.isElement(element)) this.observer.unobserve(element)
- },
- },
- computed: {
- observing() {
- return this.isElement(this.rootElement) ? this.rootElement : null
- },
- },
- watch: {
- observing(val, oldVal) {
- if (val !== oldVal) {
- this.unobserve(oldVal)
- if (val) {
- this.observe(val)
- }
- }
- },
- threshold(val, oldVal) {
- if (val !== oldVal) this.initObserver()
- },
- margin(val, oldVal) {
- if (val !== oldVal) this.initObserver()
- },
- },
- render(createElement: CreateElement, context: RenderContext<DefaultProps>): VNode {
- const slotContent = this.$scopedSlots.default && this.$scopedSlots.default({visible: this.visible})
- const slotRoot = Array.isArray(slotContent) ? slotContent.pop() : null
- return slotRoot || createElement('span', {class: 'test-visibility'})
- }
- })
- </script>
- <style scoped>
- .test-visibility {
- display: block;
- height: 0;
- width: 0;
- }
- </style>
- // usage:
- <visible v-slot:default="slot">
- <LazyCommonMainSlider :items="mainSlides" v-if="slot.visible"/>
- </visible>
Add Comment
Please, Sign In to add comment