轮播图卡顿,各位HTMLer请教,怎么解决?

我的问题

  • 我是用vue+element-ui布局
  • 我是一次性请求完数据库,不想要做一道请求一次
  • 我在做一个刷题功能,为了实现滑动功能,所以使用vue-awesome-swiper实现,一开始我的数据库只有10道题,所以没有太大压力,但是后来上线时,每个用户从数据库中随机抽取100道题目,用了v-for指令渲染100个swiper-slide,后来打开浏览器发现太卡了

    我的要求

    所以,我开始使用虚拟slide(virtual slide)来实现,但我发现,当我设置virtual: true的之后,轮播图不能滑动,接着我开始设置slides属性,不会用,接着,我发现了vue-virtual-scroller,但是它不能像轮播图一样,只能竖直显示,只是用来显示大量竖排数据,不能显示横着的轮播图,后来chatgpt-3.5告诉我使用vue-virtual-scroll-list,但还是不能横着显示,还是像vue-virtual-scroller一样,只能竖着显示,所以这个东西折磨了我一个五一,还是没有什么进展,请问怎么实现?

    我的代码 (代码技术欠缺,代码如有什么缺点,尽请原谅)

    这是我的前端结构:
    <!-- 实现滑动效果,用vue-awesome-swiper实现 -->
    <swiper :options='options' ref='subject-swiper' class="app-subjects-swiper">
      <!-- 每个题目 -->
      <swiper-slide v-for="(item, index) in   subjects  " class='subject-swiper-slide virtual-list-item'
          :key="index">
          <div class="app-virtual-list-item">
              <!-- 用来显示用户 ID 的隐藏元素 -->
              <div class='item-hide' style='display:none;'>{{ item.id }}</div>
              <!-- 题目头部部分 -->
              <div class='choices-item'>
                  <!-- 题目的标题 -->
                  <div class='item-title'>
                      <!-- 题目的编号 -->
                      <div class='title-index'>{{ index + 1 }}.&nbsp;</div>
                      <!-- 题目的类型以及题目的标题 -->
                      <div class='title-desc'>{{ item.type === 'singleton' ? '单选题' : item.type === 'multiple' ? '多选题' : item.type === 'judgment' ? '判断题' : '' }}{{ item.title }}
                      </div>
                  </div>
                  <!-- 题目的内容 -->
                  <div class='item-desc'>
                      <!-- 每个选项 -->
                      <div class='item-desc-item' v-for="($item, $index) in item.choice.split('|')"
                          :key='$index'
                          @click="handleClick($event, item.answer, 'ABCDE'[$index], item, index)">
                          <!-- 选项的标号 -->
                          <span class='item-icon'>{{ 'ABCDE'[$index] }}</span>.&nbsp;
                          <!-- 选项的内容 -->
                          <p class='text'>{{ $item }}</p>
                          <!-- icon -->
                          <div class='item-tick'><svg viewBox='0 0 48 48'
                                  xmlns='http://www.w3.org/2000/svg' class='icon-info icon-success'>
                                  <path
                                      d='M24,4 C35.045695,4 44,12.954305 44,24 C44,35.045695 35.045695,44 24,44 C12.954305,44 4,35.045695 4,24 C4,12.954305 12.954305,4 24,4 Z M34.5548098,16.4485711 C33.9612228,15.8504763 32.9988282,15.8504763 32.4052412,16.4485711 L32.4052412,16.4485711 L21.413757,27.5805811 L21.413757,27.5805811 L21.4034642,27.590855 C21.0097542,27.9781674 20.3766105,27.9729811 19.9892981,27.5792711 L19.9892981,27.5792711 L15.5947588,23.1121428 C15.0011718,22.514048 14.0387772,22.514048 13.4451902,23.1121428 C12.8516033,23.7102376 12.8516033,24.6799409 13.4451902,25.2780357 L13.4451902,25.2780357 L19.6260786,31.5514289 C20.2196656,32.1495237 21.1820602,32.1495237 21.7756472,31.5514289 L21.7756472,31.5514289 L34.5548098,18.614464 C35.1483967,18.0163692 35.1483967,17.0466659 34.5548098,16.4485711 Z'>
                                  </path>
                              </svg><svg viewBox='0 0 48 48' xmlns='http://www.w3.org/2000/svg'
                                  class='icon-info icon-error'>
                                  <path
                                      d='M24,4 C35.045695,4 44,12.954305 44,24 C44,35.045695 35.045695,44 24,44 C12.954305,44 4,35.045695 4,24 C4,12.954305 12.954305,4 24,4 Z M32.57818,15.42182 C32.0157534,14.8593933 31.1038797,14.8593933 30.541453,15.42182 L30.541453,15.42182 L24.0006789,21.9625941 L17.458547,15.42182 C16.8961203,14.8593933 15.9842466,14.8593933 15.42182,15.42182 C14.8593933,15.9842466 14.8593933,16.8961203 15.42182,17.458547 L15.42182,17.458547 L21.9639519,23.9993211 L15.42182,30.541453 C14.8593933,31.1038797 14.8593933,32.0157534 15.42182,32.57818 C15.9842466,33.1406067 16.8961203,33.1406067 17.458547,32.57818 L17.458547,32.57818 L24.0006789,26.0360481 L30.541453,32.57818 C31.1038797,33.1406067 32.0157534,33.1406067 32.57818,32.57818 C33.1406067,32.0157534 33.1406067,31.1038797 32.57818,30.541453 L32.57818,30.541453 L26.0374059,23.9993211 L32.57818,17.458547 C33.1406067,16.8961203 33.1406067,15.9842466 32.57818,15.42182 Z'>
                                  </path>
                              </svg></div>
                      </div>
                      <!-- 当用户答完当前题后,显示的答案解析 -->
                      <div class='item-more-desc'>
                          <!-- 只有多选题有确定按钮 -->
                          <div class='item-more-btn' v-show='currentSubject.mored[index]'>
                              <el-button @click='checkCorrect($event, item.answer, index);'>确定</el-button>
                          </div>
                          <!-- 题目的正确答案以及用户答案 -->
                          <div class='item-more-info'
                              v-show=' currentSubject.answer.showInfo[index.toString()] '>
                              <span>正确答案:
                              </span><span class='correct-answer'
                                  :style=" { 'color': 'var(--success-color)', 'font-size': 'large', 'font-weight': 'bold' } ">{{currentSubject.answer.correct[index]}}</span><span>
                                  您的答案:</span><span class='user-answer'
                                  :style=" { 'color': currentSubject.answer.correct[index] === currentSubject.answer.user[index.toString()] ? 'var(--success-color)' : 'var(--failed-color)', 'font-size': 'large', 'font-weight': 'bold' } ">{{currentSubject.answer.user[index]}}</span>
                          </div>
                      </div>
                  </div>
              </div>
          </div>
      </swiper-slide>
    </swiper>
    

这是我的subjects内容,(只显示10道题):


[
    {
        "id": 1348, 
        "title": "从最吸引人的点开始,比如胖瘦、民族、年龄等此类整体印象,以及发际线、肤色、伤疤、痣等突出特点。是比对证件登载相片与持证人本人相貌是否一致的哪个原则?( ) (0.0 分)", 
        "type": "singleton", 
        "choice": "先看人、再看证|认人点为先|初看分布局|五官辨细微", 
        "answer": "B"
    }, 
    {
        "id": 1616, 
        "title": "空管部门启动航班放行协调机制,( )启动旅客服务协调机制,协调海关、边防等联检单位,根据进出港航班运行情况,确保旅客快速办理联检手续; (0.0 分)", 
        "type": "singleton", 
        "choice": "机场旅客服务促进委员会|机场管理机构|机场运行指挥中心|航空公司", 
        "answer": "B"
    }, 
    {
        "id": 1244, 
        "title": "“中国人民解放军文职干部证”为本芯证件式样,发给( )。 (0.0 分)", 
        "type": "singleton", 
        "choice": "军队现役军官|军队文职干部|军队文职人员|军队职工", 
        "answer": "B"
    }, 
    {
        "id": 2312, 
        "title": "机场公安机关是指国家依法在机场设立的,对机场安保承担管理、监督、检查职责,独立执行( )的专门公安机关。 (0.0 分)", 
        "type": "singleton", 
        "choice": "覆盖民航安全检查安全管理工作任务|所辖区机场民航空防安全工作|覆盖民航系统全面安全保卫任务|民用航空运输机场安全运行全面指导、监督、管理", 
        "answer": "C"
    }, 
    {
        "id": 938, 
        "title": "根据( )的不同,旅客有效乘机身份证件可分为中国内地(大陆)地区居民有效乘机身份证件、港澳台地区居民有效乘机身份证件和外国人有效乘机身份证件三类。 (0.0 分)", 
        "type": "singleton", 
        "choice": "国籍|所属地区|国籍或所属地区|人员身份", 
        "answer": "C"
    }, 
    {
        "id": 979, 
        "title": "爆炸装置根据( ),可分为拉发结构的爆炸装置、压发结构的爆炸装置、松发结构的爆炸装置、定时结构的爆炸装置、反能动结构的爆炸装置等。 (0.0 分)", 
        "type": "singleton", 
        "choice": "制作的工艺不同|使用的用途不同|引信的结构不同|主要作用物(炸药)的不同", 
        "answer": "C"
    }, 
    {
        "id": 2504, 
        "title": "( )是团结的基础,是建立在平等信任的关系之上,而互相推诿扯皮是典型的个人主义和自由主义的表现,只能分裂团结,造成大家离心离德。 (0.0 分)", 
        "type": "singleton", 
        "choice": "互相信任与尊重|互相学习与帮助|团结奋进|互相尊重协作", 
        "answer": "D"
    }, 
    {
        "id": 648, 
        "title": "在购票、乘机登记、安检等环节均使用同一证件的前提下乘坐国内航班,有效期内的( ),予以放行。 (0.0 分)", 
        "type": "singleton", 
        "choice": "中华人民共和国普通电子护照|中华人民共和国居民身份证|中华人民共和国旅行证|中华人民共和国海员证", 
        "answer": "C"
    }, 
    {
        "id": 1527, 
        "title": "公共航空运输企业从事国际航空运输的民用航空器及其所载人员、行李、货物应当接受边防、海关等主管部门的检查;但是,检查时应当( )。 (0.0 分)", 
        "type": "singleton", 
        "choice": "避免对行李物品有所损坏|避免不必要的投诉|避免不必要的延误|注意文明执勤", 
        "answer": "C"
    }, 
    {
        "id": 2759, 
        "title": "电子客票(electronic ticket)是普通纸质机票的一种电子映像,是传统机票的一种替代品,可以实现客票的( ),电子化的订票、出票,办理乘机登记手续、登机、结算等过程。 (0.0 分)", 
        "type": "singleton", 
        "choice": "电子存储|无纸化存储|芯片存储|云存储", 
        "answer": "B"
    }
]

可以考虑使用别的轮播库,例如slick、swiper-carousel等,这些库支持虚拟滑动且对性能的优化效果较好,并且支持横向轮播

##根据@明月落乌江的说明,我现在已经更改了页面模式,但还是卡
#我的代码

<div class='slick'>
    <div class="slick-slide" v-for="(item, index) in subjects" :key="index">
        <!-- 每个题目 -->
        <div class="app-virtual-list-item">
            <!-- 用来显示用户 ID 的隐藏元素 -->
            <div class='item-hide' style='display:none;'>{{ item.id }}</div>
            <!-- 题目头部部分 -->
            <div class='choices-item'>
                <!-- 题目的标题 -->
                <div class='item-title'>
                    <!-- 题目的编号 -->
                    <div class='title-index'>{{ index + 1 }}.&nbsp;</div>
                    <!-- 题目的类型以及题目的标题 -->
                    <div class='title-desc'>{{ item.type === 'singleton' ? '单选题' : item.type === 'multiple' ? '多选题' : item.type === 'judgment' ? '判断题' : '' }}{{ item.title }}
                    </div>
                </div>
                <!-- 题目的内容 -->
                <div class='item-desc'>
                    <!-- 每个选项 -->
                    <div class='item-desc-item' v-for="($item, $index) in item.choice.split('|')"
                        :key='$index'
                        @click="handleClick($event, item.answer, 'ABCDE'[$index], item, index)">
                        <!-- 选项的标号 -->
                        <span class='item-icon'>{{ 'ABCDE'[$index] }}</span>.&nbsp;
                        <!-- 选项的内容 -->
                        <p class='text'>{{ $item }}</p>
                        <!-- icon -->
                        <div class='item-tick'><svg viewBox='0 0 48 48'
                                xmlns='http://www.w3.org/2000/svg' class='icon-info icon-success'>
                                <path
                                    d='M24,4 C35.045695,4 44,12.954305 44,24 C44,35.045695 35.045695,44 24,44 C12.954305,44 4,35.045695 4,24 C4,12.954305 12.954305,4 24,4 Z M34.5548098,16.4485711 C33.9612228,15.8504763 32.9988282,15.8504763 32.4052412,16.4485711 L32.4052412,16.4485711 L21.413757,27.5805811 L21.413757,27.5805811 L21.4034642,27.590855 C21.0097542,27.9781674 20.3766105,27.9729811 19.9892981,27.5792711 L19.9892981,27.5792711 L15.5947588,23.1121428 C15.0011718,22.514048 14.0387772,22.514048 13.4451902,23.1121428 C12.8516033,23.7102376 12.8516033,24.6799409 13.4451902,25.2780357 L13.4451902,25.2780357 L19.6260786,31.5514289 C20.2196656,32.1495237 21.1820602,32.1495237 21.7756472,31.5514289 L21.7756472,31.5514289 L34.5548098,18.614464 C35.1483967,18.0163692 35.1483967,17.0466659 34.5548098,16.4485711 Z'>
                                </path>
                            </svg><svg viewBox='0 0 48 48' xmlns='http://www.w3.org/2000/svg'
                                class='icon-info icon-error'>
                                <path
                                    d='M24,4 C35.045695,4 44,12.954305 44,24 C44,35.045695 35.045695,44 24,44 C12.954305,44 4,35.045695 4,24 C4,12.954305 12.954305,4 24,4 Z M32.57818,15.42182 C32.0157534,14.8593933 31.1038797,14.8593933 30.541453,15.42182 L30.541453,15.42182 L24.0006789,21.9625941 L17.458547,15.42182 C16.8961203,14.8593933 15.9842466,14.8593933 15.42182,15.42182 C14.8593933,15.9842466 14.8593933,16.8961203 15.42182,17.458547 L15.42182,17.458547 L21.9639519,23.9993211 L15.42182,30.541453 C14.8593933,31.1038797 14.8593933,32.0157534 15.42182,32.57818 C15.9842466,33.1406067 16.8961203,33.1406067 17.458547,32.57818 L17.458547,32.57818 L24.0006789,26.0360481 L30.541453,32.57818 C31.1038797,33.1406067 32.0157534,33.1406067 32.57818,32.57818 C33.1406067,32.0157534 33.1406067,31.1038797 32.57818,30.541453 L32.57818,30.541453 L26.0374059,23.9993211 L32.57818,17.458547 C33.1406067,16.8961203 33.1406067,15.9842466 32.57818,15.42182 Z'>
                                </path>
                            </svg></div>
                    </div>
                    <!-- 当用户答完当前题后,显示的答案解析 -->
                    <div class='item-more-desc'>
                        <!-- 只有多选题有确定按钮 -->
                        <div class='item-more-btn' v-show='currentSubject.mored[index]'>
                            <el-button @click='checkCorrect($event, item.answer, index);'>确定</el-button>
                        </div>
                        <!-- 题目的正确答案以及用户答案 -->
                        <div class='item-more-info'
                            v-show='currentSubject.answer.showInfo[index.toString()]'>
                            <span>正确答案:
                            </span><span class='correct-answer'
                                :style="{ 'color': 'var(--success-color)', 'font-size': 'large', 'font-weight': 'bold' }">{{ currentSubject.answer.correct[index] }}</span><span>
                                您的答案:</span><span class='user-answer'
                                :style="{ 'color': currentSubject.answer.correct[index] === currentSubject.answer.user[index.toString()] ? 'var(--success-color)' : 'var(--failed-color)', 'font-size': 'large', 'font-weight': 'bold' }">{{ currentSubject.answer.user[index] }}</span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>