4

我有一个从 graphql 服务器获取帖子的组件。如果用户位于页面底部,它将获取更多帖子。我怎样才能检查他是否达到了它?我查看了clientHeight、innerHeight 和outerHeight,但只有clientHeight 才有意义。Probalby 我必须从中减去一些东西,但我不知道究竟是什么以及我错过了什么?

<script>
    import {getClient, query} from 'svelte-apollo';
    import ContentWrapper from '../layout/ContentWrapper.svelte';
    import {GET_POSTS} from "../services/posts/postsApi";

    let pageInfo;
    let first = 2;
    let after;

    const client = getClient();
    let posts = query(client, {query: GET_POSTS, variables: {first}});

    const fetchMore = () => {
        posts.fetchMore({
            variables: {first, after},
            updateQuery: (previousResult, {fetchMoreResult}) => {
                const newEdges = fetchMoreResult.getPosts.edges;
                const pageInfo = fetchMoreResult.getPosts.pageInfo;

                return newEdges.length
                        ? {
                            getPosts: {
                                __typename: previousResult.getPosts.__typename,
                                edges: [...previousResult.getPosts.edges, ...newEdges],
                                pageInfo
                            }
                        }
                        : previousResult;
            }
        })
    };

    const setState = queryData => {
        pageInfo = queryData.getPosts.pageInfo;
        after = pageInfo.endCursor;
        return '';
    };

    let y;
    let clientHeight;

    const checkScrollPosition = () => {
        if(clientHeight <= y)
            fetchMore();
    }
</script>

<svelte:window on:scroll={checkScrollPosition} bind:scrollY={y} />

<ContentWrapper>
    <div slot="header">
        <h4>Page of Pagination</h4>
    </div>
    <div slot="body" bind:clientHeight={clientHeight}>
        {#await $posts}
            <h3>Loading...</h3>
        {:then result}
            {setState(result.data)}
            {#each result.data.getPosts.edges as post}
                <div class="card">
                    <div class="card-content">
                        <p class="card-text">{post.node.body}</p>
                    </div>
                </div>
            {/each}
            <div id="paginator">
                {#if pageInfo}
                    {#if pageInfo.hasNextPage}
                        <div class="btn" on:click={fetchMore}>Next</div>
                    {/if}
                {/if}
            </div>
        {:catch error}
            {console.log(error)}
        {/await}
    </div>
</ContentWrapper>
4

2 回答 2

2

Intersection Observer是您在问题中寻找的。所有现代浏览器都支持该技术。有了它,您可以找到某个元素是否在屏幕上可见,然后获取更多项目。

您可以在此处查看Svelte IntersectionObserver 组件实现:它使用老式方式与 window.innerHeight 两种技术

于 2020-03-09T07:20:58.310 回答
0

好吧,这是我使用的一个简单的解决方法,以防可滚动 div 的高度对于所有屏幕尺寸都是固定的。

  • 所以,首先,将它包含在一个div和CSS中,设置overflow: scrollheight: 600px(任何固定高度)
  • 然后localhost,在浏览器开发工具的控制台中运行此函数,getX()并记下返回的值(我们将其称为“x”):
const getX = () => {
  let myDiv = document.querySelector('my-div-id')
  myDiv.scrollTop = myDiv.scrollHeight;
  return myDiv.scrollHeight - myDiv.scrollTop;
}
  • 然后在您的 Svelte 组件中:
<sript>
    let x = 585 // the value returned by getX() function
    let contentLength = 10; // number of items that load on the page initially
    
    const loadOnScroll = (elem) => {
       if (elem.scrollTop >= (elem.scrollHeight - x) ) {
         contentLength += 10; // load more as user scrolls to bottom
       }
    }
</script>

  <div id="my-div-id"
  on:scroll="{ () => loadOnScroll(document.querySelector('my-div-id')) }" >

    {#each items as item, i}
        {#if i < contentLength}
          <ul>
            <li>        
                <!-- Do something with item -->
            </li>
        </ul>
        {/if}
    {/each}
  </div>

每次用户滚动到 div 的底部时,这将从您的 API 中加载 10 个以上的获取项目。我知道它看起来有点分散,但是嘿,它有效;)

于 2021-12-22T11:39:43.693 回答