VueJS - 向组件 v-for 添加延迟加载

Posted

技术标签:

【中文标题】VueJS - 向组件 v-for 添加延迟加载【英文标题】:VueJS - Add lazy loading to component v-for 【发布时间】:2021-06-04 03:44:19 【问题描述】:

我想增加我网站的加载时间。我目前有一个我所有项目的列表,所有项目在第一个页面加载时加载。我想对这些组件实现延迟加载,但我似乎找不到方法。

我有一个名为project-card的组件:

<project-card v-bind:project="project" v-bind:key="project.id" v-if="projects" v-for="project in filteredProjects"></project-card>

模板文件:

<template>
    <div class="project-card rounded dark:bg-gray-800 bg-white overflow-hidden shadow-lg rounded-lg flex flex-col relative">
        <img class="w-full h-64 object-cover" :src="'/uploads/' + project.image" >
        <div class="px-6 py-4 h-full flex flex-col">
            <div class="project-info block min-h-8">
                <div class="w-full">
                    <p class="tracking-widest text-xs title-font font-medium dark:text-white text-gray-500 mb-1"> project.language </p>
                </div>
            </div>
            <div class="project-language flex-1">
                <div class="w-5/6 float-left">
                    <p class="font-bold dark:text-white gilroy text-xl"> project.name </p>
                </div>
            </div>
            <div class="project-description flex-2 space-y-4 py-3 h-full">
                <p class="dark:text-white "> project.description | str_limit(128) </p>
            </div>
            <div class="read-more mt-auto">
                <div class="flex items-center flex-wrap ">
                    <button type="button" @click="openModal" class="font-bold text-sm text-indigo-600 hover:text-indigo-500 transition duration-150 ease-in-out hover:text-indigo-900 read-more-button flex items-center focus:outline-none">
                        Lees meer <span class="read-more-arrow ml-2">→</span>
                    </button>
                    <span class="text-gray-600 mr-3 inline-flex items-center lg:ml-auto md:ml-0 ml-auto leading-none text-sm pr-3 py-1 border-r-2 border-gray-300">

                    </span>
                    <span class="text-gray-600 inline-flex items-center leading-none text-sm">
                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke- viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4 mr-1">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke- d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
                        </svg>
                         project.stargazers_count 
                    </span>
                </div>
                <project-card-modal :project="project" ref="projectModal"></project-card-modal>
            </div>
        </div>
    </div>
</template>

<script>
    import projectCardModalComponent from "./projectCardModalComponent";

    export default 
        components: 
            projectCardModalComponent
        ,
        methods: 
            openModal() 
                this.$refs.projectModal.show = true;
            
        ,

        props: ['project']
    
</script>

目前它看起来像这样,所以它给出了它应该如何结果的想法。但我想对这个组件实现延迟加载。我怎样才能做到这一点?

APP.JS

import Vue from "vue";

require('./bootstrap');

window.Vue = require('vue');

Vue.component('project-card', require('./components/projectCardComponent.vue').default);
Vue.component('project-card-modal', require('./components/projectCardModalComponent.vue').default);
Vue.component('contact-form', require('./components/contactFormComponent.vue').default);
Vue.component('contact-form-flash', require('./components/contactFormFlashComponent.vue').default);
Vue.component('project-language-filter-button', require('./components/projectLanguageButtonFilterComponent.vue').default);
Vue.component('project-language-filter-dropdown', require('./components/projectLanguageDropdownFilterComponent.vue').default);
Vue.component('education', require('./components/educationComponent.vue').default);
Vue.component('work-experience', require('./components/workExperienceComponent.vue').default);

Vue.component('sidebar', require('./components/dashboard/dashboardSidebarComponent.vue').default);
Vue.component('projects', require('./components/dashboard/dashboardProjectsComponent.vue').default);

import MugenScroll from 'vue-mugen-scroll'

const app = new Vue(
    el: '#app',
    data: 
        showModal: false,
        projects: [],
        filteredProjects: [],
        languages: [],
        languageFilterKey: 'all',
        workExperiences: [],
        educations: [],

        search: '',
        pageSizeBegin: 0,
        pageSizeEnd: null,

        projectsLoading: false,
    ,
    mounted: function() 
        this.getProjects();
        this.getWorkExperiences();
        this.getAllEducations();
        this.getProjectLanguages();
    ,
    created() 
        this.getFilteredProjects();
    ,
    methods: 
        getProjects: function() 
            axios.get('/api/get/projects')
                .then(response => 
                    this.filteredProjects = this.projects = response.data
                ).catch(err => 
                console.log(err)
            );
        ,
        getFilteredProjects: function() 
            for(let i = 0;  i < 6; i++) 
                let count = this.filteredProjects.length + i
            
        ,
        getProjectLanguages: function() 
            axios.get('/api/get/project/languages')
                .then(response => 
                    this.languages = response.data
                ).catch(err => 
                console.log(err)
            );
        ,
        selectedLanguage: function() 
            if(this.languageFilterKey !== null) 
                this.languages.forEach((item) => 
                    item.active = item.language === this.languageFilterKey;
                );
             else 
                this.languageFilterKey = null
            
        ,
        filterProjectsByLanguage () 
            if(this.languageFilterKey === 'all') 
                this.filteredProjects = this.projects;
             else 
                this.filteredProjects = this.projects.filter((project) => 
                    return this.languageFilterKey === project.language
                );
            
        ,
        getWorkExperiences: function() 
            axios.get('/api/get/workexperiences')
                .then(response => 
                    this.workExperiences = response.data
                ).catch(err => 
                console.log(err)
            );
        ,
        getAllEducations: function() 
            axios.get('/api/get/educations')
                .then(response => 
                    this.educations = response.data
                ).catch(err => 
                console.log(err)
            );
        ,
        amountOnChange(event) 
            if(!event.target.value) 
                this.pageSizeEnd = null;
             else 
                this.pageSizeEnd = event.target.value;
            
        
    ,
    computed: 
        filteredList() 
            if(!this.pageSizeEnd) 
                return this.projects.filter((project) => 
                    return  project.name.toLowerCase().includes(this.search.toLowerCase()) || project.language.toLowerCase().includes(this.search.toLowerCase())
                )
            
            return this.projects.filter((project) => 
                return  project.name.toLowerCase().includes(this.search.toLowerCase()) || project.language.toLowerCase().includes(this.search.toLowerCase())
            ).slice(this.pageSizeBegin, this.pageSizeEnd)

        ,
    
)

Vue.filter('str_limit', function (value, size) 
    if (!value) return '';
    value = value.toString();

    if (value.length <= size) 
        return value;
    
    return value.substr(0, size) + '...';
);

【问题讨论】:

【参考方案1】:

我认为你想要的实际上是无限滚动。

lot of libs 正在这样做,我最喜欢的是 vue-mugen-scroll。

看看their demo,我认为它接近你的用例。

var vm = new Vue(
  el: '#vue-instance',
  data: 
    posts: [],
    loading: false
  ,
  created() 
    this.getPosts()
  ,
    methods: 
    getPosts() 
        for (var i = 0; i < 16; i++) 
                var count = this.posts.length + i
        this.posts.push(
          title: 'title ' + count
        )
      
    
  
);
<script src="https://unpkg.com/vue-mugen-scroll@0.2.5/dist/vue-mugen-scroll.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="vue-instance" class="container">
      <div class="row">
        <div  class="col-sm-6" v-for="(post, index) in posts">
        <div class="card m-4" style="width: 18rem;">
          <img class="card-img-top" src="https://via.placeholder.com/350x150">
          <div class="card-body">
            <h5 class="card-title"><strong> post.title </strong></h5>
            </div>
          </div>
        </div>  
      </div>
      <mugen-scroll :handler="getPosts" :should-handle="!loading">
        loading...
      </mugen-scroll>
</div>

【讨论】:

我不太明白如何在我的用例中实现这一点。你能示范一下吗?我用 app.js 文件更新了问题 好像你已经有了自己的分页系统,带有 pageSizeBegin 和 pageSizeEnd。 那是一组不同的项目。

以上是关于VueJS - 向组件 v-for 添加延迟加载的主要内容,如果未能解决你的问题,请参考以下文章

Vuejs 和 HTML 动态创建复杂的 JSON 对象并使用 V-for 向用户显示相同的对象

单击使用 v-for 创建的组件时,将类添加到特定的父 div

v-for在VueJS中,如何跟踪以前的组件数据?

Vuejs 使用 v-for 添加和删除类

将 EfCore 延迟加载代理与 blazor 一起使用

使用“v-on:”指令向 <router-link> 组件添加事件监听器 - VueJS