javascript شرح - حلقة داخل React JSX




ماهو ترجمة (25)

إذا كان numrows صفيفًا ، وهو بسيط جدًا.

<tbody>
   {numrows.map(item => <ObjectRow />)}
</tbody>

نوع بيانات المصفوفة في React هو الأفضل ، يمكن للمصفوفة أن تدعم مجموعة جديدة ، وفلتر الدعم ، وتقليل الخ.

أحاول أن أفعل شيئًا مثل ما يلي في React JSX (حيث يكون ObjectRow مكونًا منفصلاً):

<tbody>
    for (var i=0; i < numrows; i++) {
        <ObjectRow/>
    } 
</tbody>

أدرك وفهم سبب عدم صحة JSX ، نظرًا لأن JSX يعمل على تعيين المكالمات. ومع ذلك ، وأنا قادم من نموذج القالب وكوني جديدًا في JSX ، فأنا غير متأكد من كيفية تحقيق ما ورد أعلاه (إضافة مكون عدة مرات).


سؤال عظيم.

ما أقوم به عندما أريد إضافة عدد معين من المكونات هو استخدام وظيفة المساعد.

حدد وظيفة تقوم باعادة JSX:

const myExample = () => {
    let myArray = []
    for(let i = 0; i<5;i++) {
        myArray.push(<MyComponent/>)
    }
    return myArray
}

//... in JSX

<tbody>
    {myExample()}
</tbody>

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

render() {
const mapItem = [];
for(let i =0;i<item.length;i++) 
  mapItem.push(i);
const singleItem => (item, index) {
 // item the single item in the array 
 // the index of the item in the array
 // can implement any logic here
 return (
  <ObjectRow/>
)

}
  return(
   <tbody>{mapItem.map(singleItem)}</tbody>
  )
}

فكر في الأمر وكأنك فقط تتصل بوظائف JavaScript. لا يمكنك وضع حلقة for داخل حلقة استدعاء دالة:

return tbody(
    for (var i = 0; i < numrows; i++) {
        ObjectRow()
    } 
)

ولكن يمكنك إنشاء صفيف ، ثم تمرير ذلك في:

var rows = [];
for (var i = 0; i < numrows; i++) {
    rows.push(ObjectRow());
}
return tbody(rows);

يمكنك استخدام البنية نفسها في الأساس عند العمل مع JSX:

var rows = [];
for (var i = 0; i < numrows; i++) {
    // note: we add a key prop here to allow react to uniquely identify each
    // element in this array. see: https://reactjs.org/docs/lists-and-keys.html
    rows.push(<ObjectRow key={i} />);
}
return <tbody>{rows}</tbody>;

وبالمناسبة ، فإن مثال جافا سكريبت الخاص بي هو تقريبا بالضبط ما يتحول هذا المثال إلى JSX. العب مع Babel REPL للتعرف على كيفية عمل JSX.


لنفترض أن لدينا مجموعة من العناصر في ولايتك:

[{name: "item1", id: 1}, {name: "item2", id: 2}, {name: "item3", id: 3}]

<tbody>
    {this.state.items.map((item) => {
        <ObjectRow key={item.id} name={item.name} />
    })} 
</tbody>

ويمكن القيام بذلك بطرق متعددة.

  1. كما هو موضح أعلاه ، قبل أن يقوم return تخزين كافة العناصر في الصفيف
  2. حلقة داخل return

    طريقة 1

     let container =[];
        let arr = [1,2,3] //can be anything array, object 
    
        arr.forEach((val,index)=>{
          container.push(<div key={index}>
                         val
                         </div>)
            /** 
            * 1. All loop generated elements require a key 
            * 2. only one parent element can be placed in Array
            * e.g. container.push(<div key={index}>
                                        val
                                  </div>
                                  <div>
                                  this will throw error
                                  </div>  
                                )
            **/   
        });
        return (
          <div>
             <div>any things goes here</div>
             <div>{container}</div>
          </div>
        )
    

    الطريقة الثانية

       return(
         <div>
         <div>any things goes here</div>
         <div>
            {(()=>{
              let container =[];
              let arr = [1,2,3] //can be anything array, object 
              arr.forEach((val,index)=>{
                container.push(<div key={index}>
                               val
                               </div>)
                             });
                        return container;     
            })()}
    
         </div>
      </div>
    )
    

يمكنك أيضًا استخدام وظيفة استدعاء ذاتي:

return <tbody>
           {(() => {
              let row = []
              for (var i = 0; i < numrows; i++) {
                  row.push(<ObjectRow key={i} />)
              }
              return row

           })()}
        </tbody>

هناك عدة إجابات تشير إلى استخدام بيان map . في ما يلي مثال كامل باستخدام مكرر ضمن مكون FeatureList لسرد مكونات الميزة استنادًا إلى بنية بيانات JSON تسمى الميزات .

const FeatureList = ({ features, onClickFeature, onClickLikes }) => (
  <div className="feature-list">
    {features.map(feature =>
      <Feature
        key={feature.id}
        {...feature}
        onClickFeature={() => onClickFeature(feature.id)}
        onClickLikes={() => onClickLikes(feature.id)}
      />
    )}
  </div>
); 

يمكنك عرض رمز FeatureList الكامل على GitHub. يتم سرد ميزات تركيبات هنا .


وهنا حل بسيط لذلك.

var Object_rows=[];
for (var i=0; i < numrows; i++) {
    Object_rows.push(<ObjectRow/>)
} 
<tbody>
{Object_rows}
</tbody>

لا تحتاج إلى تخطيط ورمز معقد. تحتاج فقط إلى دفع الصفوف إلى صفيف وإرجاع القيم لعرضها.


نظرًا لأنك تكتب صياغة جافا سكريبت داخل شفرة JSX ، يجب أن تقوم بتغليف جافا سكريبت في أقواس معقوفة.

row = () => {
   var rows = [];
   for (let i = 0; i<numrows; i++) {
       rows.push(<ObjectRow/>);
   }
   return rows;
}
<tbody>
{this.row()}  
</tbody>

ES2015 Array.from مع وظيفة الخريطة + مفتاح

إذا لم يكن لديك أي شيء .map() يمكنك استخدام Array.from() مع mapFn لتكرار العناصر:

<tbody>
  {Array.from({ length: 5 }, (v, k) => <ObjectRow key={k} />)}
</tbody>

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

إليك بعض التعليمات البرمجية التي قد تساعد في:

MyClass extends Component {
    constructor() {
        super(props)
        this.state = { elements: [] }
    }
    render() {
        return (<tbody>{this.state.elements}<tbody>)
    }
    add() {
        /*
         * The line below is a cheap way of adding to an array in the state.
         * 1) Add <tr> to this.state.elements
         * 2) Trigger a lifecycle update.
         */
        this.setState({
            elements: this.state.elements.concat([<tr key={elements.length}><td>Element</td></tr>])
        })
    }
}

يمكنك بالطبع حل مع .map كما اقترحه الجواب الآخر. إذا كنت تستخدم بالفعل babel ، فيمكنك التفكير في استخدام jsx-control-statements فهي تتطلب القليل من الإعداد ، ولكن أعتقد أنه يستحق القراءة من حيث قابلية القراءة (خاصة للمطورين الذين لا يتفاعلون). إذا كنت تستخدم eslint-plugin-jsx-control-statements ، فهناك أيضًا eslint-plugin-jsx-control-statements


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

تهدف إجابتي إلى دمج جميع الطرق الرائعة التي تم تقديمها هنا:

إذا لم يكن لديك مجموعة من الكائنات ، ببساطة عدد الصفوف:

داخل كتلة return ، وإنشاء Array واستخدام Array.prototype.map :

render() {
  return (
    <tbody>
      {Array(numrows).fill(null).map((value, index) => (
        <ObjectRow key={index}>
      ))}
    </tbody>
  );
}

خارج كتلة return ، ما عليك سوى استخدام JavaScript for-loop العادي:

render() {
  let rows = [];
  for (let i = 0; i < numrows; i++) {
    rows.push(<ObjectRow key={i}/>);
  } 
  return (
    <tbody>{rows}</tbody>
  );
}

على الفور استدعاء وظيفة التعبير:

render() {
  return (
    <tbody>
      {() => {
        let rows = [];
        for (let i = 0; i < numrows; i++) {
          rows.push(<ObjectRow key={i}/>);
        }
        return rows;
      }}
    </tbody>
  );
}

إذا كان لديك مجموعة من الكائنات

داخل كتلة return .map() كل كائن إلى مكون <ObjectRow> :

render() {
  return (
    <tbody>
      {objectRows.map((row, index) => (
        <ObjectRow key={index} data={row} />
      ))}
    </tbody>
  );
}

خارج كتلة return ، ما عليك سوى استخدام JavaScript for-loop العادي:

render() {
  let rows = [];
  for (let i = 0; i < objectRows.length; i++) {
    rows.push(<ObjectRow key={i} data={objectRows[i]} />);
  } 
  return (
    <tbody>{rows}</tbody>
  );
}

على الفور استدعاء وظيفة التعبير:

render() {
  return (
    <tbody>
      {() => {
        let rows = [];
        for (let i = 0; i < objectRows.length; i++) {
          rows.push(<ObjectRow key={i} data={objectRows[i]} />);
        }
        return rows;
      }}
    </tbody>
  );
}

تستخدم إمكانية ES2015 / Babel وظيفة المولد لإنشاء صفيف من JSX:

function* jsxLoop(times, callback)
{
    for(var i = 0; i < times; ++i)
        yield callback(i);
}

...

<tbody>
    {[...jsxLoop(numrows, i =>
        <ObjectRow key={i}/>
    )]}
</tbody>

أنا استخدمها مثل

<tbody>
{ numrows ? (
   numrows.map(obj => { return <ObjectRow /> }) 
) : null}
</tbody>

أعلم أن هذا خيط قديم ، ولكن قد ترغب في الخروج http://wix.github.io/react-templates/ ، مما يتيح لك استخدام قوالب نمط jsx في التفاعل ، مع بعض التوجيهات (مثل rt- كرر).

المثال الخاص بك ، إذا استخدمت قوالب تفاعل ، سيكون:

<tbody>
     <ObjectRow rt-repeat="obj in objects"/>
</tbody>

ما عليك سوى استخدام .map() للتكرار من خلال المجموعة الخاصة بك <ObjectRow> عناصر <ObjectRow> مع props من كل التكرار.

افترض objects هي مجموعة في مكان ما ...

<tbody>
  { objects.map((obj, index) => <ObjectRow obj={ obj } key={ index }/> ) }
</tbody>

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

لذا من المحتمل أن أفعل شيئًا مثل:

import _ from 'lodash';

...

const TableBody = ({ objects }) => {
  const objectRows = objects.map(obj => <ObjectRow object={obj} />);      

  return <tbody>{objectRows}</tbody>;
} 

من المسلم به أن هذا هو كمية صغيرة من التعليمات البرمجية التي قد تعمل بشكل جيد.


انا استعمل هذا:

gridItems = this.state.applications.map(app =>
                            <ApplicationItem key={app.Id} app={app } />
                            );

PD: أبدا ننسى المفتاح أو سيكون لديك الكثير من التحذيرات!


ببساطة ، استخدم طريقة Array Map مع صيغة ES6:

<tbody>
  {items.map(item => <ObjectRow key={item.id} name={item.name} />)} 
</tbody>

لا تنس الملكية key .


سيتم ترجمة شفرة ReactElement إلى شفرة جافا سكريبت خالصة ، وسيتم استبدال أية علامات ReactElement . في JavaScript ، لا يمكنك استدعاء دالة عدة مرات لتجميع المتغيرات التي تم إرجاعها.

إنه غير قانوني ، الطريقة الوحيدة هي استخدام صفيف لتخزين المتغيرات التي يتم إرجاعها.

أو يمكنك استخدام map والذي يتوفر منذ JavaScript ES5 للتعامل مع هذا الموقف.

ربما يمكننا أن نكتب مترجمًا آخر لإعادة إنشاء بنية JSX جديدة لتنفيذ وظيفة تكرار تمامًا مثل تكرار Angular في Angular .


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

إذا كانت هذه هي شفرتك مع حلقة for:

<tbody>
    for (var i=0; i < objects.length; i++) {
        <ObjectRow obj={objects[i]} key={i}>
    } 
</tbody>

يمكنك أن تكتبها هكذا مع map :

<tbody>
    {objects.map(function(object, i){
        return <ObjectRow obj={object} key={i} />;
    })}
</tbody>

بنية ES6:

<tbody>
    {objects.map((object, i) => <ObjectRow obj={object} key={i} />)}
</tbody>

يمكنك أيضًا استخراج خارج كتلة الإرجاع:

render: function() {
    var rows = [];
    for (var i = 0; i < numrows; i++) {
        rows.push(<ObjectRow key={i}/>);
    } 

    return (<tbody>{rows}</tbody>);
}

بالنسبة للناس ، يبحثون عن الإجابات المكتوبة على وظيفة "الخريطة" والبيانات الديناميكية ، هنا مثال عملي.

<img src={"http://examole.com/randomview/images" + each_actor['logo']} />

وهذا يعطي عنوان URL كـ " http://examole.com/randomview/images/2/dp_pics/182328.jpg " (مثال عشوائي)





javascript reactjs