You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Livewire实现Statamic移动端动态调整条目显示数量

问题:根据屏幕尺寸动态调整Livewire组件的文章显示条数

首次使用Livewire开发,现有一个Statamic Livewire组件用于展示博客文章集合,默认显示9条,但移动端(屏幕宽度<768px)需要调整为3条,尝试用JavaScript连接Livewire未成功,求实现方案。

组件代码如下:

<?php

namespace App\Livewire;

use Livewire\Component;
use Statamic\Facades\Collection;

class FilterCollection extends Component
{
    public $taxonomyField;
    public $taxonomySlug;
    public $collectionName;
    public $viewName = 'collection';
    public $offset = 0;
    public $limit = 9;
    public $q;
    public $defaultSortBy = 'desc';
    public $sortBy;
    public $cards = [
        'blog_articles' => '_blog-list-card',
    ];

    public function render()
    {
        $newEntries = Collection::find($this->collectionName)
        ->queryEntries()
        ->where('published', 1)
        ->orderBy('date', $this->defaultSortBy)
        ->offset($this->offset)
        ->limit($this->limit);

        if (!empty($this->taxonomySlug)) {
            $newEntries->whereTaxonomy($this->taxonomyField . '::' . $this->taxonomySlug);
        }
        if (!empty($this->q)) {
            $newEntries->where(function ($query) {
                $query->where('title', 'like', '%' . $this->q . '%')
                    ->orWhere('article_summary', 'like', '%' . $this->q . '%')
                    ->orWhere('page_builder', 'like', '%' . $this->q . '%');;
            });
        }

        return view('livewire.filter-' . $this->viewName, ['entries' => $newEntries]);
    }

    public function filterCollection($taxonomySlug)
    {
        $this->taxonomySlug = $taxonomySlug;
    }

    public function loadMore()
    {
        $this->limit += $this->limit;
    }

    public function mount($collectionName, $taxonomyField = 'articles_tags', $q = null)
    {
        $this->collectionName = $collectionName ?? 'articles';
        $this->taxonomyField = $taxonomyField;
        $this->q = $q;
    }

}

解决方案

1. 给组件添加响应式状态与更新方法

修改组件类,添加移动端判断属性,并实现根据屏幕状态更新limit的方法:

<?php

namespace App\Livewire;

use Livewire\Component;
use Statamic\Facades\Collection;

class FilterCollection extends Component
{
    // 标记是否为移动端
    public $isMobile = false;
    // 基础显示条数,用于统一加载增量
    private $baseLimitDesktop = 9;
    private $baseLimitMobile = 3;

    public $taxonomyField;
    public $taxonomySlug;
    public $collectionName;
    public $viewName = 'collection';
    public $offset = 0;
    public $limit = 9;
    public $q;
    public $defaultSortBy = 'desc';
    public $sortBy;
    public $cards = [
        'blog_articles' => '_blog-list-card',
    ];

    // 根据屏幕状态更新显示条数
    public function updateLimitBasedOnScreen($isMobile)
    {
        $this->isMobile = $isMobile;
        // 重置为对应设备的基础条数,避免loadMore后的值混乱
        $this->limit = $isMobile ? $this->baseLimitMobile : $this->baseLimitDesktop;
    }

    // 修改loadMore逻辑:按对应设备的基础条数增量加载
    public function loadMore()
    {
        $addAmount = $this->isMobile ? $this->baseLimitMobile : $this->baseLimitDesktop;
        $this->limit += $addAmount;
    }

    public function render()
    {
        $newEntries = Collection::find($this->collectionName)
        ->queryEntries()
        ->where('published', 1)
        ->orderBy('date', $this->defaultSortBy)
        ->offset($this->offset)
        ->limit($this->limit);

        if (!empty($this->taxonomySlug)) {
            $newEntries->whereTaxonomy($this->taxonomyField . '::' . $this->taxonomySlug);
        }
        if (!empty($this->q)) {
            $newEntries->where(function ($query) {
                $query->where('title', 'like', '%' . $this->q . '%')
                    ->orWhere('article_summary', 'like', '%' . $this->q . '%')
                    ->orWhere('page_builder', 'like', '%' . $this->q . '%');;
            });
        }

        return view('livewire.filter-' . $this->viewName, ['entries' => $newEntries]);
    }

    public function filterCollection($taxonomySlug)
    {
        $this->taxonomySlug = $taxonomySlug;
    }

    public function mount($collectionName, $taxonomyField = 'articles_tags', $q = null)
    {
        $this->collectionName = $collectionName ?? 'articles';
        $this->taxonomyField = $taxonomyField;
        $this->q = $q;
    }

}

2. 在视图中添加JavaScript监听窗口变化

在组件对应的视图文件(livewire.filter-collection.blade.php)底部添加以下代码,监听窗口resize事件并同步状态到Livewire后端:

<script>
// 防抖函数,避免窗口拖动时频繁触发请求
function debounce(func, wait) {
    let timeout;
    return function() {
        const context = this;
        const args = arguments;
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(context, args), wait);
    };
}

// 检查当前是否为移动端
function checkIsMobile() {
    return window.innerWidth < 768;
}

// 页面初始化时同步一次屏幕状态
document.addEventListener('livewire:initialized', () => {
    @this.updateLimitBasedOnScreen(checkIsMobile());
});

// 监听窗口resize事件,防抖后更新状态
window.addEventListener('resize', debounce(() => {
    @this.updateLimitBasedOnScreen(checkIsMobile());
}, 300));
</script>

说明

  • 防抖函数设置300毫秒延迟,减少不必要的Livewire请求
  • 初始化时自动检测屏幕尺寸并设置对应显示条数
  • 窗口大小变化时,自动重置显示条数为对应设备的基础值,保证移动端始终从3条开始加载
  • 修改后的loadMore方法,移动端每次加载3条,桌面端每次加载9条,逻辑更符合场景需求

内容的提问来源于stack exchange,提问作者D Silva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 21:56:06