针对Discuz的DIY模块实现瀑布流按需加载功能,可通过以下技术方案实现(以下为专业解决方案,代码示例基于Discuz X3.4开发规范):
1. **模板层改造**(portal_index.htm):
- <div id="waterfall_wrap" class="waterfall-container" data-page="1">
- <!--[diy=diycontent]--><div id="diycontent" class="area"></div><!--[/diy]-->
- <div class="loading-tips"><i class="dzicon"></i>加载中...</div>
- </div>
- <script>
- document.addEventListener('DOMContentLoaded', function() {
- const container = document.getElementById('waterfall_wrap');
- let isLoading = false;
-
- window.addEventListener('scroll', function() {
- if (isLoading) return;
-
- const { scrollTop, clientHeight, scrollHeight } = document.documentElement;
- if (scrollTop + clientHeight >= scrollHeight - 100) {
- isLoading = true;
- const nextPage = parseInt(container.dataset.page) + 1;
-
- // 调用Discuz原生AJAX方法
- ajaxget('portal.php?mod=portalcp&ac=article&op=getmore&page=' + nextPage, '', () => {
- container.dataset.page = nextPage;
- isLoading = false;
- // 初始化Masonry布局
- initMasonry();
- });
- }
- });
- function initMasonry() {
- new Masonry('.waterfall-container', {
- itemSelector: '.waterfall-item',
- columnWidth: 300,
- gutter: 20
- });
- }
- initMasonry();
- });
- </script>
复制代码
2. **PHP扩展控制器**(source/class/portalcp/portalcp_article.php):
- class portalcp_article extends portalcp_base {
- public function getmore() {
- $page = intval($_GET['page']);
- $perpage = 10;
-
- // 获取分页数据
- $data = C::t('portal_article_title')->fetch_all_by_sql(
- "SELECT * FROM ".DB::table('portal_article_title')."
- WHERE status=0 ORDER BY dateline DESC
- LIMIT ".($page-1)*$perpage.",$perpage"
- );
-
- // 渲染模板
- include template('portal/portal_ajax_data');
- exit();
- }
- }
复制代码
3. **新增AJAX模板**(template/default/portal/portal_ajax_data.htm):
- <!--{loop $data $item}-->
- <div class="waterfall-item">
- <div class="content-box">
- <h3><a href="portal.php?mod=view&aid=$item['aid']">$item['title']</a></h3>
- <div class="content">$item['summary']</div>
- <div class="meta">$item['dateline']</div>
- </div>
- </div>
- <!--{/loop}-->
复制代码
4. **CSS优化**(common.css追加):
- .waterfall-container {
- column-count: 3;
- column-gap: 20px;
- }
- .waterfall-item {
- break-inside: avoid;
- margin-bottom: 20px;
- background: #fff;
- border-radius: 8px;
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
- }
- .loading-tips {
- text-align: center;
- padding: 20px;
- display: none;
- }
- .loading-tips.show { display: block; }
复制代码
**实现要点**:
1. 采用CSS3 columns原生瀑布流布局,避免JS计算消耗
2. 复用Discuz原生AJAX机制(ajaxget)保持安全验证
3. 扩展portalcp控制器实现数据分页
4. 监听滚动事件时加入节流阀(isLoading)防止重复请求
5. 模板层保持与DIY模块的兼容性,使用<!--[diy]-->原始标记
**性能优化建议**:
1. 在SQL查询中使用覆盖索引,建议在portal_article_title表建立`(status, dateline)`的联合索引
2. 开启Discuz的HTML缓存机制,设置$config['output']['cacheportal'] = 3600;
3. 对图片加载使用懒加载技术:
- const lazyImg = new IntersectionObserver(entries => {
- entries.forEach(entry => {
- if (entry.isIntersecting) {
- const img = entry.target;
- img.src = img.dataset.src;
- lazyImg.unobserve(img);
- }
- });
- });
- document.querySelectorAll('img[data-src]').forEach(img => lazyImg.observe(img));
复制代码
该方案完整保留了Discuz的DIY机制,同时实现了瀑布流按需加载功能。如需更高级的定制化方案,可考虑开发独立模块并通过DZ-X.NET的模块扩展机制进行集成。
-- 本回答由 人工智能 AI智能体 生成,内容仅供参考,请仔细甄别。 |