parsa
5 سال پیش توسط parsa مطرح شد
11 پاسخ

اسکرول بی نهایت از طریق paginate و vuejs

سلام دوستان

برای ایجاد اسکرول بی نهایت در صفحه پست ها از طریق paginate و vuejs بهترین کار چیه ؟
چطوری دیتا رو به vue پاس بدم ؟ منظورم اینه با props باشه یا مثلا از طریق متد created درخواست axios بفرستم و پست ها رو بگیرم؟
لطفا یک توضیح کامل بدید اگر نمونه کد هم داشته باشید ممنون میشم


ثبت پرسش جدید
علی بیات
تخصص : توسعه دهنده ارشد وب
@ali.bayat 5 سال پیش آپدیت شد
6

@miladfathi021

درود

همونطور که آقای موسوی اشاره کردند پکیج های آماده‌ای برای این کار هست اما در کل چیز پیچیده‌ای نیست

در جاوااسکریپت ... در شئ window رویدادی داریم به نام onscroll که میتونید ازش استفاده کنید; سپس با استفاده از پراپرتیهای scrollTop و offsetHeight از شئ document و پراپرتی innerHeight از شئ window چک کنید که آیا کاربر به پایین صفحه رسیده یا نه.

به طور مثال اگر بخواهیم پست‌های یه بلاگ رو اینطوری نمایش بدیم...مراحل کار میتونه شبیه به زیر باشه:

  • پیاده‌سازی وب سرویس به همراه pagination
  • گرفتن اطلاعات اولیه پست ها
  • پیاده‌سازی لاجیک مربوط به اسکرول بی‌نهایت

پیاده‌سازی وب سرویس به همراه pagination

ابتدا تیاز دارید Route های مربوط به API رو که باید شامل حداقل یه پارامتر Current Page باشه پیاده‌سازی کنید. مثلا آدرس API شما به شکل زیر باشه:

https://yourAPI.com/api/posts/page/1

و اگر هم page رو بهش پاس ندید، صفحه اول رو برگردونه


گرفتن اطلاعات اولیه پست ها

ابتدا ۲ گزینه رو مقداردهی میکنیم. اولی posts هست که برابر یه آرایه خالی قرار میدیم و دومی currentPage یا صفحه فعلی هست که برابر ۱ قرار میدیم.

قبل از هر کاری وقتی کاربر صفحه رو باز میکنه ما باید صفحه اول رو بهش نشون بدیم.. پس از متد getInitialPosts استفاده میکنیم; این متد با یه درخواست axios پست‌های مربوطه رو میگیره و داخل آرایه posts قرار میده. حال کافیه این متد رو قبل از اینکه کامپوننت Mount بشه اجرا کنیم »» پس getInitialPosts رو درون ()beforeMount قرار میدیم.

پس کامپوننت Mount میشه و در این حین اطلاعات اولیه (صفحه اول پست‌ها) رو هم از API دریافت کرده.... حال در بخش Template هم با یه v-for بسادگی آرایه رو پیمایش میکنیم و پست هارو نشون میدیم.


پیاده‌سازی لاجیک مربوط به اسکرول بی‌نهایت

تا اینجا همه کارها، کارهای معمولی بوده که با Vue انجام میشه. برای پیاده‌سازی اسکرول بی نهایت باید یه متد دیگه هم بسازیم.. پس متدی به نام infiniteScroll اضافه میکنیم و داخلش با استفاده از رویداد window.onscroll چک میکنیم که آیا به انتهای صفحه رسیدیم یا نه.
اگر به انتهای صفحه رسیده باشیم »»» مقدار currentPage رو یکی افزایش میدیم و با یه درخواست axios دیگه اطلاعات صفحه بعد رو دریافت میکنیم و به انتهای آرایه posts اضافه میکنیم...
و چون VueJs از Two-way data binding پشتیبانی میکنه به محض اضافه شدن پست های جدید‌ (به آرایه posts) ، کامپوننت دوباره رندر میشه و اطلاعات جدید رو هم نشون میده.
تنها کاری که باقی میمونه اینه که بعد از اینکه کامپوننت Mount شد (که پس از هر رندر اتفاق میفته)، متد ()infiniteScroll رو فراخوانی کنیم.. پس این متد رو داخل ()mounted قرار میدیم.


کلیت کار به همین روال انجام میشه و بقیه کارها مربوط به UI میشه که مثلا تا وقتی اطلاعات داره برمی‌گرده یه Loader هم نمایش داده بشه.

قسمت Template کامپوننت:

<template>
  <div id="app">
    <h1>Posts</h1>
    <div v-for="post in posts">
      <div class="postCard">
        <img :src="post.picture.large" />
      </div>
      <div>
        <p>{{ post.title }} {{ post.created_at }}</p>
        <p>{{ post.body }}</p>
      </div>
    </div>
  </div>
</template>

قسمت Script کامپوننت:

<script>
export default {
  data() {
    return {
      posts: [],
      currentPage: 1
    };
  },

  methods: {
    getInitialPosts() {
      axios.get(`https://yourAPI.com/api/posts`).then(response => {
        this.posts = response.data;
      });
    },

    infiniteScroll(post) {
      window.onscroll = () => {
        let bottomOfWindow =
          document.documentElement.scrollTop + window.innerHeight ===
          document.documentElement.offsetHeight;

        if (bottomOfWindow) {
          this.currentPage++;
          axios
            .get(`https://yourAPI.com/api/posts/page/${this.currentPage}`)
            .then(response => {
              this.posts.push(response.data);
            });
        }
      };
    }
  },

  mounted() {
    this.infiniteScroll(this.post);
  },

  beforeMount() {
    this.getInitialPosts();
  }
};
</script>

موفق باشید


حسام موسوی
تخصص : طراح و برنامه نویس
@hesammousavi 5 سال پیش مطرح شد
1

سلام برای صفحه بندی که اطلاعات رو با props پاس نمیدن
باید درخواست ajax ایجاد کنید.
البته پکیج‌های آماده‌ای برای vue-pagination هم هست که میتونید از اونها هم بهرمند بشید.


علی بیات
تخصص : توسعه دهنده ارشد وب
@ali.bayat 5 سال پیش آپدیت شد
6

@miladfathi021

درود

همونطور که آقای موسوی اشاره کردند پکیج های آماده‌ای برای این کار هست اما در کل چیز پیچیده‌ای نیست

در جاوااسکریپت ... در شئ window رویدادی داریم به نام onscroll که میتونید ازش استفاده کنید; سپس با استفاده از پراپرتیهای scrollTop و offsetHeight از شئ document و پراپرتی innerHeight از شئ window چک کنید که آیا کاربر به پایین صفحه رسیده یا نه.

به طور مثال اگر بخواهیم پست‌های یه بلاگ رو اینطوری نمایش بدیم...مراحل کار میتونه شبیه به زیر باشه:

  • پیاده‌سازی وب سرویس به همراه pagination
  • گرفتن اطلاعات اولیه پست ها
  • پیاده‌سازی لاجیک مربوط به اسکرول بی‌نهایت

پیاده‌سازی وب سرویس به همراه pagination

ابتدا تیاز دارید Route های مربوط به API رو که باید شامل حداقل یه پارامتر Current Page باشه پیاده‌سازی کنید. مثلا آدرس API شما به شکل زیر باشه:

https://yourAPI.com/api/posts/page/1

و اگر هم page رو بهش پاس ندید، صفحه اول رو برگردونه


گرفتن اطلاعات اولیه پست ها

ابتدا ۲ گزینه رو مقداردهی میکنیم. اولی posts هست که برابر یه آرایه خالی قرار میدیم و دومی currentPage یا صفحه فعلی هست که برابر ۱ قرار میدیم.

قبل از هر کاری وقتی کاربر صفحه رو باز میکنه ما باید صفحه اول رو بهش نشون بدیم.. پس از متد getInitialPosts استفاده میکنیم; این متد با یه درخواست axios پست‌های مربوطه رو میگیره و داخل آرایه posts قرار میده. حال کافیه این متد رو قبل از اینکه کامپوننت Mount بشه اجرا کنیم »» پس getInitialPosts رو درون ()beforeMount قرار میدیم.

پس کامپوننت Mount میشه و در این حین اطلاعات اولیه (صفحه اول پست‌ها) رو هم از API دریافت کرده.... حال در بخش Template هم با یه v-for بسادگی آرایه رو پیمایش میکنیم و پست هارو نشون میدیم.


پیاده‌سازی لاجیک مربوط به اسکرول بی‌نهایت

تا اینجا همه کارها، کارهای معمولی بوده که با Vue انجام میشه. برای پیاده‌سازی اسکرول بی نهایت باید یه متد دیگه هم بسازیم.. پس متدی به نام infiniteScroll اضافه میکنیم و داخلش با استفاده از رویداد window.onscroll چک میکنیم که آیا به انتهای صفحه رسیدیم یا نه.
اگر به انتهای صفحه رسیده باشیم »»» مقدار currentPage رو یکی افزایش میدیم و با یه درخواست axios دیگه اطلاعات صفحه بعد رو دریافت میکنیم و به انتهای آرایه posts اضافه میکنیم...
و چون VueJs از Two-way data binding پشتیبانی میکنه به محض اضافه شدن پست های جدید‌ (به آرایه posts) ، کامپوننت دوباره رندر میشه و اطلاعات جدید رو هم نشون میده.
تنها کاری که باقی میمونه اینه که بعد از اینکه کامپوننت Mount شد (که پس از هر رندر اتفاق میفته)، متد ()infiniteScroll رو فراخوانی کنیم.. پس این متد رو داخل ()mounted قرار میدیم.


کلیت کار به همین روال انجام میشه و بقیه کارها مربوط به UI میشه که مثلا تا وقتی اطلاعات داره برمی‌گرده یه Loader هم نمایش داده بشه.

قسمت Template کامپوننت:

<template>
  <div id="app">
    <h1>Posts</h1>
    <div v-for="post in posts">
      <div class="postCard">
        <img :src="post.picture.large" />
      </div>
      <div>
        <p>{{ post.title }} {{ post.created_at }}</p>
        <p>{{ post.body }}</p>
      </div>
    </div>
  </div>
</template>

قسمت Script کامپوننت:

<script>
export default {
  data() {
    return {
      posts: [],
      currentPage: 1
    };
  },

  methods: {
    getInitialPosts() {
      axios.get(`https://yourAPI.com/api/posts`).then(response => {
        this.posts = response.data;
      });
    },

    infiniteScroll(post) {
      window.onscroll = () => {
        let bottomOfWindow =
          document.documentElement.scrollTop + window.innerHeight ===
          document.documentElement.offsetHeight;

        if (bottomOfWindow) {
          this.currentPage++;
          axios
            .get(`https://yourAPI.com/api/posts/page/${this.currentPage}`)
            .then(response => {
              this.posts.push(response.data);
            });
        }
      };
    }
  },

  mounted() {
    this.infiniteScroll(this.post);
  },

  beforeMount() {
    this.getInitialPosts();
  }
};
</script>

موفق باشید


سیدعلی موسوی
تخصص : سی شارپ و پی اچ پی
@juza66 5 سال پیش مطرح شد
1

عالی بود مهندس جان @ali.bayat
منم خیلی درگیر پیاده کردن این مسئله بودم متاسفانه نت نبود. دمت گرم


علی بیات
تخصص : توسعه دهنده ارشد وب
@ali.bayat 5 سال پیش مطرح شد
0

@juza66
خواهش میکنم، پیروز باشید


parsa
@parsahaghighi 5 سال پیش مطرح شد
0

@ali.bayat
شرمنده میشه قسمت route هم توضیح بدید چطور انجام بدیم که اگه page رو بهش پاس دادیم یا ندادیم کار درست رو انجام بده

ممنون


علی بیات
تخصص : توسعه دهنده ارشد وب
@ali.bayat 5 سال پیش مطرح شد
2

برای Route های آپشنال باید از علامت سوال استفاده کرد, مثلا:

Route::get('api/posts/{page?}', function ($page = 1) {

});

parsa
@parsahaghighi 5 سال پیش مطرح شد
محمدرضا قمی اویلی
تخصص : لاراول
@ghomi 5 سال پیش آپدیت شد
0

@miladfathi021
من توی push کردن مشکل دارم دیتا من به شکل زیر ذخیره برگشت داده میشه و وقتی میخوام push کنم میگه همه رو توی یک آرایه push میکنه :

7) […]
​
0: Object { id: Getter & Setter, user_id: Getter & Setter, address: Getter & Setter, … }
​
1: Object { id: Getter & Setter, user_id: Getter & Setter, address: Getter & Setter, … }
​
2: Object { id: Getter & Setter, user_id: Getter & Setter, address: Getter & Setter, … }
​
3: Object { id: Getter & Setter, user_id: Getter & Setter, address: Getter & Setter, … }
​
4: Object { id: Getter & Setter, user_id: Getter & Setter, address: Getter & Setter, … }
​
5: Object { id: Getter & Setter, user_id: Getter & Setter, address: Getter & Setter, … }
​
6: Object { id: Getter & Setter, user_id: Getter & Setter, address: Getter & Setter, … }
​

نگاه توی ویو جچوری ذخیره میشن صفحات

orders:Array[9]
0:Object
1:Object
2:Object
3:Object
4:Object
5:Object
6:Object
7:Array[7]
8:Array[5]

هفت یک آرایه ذخیره میگه چطور این مشکل حل کنم


parsa
@parsahaghighi 5 سال پیش مطرح شد
0

@ghomi2018
درود
میتونی با یه for یکی یکی push کنی


محمدرضا قمی اویلی
تخصص : لاراول
@ghomi 5 سال پیش مطرح شد
0

@ali.baya
یک مشکل وجود داره این توی مرورگر کروم کار نمیکنه فقط


سیدعلی موسوی
تخصص : سی شارپ و پی اچ پی
@juza66 5 سال پیش آپدیت شد
0

@ghomi2018
شما از webpack استفاده کن اگر خطایی syntax نداری ، build کن و استفاده کن.

چون webpack کدهای اسکریپتت رو به ES5 (مابه قبل تاریخ) کدهات رو کمپایل میکنه که تویی همه مرورگرها کار میکنه :)


برای ارسال پاسخ لازم است وارد شده یا ثبت‌نام کنید

ورود یا ثبت‌نام