[javascript] تمرير الدعائم إلى المكون الرئيسي في React.js


2 Answers

التحديث (9/1/15): لقد جعل هذا البروتوكول سؤالاً قليلاً من هدف متحرك. لقد تم تحديثه مرة أخرى. لذا ، أشعر بالمسؤولية لتحديث ردي.

أولاً ، إجابة على المثال الذي قدمته:

نعم ، هذا ممكن.

يمكنك حل هذه المشكلة من خلال تحديث " onClick الخاص بالأطفال ليكون هذا this.props.onClick.bind(null, this) :

var Child = React.createClass({
  render: function () {
    return <a onClick={this.props.onClick.bind(null, this)}>Click me</a>;
  }
});

يمكن لمعالج الحدث في الوالد الخاص بك الوصول إلى المكون والحدث كما يلي:

  onClick: function (component, event) {
    // console.log(component, event);
  },

لقطة JSBin


لكن السؤال نفسه مضلل

الوالد يعرف بالفعل props الطفل.

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

var Child = React.createClass({
  render: function () {
    return <a onClick={this.props.onClick}> {this.props.text} </a>;
  }
});

var Parent = React.createClass({
  getInitialState: function () {
    return { text: "Click here" };
  },
  onClick: function (event) {
    // event.component.props ?why is this not available? 
  },
  render: function() {
    return <Child onClick={this.onClick} text={this.state.text} />;
  }
});

يصبح أكثر وضوحا في هذا المثال أنك تعرف بالفعل ما هي الدعائم للطفل.

لقطة JSBin


إذا كان حقا حول استخدام الدعائم الطفل ...

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

يحتوي JSX على واجهة برمجة التطبيقات لبيانات الانتشار التي استخدمها غالبًا على مكونات مثل الطفل. يأخذ كل props ويطبقها على أحد المكونات. سيبدو الطفل هكذا:

var Child = React.createClass({
  render: function () {
    return <a {...this.props}> {this.props.text} </a>;
  }
});

يسمح لك باستخدام القيم مباشرة في الوالد:

var Parent = React.createClass({
  getInitialState: function () {
    return { text: "Click here" };
  },
  onClick: function (text) {
    alert(text);
  },
  render: function() {
    return <Child onClick={this.onClick.bind(null, this.state.text)} text={this.state.text} />;
  }
});

لقطة JSBin


وليس هناك أي تكوين إضافي مطلوب لأنك تقوم بتوصيل مكونات إضافية للأطفال

var Parent = React.createClass({
  getInitialState: function () {
    return {
      text: "Click here",
      text2: "No, Click here",
    };
  },
  onClick: function (text) {
    alert(text);
  },
  render: function() {
    return <div>
      <Child onClick={this.onClick.bind(null, this.state.text)} text={this.state.text} />
      <Child onClick={this.onClick.bind(null, this.state.text2)} text={this.state.text2} />
    </div>;
  }
});

لقطة JSBin

لكنني أشك في أن هذه ليست حالة الاستخدام الفعلية الخاصة بك. لذلك دعونا نحفر أبعد ...


مثال عملي قوي

من الصعب الحديث عن الطبيعة العامة للمثال المقدم. لقد أنشأت مكونًا يدل على الاستخدام العملي للسؤال أعلاه ، ويتم تنفيذه بطريقة رد الفعل للغاية:

DTServiceCalculator مثال على ذلك
DTServiceCalculator ريبو

هذا المكون هو آلة حاسبة بسيطة. تزودها بقائمة من الخدمات (مع الأسماء والأسعار) وستحسب إجمالي الأسعار المحددة.

الأطفال هم جاهلون بفرح

ServiceItem هو المكون ServiceItem في هذا المثال. ليس لديها الكثير من الآراء حول العالم الخارجي. يتطلب عددًا قليلًا من الدعائم ، أحدها دالة يجب استدعاؤها عند النقر عليها.

<div onClick={this.props.handleClick.bind(this.props.index)} />

لا يفعل أي شيء سوى استدعاء الاتصال handleClick المتوفر مع index المتوفر [ source ].

الآباء هم من الأطفال

DTServicesCalculator هو المكون الأصل هذا المثال. إنه أيضًا طفل دعونا ننظر.

ينشئ DTServiceCalculator قائمة DTServiceCalculator ( ServiceItem s) ويوفر لهم الدعائم [ source ]. إنه المكون الرئيسي لـ ServiceItem ولكنه العنصر التابع للمكون الذي يمررها في القائمة. لا يمتلك البيانات. لذلك يفوض مرة أخرى معالجة المكون إلى source الأصل المكون الخاص به

<ServiceItem chosen={chosen} index={i} key={id} price={price} name={name} onSelect={this.props.handleServiceItem} />

handleServiceItem بالتقاط المؤشر ، وتمريره من الطفل ، handleServiceItem إلى source الأصلي [ source ]

handleServiceClick (index) {
  this.props.onSelect(index);
}

المالكون يعرفون كل شيء

مفهوم "الملكية" هو مفهوم مهم في React. أوصي بقراءة المزيد حول هذا الموضوع here .

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

عندما نصل في النهاية إلى هناك ، نتعامل مع اختيار الولاية / إلغاء الاختيار مثل ذلك [ source ]:

handleSelect (index) {
  let services = […this.state.services];
  services[index].chosen = (services[index].chosen) ? false : true;
  this.setState({ services: services });
}


استنتاج

جرِّب إبقاء معظم المكونات الخارجية غير شفافة قدر الإمكان. احرص على التأكد من أن لديهم تفضيلات قليلة للغاية حول كيفية اختيار أحد الوالدين لتطبيقها.

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

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

Question

هل هناك طريقة بسيطة لتمرير props الطفل إلى والده باستخدام الأحداث ، في React.js؟

var Child = React.createClass({
  render: function() {
    <a onClick={this.props.onClick}>Click me</a>
  }
});

var Parent = React.createClass({
  onClick: function(event) {
    // event.component.props ?why is this not available?
  },
  render: function() {
    <Child onClick={this.onClick} />
  }
});

أعلم أنه يمكنك استخدام المكونات التي يتم التحكم فيها لتمرير قيمة المدخلات ، ولكن سيكون من الجيد تمرير المجموعة الكاملة n 'kaboodle. يحتوي المكون الفرعي أحيانًا على مجموعة من المعلومات التي لا تحتاج إلى البحث عنها.

ربما هناك طريقة لربط المكون بالحدث؟

تحديث - 9/1/2015

بعد استخدام React منذ أكثر من عام ، وحفزنا على إجابة سيباستيان لوربر ، انتهيت من تمرير مكونات الأطفال كمجالات إلى وظائف في الآباء ليست في الواقع طريقة رد الفعل ، ولم تكن فكرة جيدة على الإطلاق. لقد غيرت الجواب.




في ما يلي تنفيذ بسيط لـ 3 خطوات ES6 باستخدام ربط الدالة في منشئ الأهل. هذه هي الطريقة الأولى التي يوصي بها البرنامج التعليمي الرسمي (هناك أيضًا بنية لغوية في فئة الطبقة العامة لم يتم تغطيتها هنا). يمكنك العثور على جميع هذه المعلومات هنا https://reactjs.org/docs/handling-events.html

وظائف الوالدين الملزمة بحيث يمكن للأطفال الاتصال بهم (وتمرير البيانات حتى الأم!: D)

  1. تأكد من أن المُنشئ الأصل يقوم بربط الوظيفة التي قمت بإنشائها في الأصل
  2. تمرير الوظيفة المنحدرة إلى الطفل كدعم (لا لامدا لأننا نجتاز مرجعًا للعمل)
  3. استدعاء الدالة المندمجة من حدث الطفل (لامبدا! نحن نطلق على هذه الوظيفة عندما يتم إطلاق الحدث. إذا لم نفعل ذلك فسوف يتم تشغيل الوظيفة تلقائيًا عند التحميل ولن يتم تشغيلها في الحدث).

وظيفة الوالدين

handleFilterApply(filterVals){} 

منشئ الوالدين

this.handleFilterApply = this.handleFilterApply.bind(this);

الدعامة مرت على الطفل

onApplyClick = {this.handleFilterApply}

دعوة حدث الطفل

onClick = {() => {props.onApplyClick(filterVals)}



السؤال هو كيفية تمرير الحجة من الطفل إلى المكون الرئيسي. هذا المثال سهل الاستخدام والاختبار:

//Child component
class Child extends React.Component {
    render() {
        var handleToUpdate  =   this.props.handleToUpdate;
        return (<div><button onClick={() => handleToUpdate('someVar')}>Push me</button></div>
        )
    }
}

//Parent component
class Parent extends React.Component {
        constructor(props) {
        super(props);
        var handleToUpdate  = this.handleToUpdate.bind(this);
    }

        handleToUpdate(someArg){
            alert('We pass argument from Child to Parent: \n' + someArg);
    }

    render() {
        var handleToUpdate  =   this.handleToUpdate;
        return (<div>
                    <Child handleToUpdate = {handleToUpdate.bind(this)} /></div>)
    }
}

if(document.querySelector("#demo")){
    ReactDOM.render(
        <Parent />,
        document.querySelector("#demo")
    );
}

انظر إلى JSFIDDLE






Related