تغيير اكتشاف المكون Glimmer لا يعمل - تعديل الخصائص في مصفوفة @tracked

أهلاً بالجميع!

أواجه مشكلة في اكتشاف التغييرات في مكون Glimmer وأحتاج إلى بعض التوجيه. عندما أقوم بتعديل خصائص الكائنات داخل مصفوفة \@tracked\\، لا يتم إعادة عرض القالب.

\\إعداداتي:\\

```javascript

import Component from '@glimmer/component';

import { tracked } from '@glimmer/tracking';

import { fn } from '@ember/helper';

import { on } from '@ember/modifier';

import { action } from '@ember/object';



export default class CustomSidebarComponent extends Component {

  @tracked items = [

    {

      id: 'home',

      label: 'Home',

      expanded: false

    },

    {

      id: 'my-posts', 

      label: 'My Posts',

      expanded: false

    }

    // ... المزيد من العناصر

  ];



  @action

  toggleExpanded(item) {

    item.expanded = !item.expanded; // هذا التعديل لا يؤدي إلى إعادة العرض

    console.log('Toggled:', item.label, item.expanded); // يتم تسجيلها بشكل صحيح

  }



  <template>
    <div id="custom-sidebar">
      <ul>
        {{#each this.items key="@index" as |item|}}
          <li class="menu-item {{if item.expanded 'expanded'}}" {{on "click" (fn this.toggleExpanded item)}}>
            {{item.label}} {{if item.expanded "(expanded)" ""}}
          </li>
        {{/each}}
      </ul>
    </div>
  </template>

}

```

\\المشكلة:\\

  1. معالج النقر يعمل بشكل صحيح
  2. الخاصية \item.expanded\\ يتم تحديثها (تم التحقق منها في وحدة التحكم)
  3. لكن القالب لا يتم إعادة عرضه - لا توجد تغييرات في الفئة، ولا تغييرات في النص

\\ما جربته:\\

  1. \\إعادة تعيين المصفوفة\\ - \this.items = [...this.items]\\ بعد التعديل (لا يعمل)
  2. \\Immer للتحديثات غير القابلة للتغيير\\ - أردت تجربة هذا ولكن لم أتمكن من جعل استيرادات npm تعمل في سمات Discourse
  3. \\استراتيجيات مفاتيح مختلفة\\ - \key="id"\\ بدلاً من \key="@index"\\

\\الأسئلة:\\

\- هل تعديل الخصائص على الكائنات داخل مصفوفات \@tracked\\ يفترض أن يعمل في Glimmer؟
\- هل أحتاج إلى جعل الكائنات الفردية قابلة للتتبع بطريقة ما؟
\- هل هناك نمط موصى به لهذه الحالة؟
\- هل يمكن أن يكون هذا مرتبطًا بالتشغيل في بيئة سمة Discourse؟
\- هل هناك قيود على استيرادات npm في سمات Discourse تؤثر على مكتبات التفاعلية؟

\\البيئة:\\

\- مكون سمة Discourse
\- مكونات Glimmer مع ملفات \.gjs\\
\- أحدث إصدار من Discourse - تم تحديثه اليوم

أي رؤى ستكون محل تقدير كبير! هل هناك شيء أساسي أفتقده حول نظام التفاعلية في Glimmer؟

شكرًا!

إعجابَين (2)

حسنًا، هذا غريب. عادةً ما تنجح خدعة تعيين المصفوفة.

بديل وجدته هو جعل الكائنات في المصفوفة من فئة لها خصائصها المتعقبة الخاصة. شيء مثل:

class CustomSidebarItem {
  @tracked expanded = false;
  constructor(id, label) {
    this.id = id;
    this.label = label;
  }
}

export default class CustomSidebarComponent extends Component {

  @tracked items = [
    new CustomSidebarItem('home', 'Home'),
    new CustomSidebarItem('my-posts', 'My Posts'),
    ...
  ];
  // rest of your code
}

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

4 إعجابات

مرحباً Alteras،

شكراً لاقتراحك !!! لقد نجح الأمر كما اقترحت ولقد جعل يومنا أسهل بكثير نص مُشدد :وجه_ضاحك:

إعجابَين (2)

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

طريقة أخرى للتعامل معها هي استخدام trackedObject، ونحن نستخدم هذا في عدد قليل من الأماكن في جميع أنحاء Discourse.

3 إعجابات

شكراً على مدخلاتك. لدي أسئلة متابعة أخرى:

هل استخدام مكتبة مثل immer سيعمل؟
إذا كان الأمر كذلك، كيف يجب أن أدرج immer في discourse؟
لقد رأيت إشارات إلى “نسخها إلى الأصول من node_modules”، لكنني أفضل إذا كانت هناك طريقة للقيام بذلك عبر npm، أو حتى رابط CDN في وسم الرأس.

يمكنك استخدام loadScript() لتحميل JS، حتى لو كان عنوان URL المقدم عنوان URL خارجيًا. يجب أن تعمل الخدمات الخارجية مثل jsdelivr مع هذا.

import loadScript from "discourse/lib/load-script";

...

loadScript(URL).then(() => {
   // your code
})

على الرغم من أنني لم أختبره بشكل شامل، إلا أن الاستيراد الديناميكي يجب أن يعمل أيضًا.

async function load() {
  const {
    default: myDefault,
    foo,
    bar,
  } = await import(URL);
  // rest of code
}

يجب أن أشير إلى أنه من الآمن على الأرجح حفظ ملفات NPM مباشرة في الكود الخاص بك بدلاً من الاعتماد على شبكة توصيل محتوى خارجية، اعتمادًا على مدى أهمية JS. وبالمثل، قد تحتاج إلى إجراء بعض التجميع والمعالجة المسبقة قبل أن تتمكن من استخدامه في المتصفح.


أما بالنسبة لما إذا كان Immer سيعمل مع discourse، فلا أعرف.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.