مع بلوجر متجر إلكتروني ولا أسهل

أنشئ متجرك الإلكتروني مع بلوجر بسيط يساعدك في البيع أكثر . قم بإدارته من أي مكان وبأي وقت كل هذا مجانا

‏إظهار الرسائل ذات التسميات vuejs. إظهار كافة الرسائل
‏إظهار الرسائل ذات التسميات vuejs. إظهار كافة الرسائل

الأحد، 24 أكتوبر 2021

ما هو Vue.js ؟

ما هو Vue.js؟
Vue هو إطار تقدمي لبناء واجهات المستخدم. على عكس الأطر المتجانسة الأخرى ، تم تصميم Vue من الألف إلى الياء ليكون قابلاً للتطبيق بشكل تدريجي. تركز المكتبة الأساسية على طبقة العرض فقط ، ومن السهل التقاطها والتكامل مع المكتبات الأخرى أو المشاريع الحالية. من ناحية أخرى ، فإن Vue قادر تمامًا أيضًا على تشغيل تطبيقات الصفحة الواحدة المعقدة عند استخدامها مع الأدوات الحديثة والمكتبات الداعمة مثال حي اضغط هنا 
إذا كنت ترغب في معرفة المزيد عن Vue قبل التعمق في الموضوع ، فقد أنشأنا مقطع فيديو يسير عبر المبادئ الأساسية ونموذج مشروع.
#ابدء
تلميح
قبل البدأ من المفروض ان لديك  معرفة متوسطة على الاقل  بـ HTML و CSS و JavaScript. إذا كنت جديدًا تمامًا على تطوير الواجهة الأمامية ،فانصحك بتعلم الاساسيات للغات المذكورة   فقد لا تكون أفضل فكرة القفز مباشرة إلى إطار العمل  كخطوة أولى - فهم الأساسيات ثم العودة! الخبرة  مع أطر العمل الأخرى تساعد ، ولكنها ليست مطلوبة.
أسهل طريقة لتجربة Vue.js هي استخدام مثال Hello World المشهور لاي لغة جديدة  لا تتردد جربه الان مثال حي اظغط هنا 
تنصيب vue.js
  <script src="https://unpkg.com/vue@next"></script>  
ملاحظة: لا نوصي بأن يبدأ المبتدئين بـ vue-cli ، خاصة إذا لم تكن على دراية بأدوات البناء المستندة إلى Node.js. سنشرح  Node.js.  في دورة منفصلة 
#التقديم التصريحي
يوجد في Vue.js نظام يمكّننا من عرض البيانات بشكل تصريحي إلى DOM باستخدام بناء جملة قالب مباشر:
<div id="counter">
  Counter: {{ counter }}
</div>
<script>
const Counter = {
  data() {
    return {
      counter: 0
    }
  }
} 
Vue.createApp(Counter).mount('#counter')
</script>

لقد أنشأنا بالفعل أول تطبيق Vue!، وهذا لان Vue قامت بالكثير من العمل خلف الستارلتسهيل الامر للمستخدمين . البيانات و DOM مرتبطتان الآن ، وكل شيء أصبح الآن تفاعليًا. تريد معرفة ذالك ؟ ألق نظرة على المثال أدناه حيث تزداد خاصية العداد كل ثانية وسترى كيف يتغير عرض DOM:


<div id="counter">
  Counter: {{ counter }}
</div>
<script>
const Counter = {
  data() {
    return {
      counter: 0
    },mounted() {
    setInterval(() => {
      this.counter++
    }, 1000)
   }
  }
}

Vue.createApp(Counter).mount('#counter')
</script> 

بالإضافة إلى الاستيفاء النصي ، يمكننا أيضًا ربط سمات العناصر(bind element attributes) مثل هذا:


<div id="bind-attribute">
  <span v-bind:title="message">
    Hover your mouse over me for a few seconds to see my dynamically bound
    title!
  </span>
</div>
<script>
const AttributeBinding = {
  data() {
    return {
      message: 'You loaded this page on ' + new Date().toLocaleString()
    }
  }
}

Vue.createApp(AttributeBinding).mount('#bind-attribute')
</script>

هنا نلاحظ عنصر جديدًا. يسمى v-bind هو عبارة عن (Attribut). تكون التوجيهات مسبوقة بـ v-للإشارة إلى أنها سمات (Attribut) خاصة مقدمة من Vue ، وكما تلاحظ ، فإنها تجعل العنصر تفاعليًا خاصًتا على DOM المعروض. هنا نقول لل (v-bind) "احتفظ بسمة(Attribut) عنوان(title) هذا العنصر(element's) محدثة بخاصية(property) message في المثال النشط الحالي".

#معالجة مدخلات المستخدم(input)
للسماح للمستخدمين بالتفاعل مع تطبيقك ، يمكننا استخدام التوجيه v-on لإرفاق الأحداث (event) لاستدعاء الدوال (function) في المثال التالي:

<div id="event-handling">
  <p>{{ message }}</p>
  <button v-on:click="reverseMessage">Reverse Message</button>
</div>
<script>
const EventHandling = {
  data() {
    return {
      message: 'Hello Vue.js!'
    }
  },
  methods: {
    reverseMessage() {
      this.message = this.message
        .split('')
        .reverse()
        .join('')
    }
  }
} 
Vue.createApp(EventHandling).mount('#event-handling') 
</script>

يوفر Vue أيضًا التوجيه v-model الذي يجعل الربط ثنائي الاتجاه أي عند إدخال قيمة في النموذج (input) يتم تحديث قيمة المتغير مباشرة:


 <div id="two-way-binding">
  <p>{{ message }}</p>
  <input v-model="message" />
</div>
<script>
const TwoWayBinding = {
  data() {
    return {
      message: 'Hello Vue!'
    }
  }
}

Vue.createApp(TwoWayBinding).mount('#two-way-binding')
</script>


#الشرطية والحلقات(Conditionals and Loops)
 من السهل أيضًا تبديل وجود العنصر مثال تحقق الشرط اذا كان المتغيير منطقي (true) اظهر محتوى(div)  اما اذا كان المتغيير غير منطقي 
(false) لاتظهر محتوى ابلوك (div):

 <div id="conditional-rendering">
  <span v-if="seen">Now you see me</span>
</div>
<script>
const ConditionalRendering = {
  data() {
    return {
      seen: true
    }
  }
}
Vue.createApp(ConditionalRendering).mount('#conditional-rendering')
</script>

مثال على عمل التكرار (loop)

<div id="list-rendering">
  <ol>
    <li v-for="todo in todos">
      {{ todo.text }}
    </li>
  </ol>
</div>
<script>
const ListRendering = {
  data() {
    return {
      todos: [
        { text: 'Learn JavaScript' },
        { text: 'Learn Vue' },
        { text: 'Build something awesome' }
      ]
    }
  }
}
Vue.createApp(ListRendering).mount('#list-rendering')
</script>


#المكونات (Components)
 يعد نظام المكونات (Components) مفهومًا مهمًا آخر في Vue ، لأنه  يسمح لنا ببناء تطبيقات واسعة النطاق تتكون من مكونات صغيرة قائمة بذاتها وقابلة لإعادة الاستخدام في كثير من الأحيان. إذا فكرنا في الأمر ، يمكن تلخيص أي نوع من واجهة التطبيق تقريبًا في شجرة من المكونات مثلا النافبار عبارة عن مكون والهيدر مكون والمحتوى مكون  والفوتر مكون وووو....الخ:مثال

في Vue ، يعد المكون (Components) أساسًا مثيلًا بخيارات محددة مسبقًا. يعد تسجيل مكون في Vue أمرًا سهلاً: نقوم بإنشاء كائن (Object) مكون كما فعلنا مع كائنات التطبيق ونقوم بتعريفه في خيار مكونات الأصل:

<script>
 // Create Vue application
const app = Vue.createApp(...)

// Define a new component called todo-item
app.component('todo-item', {
  template: `<li>This is a todo</li>`
})

// Mount Vue application
app.mount(...)
</script>


الآن يمكنك تكوينه في قالب مكون آخر:

<ol>
  <!-- Create an instance of the todo-item component -->
  <todo-item></todo-item>
</ol>


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

 <script> 
app.component('todo-item', {
  props: ['todo'],
  template: `<li>{{ todo.text }}</li>`
})
</script>


يمكننا الآن تمرير todo إلى كل مكون متكرر باستخدام v-bind:
 
<div id="todo-list-app">
  <ol>
    <!--
  نوفر الآن كل عنصر todo مع كائن todo
       إنه يمثلها ، بحيث يمكن أن يكون محتواها ديناميكيًا.
       نحتاج أيضًا إلى تزويد كل مكون بـ "مفتاح" ،
       والتي سيتم شرحها لاحقًا.
    -->
    <todo-item
      v-for="item in groceryList"
      v-bind:todo="item"
      v-bind:key="item.id"
    ></todo-item>
  </ol>
</div>
<script> 
 const TodoList = {
  data() {
    return {
      groceryList: [
        { id: 0, text: 'Vegetables' },
        { id: 1, text: 'Cheese' },
        { id: 2, text: 'Whatever else humans are supposed to eat' }
      ]
    }
  }
}

const app = Vue.createApp(TodoList)

app.component('todo-item', {
  props: ['todo'],
  template: `<li>{{ todo.text }}</li>`
})

app.mount('#todo-list-app')

</script>


هذا مثال مفتعل ، لكننا نجحنا في فصل تطبيقنا إلى وحدتين أصغر ، والطفل منفصل بشكل معقول عن الوالدين عبر واجهة الدعائم. يمكننا الآن تحسين مكون <todo-item> الخاص بنا من خلال نموذج ومنطق أكثر تعقيدًا دون التأثير على التطبيق الأصلي. في تطبيق كبير ، من الضروري تقسيم التطبيق بأكمله إلى مكونات لجعل التطوير قابلاً للإدارة. سنتحدث كثيرًا عن المكونات لاحقًا في الدليل ، ولكن إليك مثال (وهمي) لما قد يبدو عليه قالب التطبيق مع المكونات:

  <div id="app">
  <app-nav></app-nav>
  <app-view>
    <app-sidebar></app-sidebar>
    <app-content></app-content>
  </app-view>
</div>


في الدرس القادم نلتقي ان شاء الله


الثلاثاء، 12 أكتوبر 2021

vue3 الدرس الاول طباعة متغيرات جافاسكريبت داخل html

مقدمة


1- اولا نقوم  بانشاء الصفحة الرئيسية  index.html في اي مكان تريد في سطح المكتب مثلا ونكتب الكود التالي


 <html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title> 
    <script src="https://unpkg.com/vue@next"></script>
    </head>
    <body>
    <div id="app">
        {{ counter }} 
    </div> 
    <script> 
       const Counter = {
         data() {
           return {
             counter:0 
           }
         }
       }  
       Vue.createApp(Counter).mount('#app')
    </script> 
    </body>
    </html>

النتيجة

0


السبت، 9 أكتوبر 2021

تكبير الصور للمنتجات عند مرور الفأرة الماوس على الصورة بلغة vue js 3

 السلام عليكم ورحمة الله وبركاته 

في هذا الدرس سنتعلم تكبير الصور للمنتجات عند مرور الفأرة الماوس على الصورة بلغة vue js 3  سوف استخدم vue cli  

اولا افتح cmd و قم بانشاء مشروع جديد باضافة الامر التالي 


  vue create zoomimage
  
  


المكتبة المستعملة في التصميم css هي


"dependencies": { 
    "bulma": "^0.9.3",   
  }
  }

template انشأ كومبوننت جديد والصق الكود التالي


<template>
  <div class="container">
    <section class="section">
      <div class="columns">
        <div class="column is-1">
          <div class="img-zoom-item">
            <img
              v-for="(im, index) in img"
              :key="index"
              @click="shangimg(im.imgs)"
              id="momo"
              :src="im.imgs"
              alt="Girl"
            />
          </div>
        </div>

        <div class="column is-5">
          <div class="img-zoom-container " @mouseout="clearopacityz">
            <img
              id="momo"
              ref="imgtopz"
              @load="imageZoomz"
              :src="image"
              alt="Girl"
              @mousemove="moveLensz"
              @touchmove="moveLensz"
            />
          </div>

          <div class="img-magnifier-container ">
            <img
              id="myimage"
              :src="image"
              ref="imgmobaile"
              @load="magnify"
              @mousemove="moveMagnifier"
              @touchmove="moveMagnifier"
            />
          </div>
        </div>

        <div class="column is-5">
          <div class="img-zoom-result" ref="resulz"></div>

          <div class="product__details__text">
            <div class="content">
              <h1>product d_etails rating</h1>
              <div class="block product__details__rating">
                <span class=" has-text-warning">
                  <fa icon="star"></fa>
                </span>
                <span class=" has-text-warning">
                  <fa icon="star"></fa>
                </span>
                <span class=" has-text-warning">
                  <fa icon="star"></fa>
                </span>
                <span class=" has-text-warning">
                  <fa icon="star"></fa>
                </span>
                <span class=" has-text-warning">
                  <fa :icon="['fas', 'star-half']"></fa>
                </span>
                <span> (18 reviews)</span>
              </div>
              <h3>$50.00</h3>

              <div class="block flex-2-item">
                <div class="item-12-flex">
                  <div class="nav">
                    <div>
                      <input type="number" class="input" value="1" min="1" />
                    </div>
                    <div>
                      <a href="#" class="primary-btn">ADD TO CARD</a>
                      <a href="#" class="heart-icon">
                        <fa :icon="['fas', 'heart']"></fa>
                      </a>
                    </div>
                  </div>
                </div>
              </div>
              <div class="block flex-2-item">
                <div class="item-1-flex">
                  <b>Availability</b>
                </div>
                <div class="item-2-flex">
                  <span>In Stock</span>
                </div>
              </div>
              <div class="block flex-2-item">
                <div class="item-1-flex">
                  <b>Shipping</b>
                </div>
                <div class="item-2-flex">
                  <span>01 day shipping. <samp>Free pickup today</samp></span>
                </div>
              </div>
              <div class="block flex-2-item">
                <div class="item-1-flex">
                  <b>Weight</b>
                </div>
                <div class="item-2-flex">
                  <span>0.5 kg</span>
                </div>
              </div>
              <div class="block flex-2-item">
                <div class="item-1-flex">
                  <b>Share on</b>
                </div>
                <div class="item-2-flex">
                  <span class="icon is-large fa-2x  has-text-info">
                    <fa :icon="['fab', 'twitter']"></fa>
                  </span>
                  <span class="icon is-large fa-2x  has-text-link">
                    <fa :icon="['fab', 'facebook']"></fa>
                  </span>
                  <span class="icon is-large fa-2x  has-text-warning">
                    <fa :icon="['fab', 'instagram']"></fa>
                  </span>
                  <span class="icon is-large    fa-2x  has-text-danger">
                    <fa :icon="['fab', 'pinterest']"></fa>
                  </span>
                </div>
              </div>

              <p>
                Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a.
                Vestibulum ac diam sit amet quam vehicula elementum sed sit amet
                dui. Sed porttitor lectus nibh. Vestibulum ac diam sit amet quam
                vehicula elementum sed sit amet dui. Proin eget tortor risus.
              </p>
            </div>
          </div>
        </div>

        <div class="column is-1"></div>
      </div>
    </section>
  </div>
</template>

وفي عنصر جافاسكريبت الصق الاكود التالي js


<script>
  import { computed, ref, onMounted } from "vue";
export default {
  setup() {
    const img = ref([
      { imgs: require("../assets/blog/blog-1.jpg") },
      { imgs: require("../assets/blog/blog-2.jpg") },
      { imgs: require("../assets/blog/blog-3.jpg") },
      { imgs: require("../assets/blog/blog-4.jpg") },
      { imgs: require("../assets/blog/blog-5.jpg") },
    ]);
    const image = ref(img.value[0].imgs);
    const resultez = ref("");
    const lensz = ref("");
    const imgz = ref("");
    const resultz = ref("");
    const cxz = ref("");
    const cyz = ref("");
    const imgtopz = ref(null);
    const resulz = ref(null);
    const zoom = ref(2);

    const imgmobaile = ref(null);
    const imgmob = ref("");
    const glass = ref("");
    const h = ref("");
    const w = ref("");
    const bw = ref("");
    const wit = ref(screen.width);
    const witW = computed(() => {
      console.log(wit.value);
      return wit.value;
    });

    const shangimg = (index) => {
      if (image.value !== index) {
        image.value = index;
      } else return;
    };

    onMounted(() => {
      witW.value;
    });
    const imageZoomz = () => {
      if (witW.value >= 676) {
        var myobj = document.querySelectorAll(".img-zoom-lens");
        if (myobj.length > 0) {
          myobj[0].remove();
        }

        imgz.value = imgtopz.value;
        resultz.value = resulz.value;
        /*create lens:*/
        lensz.value = document.createElement("DIV");
        lensz.value.setAttribute("class", "img-zoom-lens");
        /*insert lens:*/
        imgz.value.parentElement.insertBefore(lensz.value, imgz.value);
        /*calculate the ratio between result DIV and lens:*/
        cxz.value = resultz.value.offsetWidth / lensz.value.offsetWidth;
        cyz.value = resultz.value.offsetHeight / lensz.value.offsetHeight;
        /*set background properties for the result DIV:*/
        resultz.value.style.backgroundImage = "url('" + imgz.value.src + "')";
        resultz.value.style.backgroundSize =
          imgz.value.width * cxz.value +
          "px " +
          imgz.value.height * cyz.value +
          "px";

        lensz.value.addEventListener("mousemove", moveLensz, { passive: true });

        lensz.value.addEventListener("touchmove", moveLensz, { passive: true });
      } else return false;
      //
    };
    const moveLensz = (e) => {
      if (witW.value >= 676) {
        var pos, x, y;

        pos = getCursorPosz(e);
        /*calculate the position of the lens:*/
        x = pos.x - lensz.value.offsetWidth / 2;
        y = pos.y - lensz.value.offsetHeight / 2;
        /*prevent the lens from being positioned outside the image:*/
        if (x > imgz.value.width - lensz.value.offsetWidth) {
          x = imgz.value.width - lensz.value.offsetWidth;
        }
        if (x < 0) {
          x = 0;
        }
        if (y > imgz.value.height - lensz.value.offsetHeight) {
          y = imgz.value.height - lensz.value.offsetHeight;
        }
        if (y < 0) {
          y = 0;
        }
        /*set the position of the lens:*/
        lensz.value.style.left = x + "px";
        lensz.value.style.top = y + "px";
        /*display what the lens "sees":*/
        resultz.value.style.opacity = 1;
        resultz.value.style.position = "relative";
        resultz.value.style.backgroundPosition =
          "-" + x * cxz.value + "px -" + y * cyz.value + "px";
      } else return;
    };
    const clearopacityz = () => {
      if (witW.value >= 676) {
        resultz.value.style.opacity = 0;
        resultz.value.style.position = "absolute";
      } else return;
    };
    const getCursorPosz = (e) => {
      var a,
        x = 0,
        y = 0;
      e = e || window.event;
      /*get the x and y positions of the image:*/
      a = imgz.value.getBoundingClientRect();
      /*calculate the cursor's x and y coordinates, relative to the image:*/
      x = e.pageX - a.left;
      y = e.pageY - a.top;
      /*consider any page scrolling:*/
      x = x - window.pageXOffset;
      y = y - window.pageYOffset;
      return { x: x, y: y };
    };

    //-imageZoom--------imageZoom---------imageZoom--//

    const magnify = () => {
      var magnifier = document.querySelectorAll(".img-magnifier-glass");
      if (magnifier.length > 0) {
        magnifier[0].remove();
      }

      imgmob.value = imgmobaile.value;
      /*create magnifier glass:*/
      glass.value = document.createElement("DIV");
      glass.value.setAttribute("class", "img-magnifier-glass");
      /*insert magnifier glass.value:*/
      imgmob.value.parentElement.insertBefore(glass.value, imgmob.value);
      //console.log(glass.value);console.log( imgmob.value);
      /*set background properties for the magnifier glass.value:*/
      glass.value.style.backgroundImage = "url('" + imgmob.value.src + "')";
      glass.value.style.backgroundRepeat = "no-repeat";
      glass.value.style.backgroundSize =
        imgmob.value.width * zoom.value +
        "px " +
        imgmob.value.height * zoom.value +
        "px";
      bw.value = 3;
      w.value = glass.value.offsetWidth / 2;
      h.value = glass.value.offsetHeight / 2;
      /*execute a function when someone moves the magnifier glass.value over the image:*/
      glass.value.addEventListener("mousemove", moveMagnifier, {
        passive: true,
      });

      /*and also for touch screens:*/
      glass.value.addEventListener("touchmove", moveMagnifier, {
        passive: true,
      });
    };
    const moveMagnifier = (e) => {
      var pos, x, y;
      /*prevent any other actions that may occur when moving over the image*/
      //e.preventDefault();
      /*get the cursor's x and y positions:*/
      pos = getCursorPoss(e);
      x = pos.x;
      y = pos.y;
      /*prevent the magnifier glass.value from being positioned outside the image:*/
      if (x > imgmob.value.width - w.value / zoom.value) {
        x = imgmob.value.width - w.value / zoom.value;
      }
      if (x < w.value / zoom.value) {
        x = w.value / zoom.value;
      }
      if (y > imgmob.value.height - h.value / zoom.value) {
        y = imgmob.value.height - h.value / zoom.value;
      }
      if (y < h.value / zoom.value) {
        y = h.value / zoom.value;
      }
      /*set the position of the magnifier glass.value:*/
      glass.value.style.left = x - w.value + "px";
      glass.value.style.top = y - h.value + "px";
      /*display what the magnifier glass.value "sees":*/
      glass.value.style.backgroundPosition =
        "-" +
        (x * zoom.value - w.value + bw.value) +
        "px -" +
        (y * zoom.value - h.value + bw.value) +
        "px";
    };
    const getCursorPoss = (e) => {
      var a,
        x = 0,
        y = 0;
      e = e || window.event;
      /*get the x and y positions of the image:*/
      a = imgmob.value.getBoundingClientRect();
      /*calculate the cursor's x and y coordinates, relative to the image:*/
      x = e.pageX - a.left;
      y = e.pageY - a.top;
      /*consider any page scrolling:*/
      x = x - window.pageXOffset;
      y = y - window.pageYOffset;
      return { x: x, y: y };
    };

    //-imageZoom--------imageZoom---------imageZoom--//

    return {
      resultez,
      lensz,
      imgz,
      resultz,
      cxz,
      cyz,
      imgtopz,
      resulz,
      imageZoomz,
      img,
      moveLensz,
      clearopacityz,
      getCursorPosz,
      image,
      shangimg,
      zoom,
      imgmob,
      glass,
      h,
      w,
      bw,
      magnify,
      moveMagnifier,
      getCursorPoss,
      imgmobaile,
      witW,
      wit,
    };
  },
}; </script>
  
  

والصق الكود التالي في style


<style>
.flex-2-item {
  display: flex;
  justify-content: flex-start;
  align-items: center;
}
.item-1-flex {
  flex: 40%;
}
.item-2-flex {
  flex: 60%;
}

.item-12-flex {
  flex: 100%;
}

.product__details__text {
  z-index: 100;
}
.img-zoom-item {
  position: relative;
  overflow: hidden;
}
.img-zoom-item img {
  height: 50px;
  width: 50px;
  display: block;
  border-radius: 50%;
  cursor: pointer;
}

.column {
  position: relative !important ;
}
.img-zoom-container {
  position: relative;
  width: 100%;
  height: auto;
  min-height: 300px;
  display: block;
}
.img-zoom-container img {
  width: 100%;
  height: auto;
}

.img-zoom-lens {
  display: block;
  position: absolute;
  border: 1px solid #d4d4d4;
  /*set the size of the lens:*/
  width: 200px;
  height: 200px;
}
.img-zoom-lens-remove {
  border: 0px;
}

.img-zoom-result {
  position: absolute;
  border: 1px solid #d4d4d4;
  /*set the size of the result div:*/
  width: 100%;
  height: 100%;
  max-block-size: 400px;
  opacity: 0;
  transition: 0.8s ease;
  /*clear: both;*/
  background-repeat: no-repeat;
}

#descreption {
  position: relative;
  z-index: 1000;
}
.img-zoom-container img:hover .img-zoom-result {
  opacity: 1 !important;
}
/*zome mobaile*/

.img-magnifier-container {
  display: none;
  position: relative;
  width: 100%;

  height: 100%;
}
.img-magnifier-container img {
  width: 100%;
  height: 100%;
}

.img-magnifier-glass {
  position: absolute;
  border: 4px solid #e3e3e3;
  border-radius: 5px;
  cursor: none;
  /*Set the size of the magnifier glass:*/
  display: block;
  width: 200px !important;
  height: 200px !important;
}
.row-img img {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 2px solid #cecece;
  cursor: pointer;
}
.row-img {
  margin-inline-start: 3px;
}
.row {
  position: relative;
}

.active {
  padding: 1em;
  border: 1px solid rgb(9, 160, 67);
}

@media screen and (max-width: 769px) {
  .row {
    display: flex;
  }

  .img-zoom-item img {
    height: 25px;
    width: 25px;
    display: inline-block;
    margin-inline-end: 15px;
  }
  .img-magnifier-container {
    display: block;
  }

  .img-zoom-container {
    display: none;
  }
  .flex-2-item {
    flex-direction: column;
    align-items: flex-start;
  }
  .img-magnifier-glass {
    width: 280px !important;
    height: 280px !important;
  }
}

/*-------- */
@media only screen and (min-width: 467px) and (max-width: 769px) {
  .img-magnifier-glass {
    width: 200px !important;
    height: 200px !important;
  }
}
@media only screen and (max-width: 467px) {
  .img-magnifier-glass {
    width: 150px !important;
    height: 150px !important;
  }
}</style>

الكود كامل


<template>
  <div class="container">
    <section class="section">
      <div class="columns">
        <div class="column is-1">
          <div class="img-zoom-item">
            <img
              v-for="(im, index) in img"
              :key="index"
              @click="shangimg(im.imgs)"
              id="momo"
              :src="im.imgs"
              alt="Girl"
            />
          </div>
        </div>

        <div class="column is-5">
          <div class="img-zoom-container " @mouseout="clearopacityz">
            <img
              id="momo"
              ref="imgtopz"
              @load="imageZoomz"
              :src="image"
              alt="Girl"
              @mousemove="moveLensz"
              @touchmove="moveLensz"
            />
          </div>

          <div class="img-magnifier-container ">
            <img
              id="myimage"
              :src="image"
              ref="imgmobaile"
              @load="magnify"
              @mousemove="moveMagnifier"
              @touchmove="moveMagnifier"
            />
          </div>
        </div>

        <div class="column is-5">
          <div class="img-zoom-result" ref="resulz"></div>

          <div class="product__details__text">
            <div class="content">
              <h1>product d_etails rating</h1>
              <div class="block product__details__rating">
                <span class=" has-text-warning">
                  <fa icon="star"></fa>
                </span>
                <span class=" has-text-warning">
                  <fa icon="star"></fa>
                </span>
                <span class=" has-text-warning">
                  <fa icon="star"></fa>
                </span>
                <span class=" has-text-warning">
                  <fa icon="star"></fa>
                </span>
                <span class=" has-text-warning">
                  <fa :icon="['fas', 'star-half']"></fa>
                </span>
                <span> (18 reviews)</span>
              </div>
              <h3>$50.00</h3>

              <div class="block flex-2-item">
                <div class="item-12-flex">
                  <div class="nav">
                    <div>
                      <input type="number" class="input" value="1" min="1" />
                    </div>
                    <div>
                      <a href="#" class="primary-btn">ADD TO CARD</a>
                      <a href="#" class="heart-icon">
                        <fa :icon="['fas', 'heart']"></fa>
                      </a>
                    </div>
                  </div>
                </div>
              </div>
              <div class="block flex-2-item">
                <div class="item-1-flex">
                  <b>Availability</b>
                </div>
                <div class="item-2-flex">
                  <span>In Stock</span>
                </div>
              </div>
              <div class="block flex-2-item">
                <div class="item-1-flex">
                  <b>Shipping</b>
                </div>
                <div class="item-2-flex">
                  <span>01 day shipping. <samp>Free pickup today</samp></span>
                </div>
              </div>
              <div class="block flex-2-item">
                <div class="item-1-flex">
                  <b>Weight</b>
                </div>
                <div class="item-2-flex">
                  <span>0.5 kg</span>
                </div>
              </div>
              <div class="block flex-2-item">
                <div class="item-1-flex">
                  <b>Share on</b>
                </div>
                <div class="item-2-flex">
                  <span class="icon is-large fa-2x  has-text-info">
                    <fa :icon="['fab', 'twitter']"></fa>
                  </span>
                  <span class="icon is-large fa-2x  has-text-link">
                    <fa :icon="['fab', 'facebook']"></fa>
                  </span>
                  <span class="icon is-large fa-2x  has-text-warning">
                    <fa :icon="['fab', 'instagram']"></fa>
                  </span>
                  <span class="icon is-large    fa-2x  has-text-danger">
                    <fa :icon="['fab', 'pinterest']"></fa>
                  </span>
                </div>
              </div>

              <p>
                Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a.
                Vestibulum ac diam sit amet quam vehicula elementum sed sit amet
                dui. Sed porttitor lectus nibh. Vestibulum ac diam sit amet quam
                vehicula elementum sed sit amet dui. Proin eget tortor risus.
              </p>
            </div>
          </div>
        </div>

        <div class="column is-1"></div>
      </div>
    </section>
  </div>
</template>
<script>
import { computed, ref, onMounted } from "vue";
export default {
  setup() {
    const img = ref([
      { imgs: require("../assets/blog/blog-1.jpg") },
      { imgs: require("../assets/blog/blog-2.jpg") },
      { imgs: require("../assets/blog/blog-3.jpg") },
      { imgs: require("../assets/blog/blog-4.jpg") },
      { imgs: require("../assets/blog/blog-5.jpg") },
    ]);
    const image = ref(img.value[0].imgs);
    const resultez = ref("");
    const lensz = ref("");
    const imgz = ref("");
    const resultz = ref("");
    const cxz = ref("");
    const cyz = ref("");
    const imgtopz = ref(null);
    const resulz = ref(null);
    const zoom = ref(2);

    const imgmobaile = ref(null);
    const imgmob = ref("");
    const glass = ref("");
    const h = ref("");
    const w = ref("");
    const bw = ref("");
    const wit = ref(screen.width);
    const witW = computed(() => {
      console.log(wit.value);
      return wit.value;
    });

    const shangimg = (index) => {
      if (image.value !== index) {
        image.value = index;
      } else return;
    };

    onMounted(() => {
      witW.value;
    });
    const imageZoomz = () => {
      if (witW.value >= 676) {
        var myobj = document.querySelectorAll(".img-zoom-lens");
        if (myobj.length > 0) {
          myobj[0].remove();
        }

        imgz.value = imgtopz.value;
        resultz.value = resulz.value;
        /*create lens:*/
        lensz.value = document.createElement("DIV");
        lensz.value.setAttribute("class", "img-zoom-lens");
        /*insert lens:*/
        imgz.value.parentElement.insertBefore(lensz.value, imgz.value);
        /*calculate the ratio between result DIV and lens:*/
        cxz.value = resultz.value.offsetWidth / lensz.value.offsetWidth;
        cyz.value = resultz.value.offsetHeight / lensz.value.offsetHeight;
        /*set background properties for the result DIV:*/
        resultz.value.style.backgroundImage = "url('" + imgz.value.src + "')";
        resultz.value.style.backgroundSize =
          imgz.value.width * cxz.value +
          "px " +
          imgz.value.height * cyz.value +
          "px";

        lensz.value.addEventListener("mousemove", moveLensz, { passive: true });

        lensz.value.addEventListener("touchmove", moveLensz, { passive: true });
      } else return false;
      //
    };
    const moveLensz = (e) => {
      if (witW.value >= 676) {
        var pos, x, y;

        pos = getCursorPosz(e);
        /*calculate the position of the lens:*/
        x = pos.x - lensz.value.offsetWidth / 2;
        y = pos.y - lensz.value.offsetHeight / 2;
        /*prevent the lens from being positioned outside the image:*/
        if (x > imgz.value.width - lensz.value.offsetWidth) {
          x = imgz.value.width - lensz.value.offsetWidth;
        }
        if (x < 0) {
          x = 0;
        }
        if (y > imgz.value.height - lensz.value.offsetHeight) {
          y = imgz.value.height - lensz.value.offsetHeight;
        }
        if (y < 0) {
          y = 0;
        }
        /*set the position of the lens:*/
        lensz.value.style.left = x + "px";
        lensz.value.style.top = y + "px";
        /*display what the lens "sees":*/
        resultz.value.style.opacity = 1;
        resultz.value.style.position = "relative";
        resultz.value.style.backgroundPosition =
          "-" + x * cxz.value + "px -" + y * cyz.value + "px";
      } else return;
    };
    const clearopacityz = () => {
      if (witW.value >= 676) {
        resultz.value.style.opacity = 0;
        resultz.value.style.position = "absolute";
      } else return;
    };
    const getCursorPosz = (e) => {
      var a,
        x = 0,
        y = 0;
      e = e || window.event;
      /*get the x and y positions of the image:*/
      a = imgz.value.getBoundingClientRect();
      /*calculate the cursor's x and y coordinates, relative to the image:*/
      x = e.pageX - a.left;
      y = e.pageY - a.top;
      /*consider any page scrolling:*/
      x = x - window.pageXOffset;
      y = y - window.pageYOffset;
      return { x: x, y: y };
    };

    //-imageZoom--------imageZoom---------imageZoom--//

    const magnify = () => {
      var magnifier = document.querySelectorAll(".img-magnifier-glass");
      if (magnifier.length > 0) {
        magnifier[0].remove();
      }

      imgmob.value = imgmobaile.value;
      /*create magnifier glass:*/
      glass.value = document.createElement("DIV");
      glass.value.setAttribute("class", "img-magnifier-glass");
      /*insert magnifier glass.value:*/
      imgmob.value.parentElement.insertBefore(glass.value, imgmob.value);
      //console.log(glass.value);console.log( imgmob.value);
      /*set background properties for the magnifier glass.value:*/
      glass.value.style.backgroundImage = "url('" + imgmob.value.src + "')";
      glass.value.style.backgroundRepeat = "no-repeat";
      glass.value.style.backgroundSize =
        imgmob.value.width * zoom.value +
        "px " +
        imgmob.value.height * zoom.value +
        "px";
      bw.value = 3;
      w.value = glass.value.offsetWidth / 2;
      h.value = glass.value.offsetHeight / 2;
      /*execute a function when someone moves the magnifier glass.value over the image:*/
      glass.value.addEventListener("mousemove", moveMagnifier, {
        passive: true,
      });

      /*and also for touch screens:*/
      glass.value.addEventListener("touchmove", moveMagnifier, {
        passive: true,
      });
    };
    const moveMagnifier = (e) => {
      var pos, x, y;
      /*prevent any other actions that may occur when moving over the image*/
      //e.preventDefault();
      /*get the cursor's x and y positions:*/
      pos = getCursorPoss(e);
      x = pos.x;
      y = pos.y;
      /*prevent the magnifier glass.value from being positioned outside the image:*/
      if (x > imgmob.value.width - w.value / zoom.value) {
        x = imgmob.value.width - w.value / zoom.value;
      }
      if (x < w.value / zoom.value) {
        x = w.value / zoom.value;
      }
      if (y > imgmob.value.height - h.value / zoom.value) {
        y = imgmob.value.height - h.value / zoom.value;
      }
      if (y < h.value / zoom.value) {
        y = h.value / zoom.value;
      }
      /*set the position of the magnifier glass.value:*/
      glass.value.style.left = x - w.value + "px";
      glass.value.style.top = y - h.value + "px";
      /*display what the magnifier glass.value "sees":*/
      glass.value.style.backgroundPosition =
        "-" +
        (x * zoom.value - w.value + bw.value) +
        "px -" +
        (y * zoom.value - h.value + bw.value) +
        "px";
    };
    const getCursorPoss = (e) => {
      var a,
        x = 0,
        y = 0;
      e = e || window.event;
      /*get the x and y positions of the image:*/
      a = imgmob.value.getBoundingClientRect();
      /*calculate the cursor's x and y coordinates, relative to the image:*/
      x = e.pageX - a.left;
      y = e.pageY - a.top;
      /*consider any page scrolling:*/
      x = x - window.pageXOffset;
      y = y - window.pageYOffset;
      return { x: x, y: y };
    };

    //-imageZoom--------imageZoom---------imageZoom--//

    return {
      resultez,
      lensz,
      imgz,
      resultz,
      cxz,
      cyz,
      imgtopz,
      resulz,
      imageZoomz,
      img,
      moveLensz,
      clearopacityz,
      getCursorPosz,
      image,
      shangimg,
      zoom,
      imgmob,
      glass,
      h,
      w,
      bw,
      magnify,
      moveMagnifier,
      getCursorPoss,
      imgmobaile,
      witW,
      wit,
    };
  },
};
</script>

<style>
.flex-2-item {
  display: flex;
  justify-content: flex-start;
  align-items: center;
}
.item-1-flex {
  flex: 40%;
}
.item-2-flex {
  flex: 60%;
}

.item-12-flex {
  flex: 100%;
}

.product__details__text {
  z-index: 100;
}
.img-zoom-item {
  position: relative;
  overflow: hidden;
}
.img-zoom-item img {
  height: 50px;
  width: 50px;
  display: block;
  border-radius: 50%;
  cursor: pointer;
}

.column {
  position: relative !important ;
}
.img-zoom-container {
  position: relative;
  width: 100%;
  height: auto;
  min-height: 300px;
  display: block;
}
.img-zoom-container img {
  width: 100%;
  height: auto;
}

.img-zoom-lens {
  display: block;
  position: absolute;
  border: 1px solid #d4d4d4;
  /*set the size of the lens:*/
  width: 200px;
  height: 200px;
}
.img-zoom-lens-remove {
  border: 0px;
}

.img-zoom-result {
  position: absolute;
  border: 1px solid #d4d4d4;
  /*set the size of the result div:*/
  width: 100%;
  height: 100%;
  max-block-size: 400px;
  opacity: 0;
  transition: 0.8s ease;
  /*clear: both;*/
  background-repeat: no-repeat;
}

#descreption {
  position: relative;
  z-index: 1000;
}
.img-zoom-container img:hover .img-zoom-result {
  opacity: 1 !important;
}
/*zome mobaile*/

.img-magnifier-container {
  display: none;
  position: relative;
  width: 100%;

  height: 100%;
}
.img-magnifier-container img {
  width: 100%;
  height: 100%;
}

.img-magnifier-glass {
  position: absolute;
  border: 4px solid #e3e3e3;
  border-radius: 5px;
  cursor: none;
  /*Set the size of the magnifier glass:*/
  display: block;
  width: 200px !important;
  height: 200px !important;
}
.row-img img {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 2px solid #cecece;
  cursor: pointer;
}
.row-img {
  margin-inline-start: 3px;
}
.row {
  position: relative;
}

.active {
  padding: 1em;
  border: 1px solid rgb(9, 160, 67);
}

@media screen and (max-width: 769px) {
  .row {
    display: flex;
  }

  .img-zoom-item img {
    height: 25px;
    width: 25px;
    display: inline-block;
    margin-inline-end: 15px;
  }
  .img-magnifier-container {
    display: block;
  }

  .img-zoom-container {
    display: none;
  }
  .flex-2-item {
    flex-direction: column;
    align-items: flex-start;
  }
  .img-magnifier-glass {
    width: 280px !important;
    height: 280px !important;
  }
}

/*-------- */
@media only screen and (min-width: 467px) and (max-width: 769px) {
  .img-magnifier-glass {
    width: 200px !important;
    height: 200px !important;
  }
}
@media only screen and (max-width: 467px) {
  .img-magnifier-glass {
    width: 150px !important;
    height: 150px !important;
  }
}
</style>