如何使用JS和Ajax获取Tumblr帖子的下一页内容
Tumblr API 分页获取图片帖子实现方案
核心参数说明
Tumblr API 分页依赖以下关键参数,配合返回的total_posts字段实现完整分页逻辑:
limit:控制单页返回的帖子数量,API限制最大值为20,默认值也是20offset:指定需要跳过的帖子数,比如第一页用offset=0,第二页用offset=20,以此类推- 返回结果中的
total_posts:当前博客下符合条件的总帖子数,用来判断是否还有更多内容可加载
改造后的Redux Action(支持分页)
将原有单页请求的Action改为支持分页加载,同时处理帖子累加、加载状态和是否还有更多内容的判断:
export const getPostsWithPagination = (offset = 0) => { return (dispatch) => { dispatch(setLoading(true)); $.ajax({ url: `https://api.tumblr.com/v2/blog/somewhatadrift.tumblr.com/posts/photo?api_key=你的API密钥&limit=20&offset=${offset}`, type: "GET", success: function(result) { // 过滤出图片类型帖子 const newPosts = result.response.posts.filter(post => post.type === 'photo'); const totalPosts = result.response.total_posts; // 累加新帖子(而非替换原有内容) dispatch(addPosts(newPosts)); // 保存总帖子数 dispatch(setTotalPosts(totalPosts)); dispatch(setLoading(false)); // 判断是否还有更多帖子可加载 const hasMore = offset + 20 < totalPosts; dispatch(setHasMore(hasMore)); }, error: function() { dispatch(setLoading(false)); // 可添加错误提示逻辑 } }); } }
对应Reducer处理逻辑
修改Reducer以支持帖子累加、状态管理:
const initialState = { posts: [], totalPosts: 0, loading: false, hasMore: true, }; export default function blogReducer(state = initialState, action) { switch(action.type) { case 'ADD_POSTS': return { ...state, posts: [...state.posts, ...action.payload], }; case 'SET_TOTAL_POSTS': return { ...state, totalPosts: action.payload, }; case 'SET_LOADING': return { ...state, loading: action.payload, }; case 'SET_HAS_MORE': return { ...state, hasMore: action.payload, }; default: return state; } }
组件中实现分页加载(示例)
在React组件中调用分页Action,实现初始加载和加载更多功能:
import { useDispatch, useSelector } from 'react-redux'; import { getPostsWithPagination } from './actions'; import { useState, useEffect } from 'react'; function BlogPage() { const dispatch = useDispatch(); const { posts, loading, hasMore, totalPosts } = useSelector(state => state.blog); const [currentOffset, setCurrentOffset] = useState(0); // 页面初始化加载第一页 useEffect(() => { dispatch(getPostsWithPagination(0)); }, [dispatch]); // 加载更多按钮点击逻辑 const loadMore = () => { if (!loading && hasMore) { const newOffset = currentOffset + 20; dispatch(getPostsWithPagination(newOffset)); setCurrentOffset(newOffset); } }; return ( <div className="blog-page"> <div className="posts-grid"> {posts.map(post => ( <div key={post.id} className="post-item"> {/* 渲染图片,可根据需求选择不同尺寸的图片地址 */} <img src={post.photos[0].original_size.url} alt={post.caption || 'Tumblr图片'} /> {/* 渲染帖子描述,处理HTML格式 */} <div dangerouslySetInnerHTML={{__html: post.caption}}></div> </div> ))} </div> {loading && <div className="loading">加载中...</div>} {hasMore && !loading && ( <button onClick={loadMore} className="load-more-btn">加载更多</button> )} {!hasMore && <div className="end-notice">已加载全部{totalPosts}条图片帖子</div>} </div> ); } export default BlogPage;
注意事项
- API调用限制:Tumblr API对浏览器端调用有频率限制,避免短时间内发起大量请求
- 图片尺寸选择:每个图片帖子的
photos字段包含多种尺寸的图片地址,可根据页面布局选择合适的尺寸,优化加载速度 - 防抖处理:如果实现滚动加载,建议添加防抖逻辑,避免滚动时频繁触发请求
内容的提问来源于stack exchange,提问作者kristin1111
相关产品推荐
相关产品推荐

