استخدام الفتحات في Vue كمثال لمقتطف المنتج

عند العمل مع المشاريع التي لا يتم فيها استخدام SSR (Server Side Rendering) أو لا يمكن تنفيذها ، تبرز المشكلة في كتابة بعض الوظائف أو المنطق مرتين للعناصر الثابتة التي تطبع الواجهة الخلفية والمكونات التي تقدم Vue.

على سبيل المثال ، نحتاج إلى تنفيذ مكون مقتطف منتج يحتوي على عدد من المتطلبات:

  • يمكن طباعته بشكل ثابت من الخلفية مع جميع المعلومات اللازمة لتحسين محركات البحث والمنطق.
  • يمكن استخدامه كمكون Vue عادي ، وتمرير المعلمات من خلال v-bind ، وإرفاق أحداث النقر ، وما إلى ذلك.
  • يجب أن يعرض الحالة الحالية لزر الشراء
  • بعد النقر على زر "شراء" ، يجب أن يظهر برنامج التحميل المسبق في انتظار حالة السلة

حل واحد:

  1. اكتب منطقًا للمقتطفات الثابتة من خلال إرفاق أحداث النقر وإضافة فئات التحميل وإزالتها على زر الشراء
  2. اكتب بشكل منفصل مكونًا على Vue يقوم بتنفيذ نفس المنطق فقط في تنسيق القالب
  3. استخدم العنصر الأول للإخراج من الواجهة الخلفية ، والثاني ، على سبيل المثال ، لإخراج البيانات النظيفة التي تم الحصول عليها من الحالة أو ajax

وبالتالي سنكتب منطقين ، أحدهما يعمل مباشرة مع DOM ، والآخر مع البيانات الخالصة.

حل هذه المشكلة هو استخدام الفتحات ، أي القدرة على تعيين المحتوى الافتراضي ، الذي سيحتوي على معلمات ديناميكية ، ولكن في نفس الوقت إذا تم استخدام المكون كقالب مضمن ، فسيتم استبدال كل هذه المعلمات بالمعلمات التي رسمتها الواجهة الخلفية.

دعنا نكتب مكونًا يمكنه التعامل مع كل من الإحصائيات والديناميكيات:

قائمة المكونات
<template> <div> <!--   image   ,       --> <slot name="image"> <!--    --> <a :href="url" class="snippet__image"> <img :src="image"> </a> </slot> <slot name="title"> <a :href="url" class="snippet__title">{{ title }}</a> </slot> <div v-if="!inCart" @click="add" :class="{ 'snippet__buy--load': load }" class="snippet__control" > <slot name="button"> <div class="snippet__button"></div> </slot> </div> <div v-if="inCart" class="snippet__control"> <div class="snippet__button"></div> </div> <div v-if="load" class="snippet__load"></div> </div> </template> <script> //  vuex     import { mapState, mapActions } from 'vuex' export default { props: { id: { type: Number, required: true }, url: { type: String }, image: { type: String }, title: { type: String } }, data() { return { //   load: false, //     inCart: false, } }, computed: { ...mapState({ //     cartItems: ({cart}) => cart.items }), }, mounted() { this.$nextTick(() => { //      this.inCart = this.cartItems.some(item => item.id === this.id) }) }, methods: { ...mapActions([ //     'addToCart' ]), add() { //    this.load = true //   this.addToCart({ id: this.id }) } }, watch: { //      cartItems(items) { //    this.load = false //      this.inCart = items.some(item => item.id === this.id) } } } </script> 


باستخدام مكون عبر الواجهة الخلفية:

 <snippet :id="1" class="snippet"> <a slot="image" href="#" class="snippet__image"> <img src="photo.jpg"> </a> <a slot="title" href="#" class="snippet__title"> 1</a> <div slot="button" class="snippet__button"></div> </snippet> 

باستخدام مكون في مكونات أخرى:

 <catalog-list> <snippet v-for="item in items" :key="item.id" v-bind="item"></snippet> </catalog-list> 

الآن لدينا مكون واحد يمكن استخدامه في حالات مختلفة.

أود أن أسمع رأيك حول هذا النهج ، ربما هناك حل أفضل.

Source: https://habr.com/ru/post/ar422465/


All Articles