הבלוג של ינון פרק

טיפים קצרים וחדשות למתכנתים

ניסוי ויו: הצפנת זיגזג

26/02/2025
vue

כתבתי פה בעבר על הספר סודות ההצפנה לילדים שכתבה סתיו אלבר כשהספר עוד היה רעיון בהדסטארט. היום הספר גמור ואני באמצע הקריאה עם הילדים הפרטיים שלי שמאוד נהנים ממנו בינתיים. בשביל המשחק ובעקבות השראה מהספר חשבתי לממש את אחת ההצפנות הפרימיטיביות מהדוגמאות של סתיו בקוד Vue.

המשך קריאה

טיפ ויו: לאן נעלמה הטמפלייט

14/02/2025
vue

הקוד הבא ב Vue מראה על המסך את הטקסט Hello Vue:

<template>
    <template v-if="true">
        <p>Hello Vue</p>
    </template>
</template>

אבל זה כבר לא מראה כלום:

<template>
    <template>
        <p>Hello Vue</p>
    </template>
</template>

בואו נראה למה.

המשך קריאה

חידת Vue - איך עובד Scoped Style

29/01/2025
vue

נכתוב את הקוד הבא בקומפוננטת App.vue:

<script setup>
import Child from './Child.vue';
</script>

<template>
  <p class="red">Hello World from App</p>
  <Child />
</template>

<style scoped>
.red {
  color: red;
}
</style>

וזה Child.vue:

<script setup></script>

<template>
  <button class="red">
    Hello World from Child
  </button>
</template>

אפשר לראות את הדוגמה לייב בקישור הזה: https://tinyurl.com/4nff62kp

עכשיו לשאלות - למה הטקסט בכפתור מופיע באדום? ואיך אפשר "לנתק" אותו מהעיצוב של App כדי שלא יקבל את הגדרת האדום משם?

שימו לב שהגדרות העיצוב הן בבלוק styled scoped ושזו לא הבעיה שמתוארת כאן: https://www.tocode.co.il/blog/2021-10-watch-out-inherited-css, למרות שגם הבעיה בפוסט ההוא מעניינת.

ואם בכל זאת אני רוצה להעביר משתנה ריאקטיבי ב Vue לילדים?

28/01/2025
vue

הקוד הבא ב Vue לא עובד, או לפחות לא עושה את מה שהתכוונתי. קומפוננטה עליונה:

<script setup>
import { ref } from 'vue'
import Child from './Child.vue';
const x = ref(10)
</script>

<template>
  <Child :x="x" />
</template>

וקומפוננטת Child:

<script setup lang="ts">
const {x} = defineProps<{x: any}>();

function inc() {
  x.value++;
}
</script>

<template>
  <p>x = {{x}}</p>
  <button @click="inc">+1</button>
</template>

נראה כאילו Child מקבל אוביקט ריאקטיבי x ומעלה את ערכו ב-1. בפועל העברת הפרמטר דרך props מעבירה את ה value של האוביקט הריאקטיבי, כלומר בתוך Child המשתנה x הוא מספר. למספר אין שדה .value ולכן הקוד נכשל.

המשך קריאה

תבנית פרויקט: nuxt, drizzle, auth0

27/01/2025
vue

אתמול פירסמתי פה תבנית לפרויקט React שמשתמש ב Next.js ומכיל קומפוננטות צד שרת, משיכת מידע מבסיס נתונים וניהול משתמשים עם auth0. היום נראה את החלק השני של הפוסט ונבנה את אותה תבנית עבור nuxt ליישומי vue. הקוד כאן:

https://github.com/ynonp/nuxt-drizzle-auth0-demo

בואו נראה מה יש בריפו.

המשך קריאה

היום למדתי: v-bind ו style scoped

23/01/2025
vue

ויו מאפשר להשתמש ב v-bind בתוך בלוק CSS כדי לחבר קוד עיצוב למידע ריאקטיבי. זה עובד ממש נחמד וזאת הדוגמה מהאתר שלהם:

<script setup>
import { ref } from 'vue'
const theme = ref({
    color: 'red',
})
</script>

<template>
  <p>hello</p>
</template>

<style scoped>
p {
  color: v-bind('theme.color');
}
</style>

אבל מה קורה כשמנסים את זה בלי scoped? כלומר מה אם ננסה:

<script setup>
import { ref } from 'vue'
const theme = ref({
    color: 'red',
})
</script>

<template>
  <p>hello</p>
</template>

<style>
p {
  color: v-bind('theme.color');
}
</style>

בשביל להבין את התשובה צריך להבין איך v-bind בתוך CSS עובד - כש vue רואה v-bind בתוך CSS הוא מגדיר משתנה CSS על האלמנט הראשי של הקומפוננטה עם הערך שכתוב בתוך ה v-bind והביטוי המלא v-bind('theme.color) מוחלף בשיערוך המשתנה.

עכשיו כבר ברור למה זה לא עובד כמו שהיינו מצפים כשבלוק ה style אינו scoped. כן כלל ה CSS שנכתוב יכול לפעול על כל אלמנטי ה p בעמוד, אבל כל אלמנטי ה p שלא נמצאים בתוך הקומפוננטה לא מכילים את משתנה ה CSS המיוחד ולכן לא יקבלו את הגדרת הצבע.

חידת Vue: ריאקטיביות

16/01/2025
vue

נתון קוד Vue הבא:

<script setup lang="ts">
import {ref, computed} from 'vue';

const data = { count: 0 };
const value = ref(data);
function btn1() {
  data.count = 5;
}

function btn2() {
  value.value.count++;
}
</script>

<template>
  <div>
  <p>
    Value is: <span>{{ value.count }}</span></p>
  <button @click="btn1">Button 1</button>
  <button @click="btn2">Button 2</button>
  <hr />
</div>
</template>

מה יופיע על המסך אחרי לחיצה על שני הכפתורים לפי הסדר? מה יקרה אם נלחץ רק על הראשון? למה זה קורה?

מה יקרה אם נשנה את התבנית ל:

<template>
  <div>
  <p>
    Value is: <span>{{ data.count }}</span></p>
  <button @click="btn1">Button 1</button>
  <button @click="btn2">Button 2</button>
  <hr />
</div>
</template>

מה יהיו ערכי המשתנים אחרי לחיצה על הכפתורים? מה יופיע על המסך?

ניסוי ריאקט: משתנה סטייט לקריאה וכתיבה

08/01/2025
vue

ב Vue אנחנו יוצרים משתנה סטייט עם הפקודה ref ומקבלים משהו שאפשר לכתוב אליו וגם לקרוא ממנו לדוגמה הקוד הבא מציג מונה לחיצות עם משתנה סטייט ששומר את מספר הלחיצות:

<script setup>
import { ref } from 'vue'

const counter = ref(0)
function inc() { counter.value++ }
</script>

<template>
  <p>{{counter}}</p>
  <button @click="inc">+1</button>
</template>

בריאקט הפקודה useState מחזירה שני דברים: את הערך עצמו של משתנה הסטייט ופונקציה שמעדכנת אותו. בואו ננסה לעטוף את useState כדי לקבל רק דבר אחד שיתנהג כמו משתנה סטייט ב vue.

המשך קריאה

חידת Vue משתנים ריאקטיביים

03/01/2025
vue

נתון קוד Vue הבא:

<script setup>
import { ref } from 'vue'
const init = {count: 0}
const item = ref(init)

function inc() { item.value.count++ }
function reset() { item.value = init }
</script>

<template>
  <p>{{ item.count }}</p>
  <button @click="inc">+1</button>
  <button @click="reset">Reset</button>
</template>

משתמש לוחץ כמה פעמים על כפתור הפלוס ואז על כפתור ה Reset. האם הערך בתיבה מתאפס? למה?

וכן הכנתי לכם את זה כבר בלייב שתוכלו לבדוק כאן: דוגמת לייב

המשך קריאה

ריאקט מול ויו - שימו לב לשינויי סטייט

31/12/2024
vue

גם בריאקט וגם ב Vue יש תמיכה בערכים מחושבים, אבל הרזולוציה שונה ואנחנו צריכים לשים לב לזה כשכותבים קוד.

בריאקט הקומפוננטה הבאה מגדירה שני ערכים ושני ערכים מחושבים:

import "./styles.css";
import { useState } from "react";

export default function App() {
  const [x, setX] = useState(0);
  const [y, setY] = useState(0);
  const twoX = x * 2;
  const twoY = y * 2;

  return (
    <div className="App">
      <label>
        X:
        <input
          type="number"
          value={x}
          onChange={(e) => setX(Number(e.target.value))}
        />
        <span>x = {x}; </span>
        <span>2x = {twoX}</span>
      </label>
      <label>
        Y:
        <input
          type="number"
          value={y}
          onChange={(e) => setY(Number(e.target.value))}
        />
        <span>y = {y}; </span>
        <span>2y = {twoY}</span>
      </label>
    </div>
  );
}

אבל לא היינו כותבים קוד כזה בעולם האמיתי. הרזולוציה לא נכונה. בדוגמת הקוד גם כש x משתנה וגם כש y משתנה יש לחשב מחדש את שני הערכים המחושבים twoX ו twoY, בגלל שרזולוציית שינויים בריאקט היא קומפוננטה. בעולם האמיתי הקומפוננטה הזאת היתה מחולקת לשתי קומפוננטות, גם בגלל כפל הקוד וגם ובעיקר בגלל ה State - לקומפוננטה יש מספר אזורים שכל אחד מהם מושפע באופן עצמאי מסטייט אחר, וזה סימן ברור שמשהו בבחירת הקומפוננטה שלנו לא נכון.

ב Vue הסיפור קצת יותר מורכב אבל גם יותר קל למשתמשים. זאת הקומפוננטה:

<script setup>
import {ref, computed} from 'vue';
const x = ref(0);
const y = ref(0);
const twoX = computed(() => x.value * 2);
const twoY = computed(() => y.value * 2);
</script>

<template>
  <div class="App">
      <label>
        X:
        <input
          type="number"
          v-model="x"
        />
        <span>x = {{x}}; </span>
        <span>2x = {{twoX}}</span>
      </label>
      <label>
        Y:
        <input
          type="number"
          v-model="y"

        />
        <span>y = {{y}}; </span>
        <span>2y = {{twoY}}</span>
      </label>
    </div>
</template>

הקוד זהה אבל ההתנהגות שונה - שינוי ב x גורם לחישוב מחדש רק של twoX ושינוי ב y גורם לחישוב מחדש רק של twoY, כלומר רזולוציית השינוי היא לפי המשתנה והערכים שמחושבים ממנו. זה אומר שב vue יהיו לנו פחות בעיות ביצועים כתוצאה משינוי שיצא משליטה, אבל מצד שני יותר קשה לנו להבין את ההשפעה האמיתית של כל שינוי כי בשביל לראות מה מושפע מ x צריך לעקוב אחרי ה computed ולהסתכל על ה render function שנוצרה ואיזה חלקים ממנה מושפעים מכל ref.

בסוף בשני המקרים יהיה הגיוני לחלק אחרת לקומפוננטות לפי מבנה ה State. אפשר להגיד ש vue יותר מתאמץ בשביל שנוכל "לחיות" עם הטעות בלי לשלם בביצועים וריאקט דורש תשומת לב גבוהה יותר לפרטים בבניית המערכת. שמעתי כבר את הטיעון שבגלל זה קוד ריאקט באופן כללי הוא טוב יותר, כי אנשים יותר מתאמצים לכתוב נכון. אני חייב להודות שמהניסיון שלי הרבה פעמים זה לא ממש עוזר וקוד ריאקט של מערכות גדולות גם לא מחולק נכון לקומפוננטות וכתוצאה מזה גם סובל מבעיות ביצועים.