React JS onClick olay işleyicisi


120

Sahibim

var TestApp = React.createClass({
      getComponent: function(){
          console.log(this.props);
      },
      render: function(){
        return(
             <div>
             <ul>
                <li onClick={this.getComponent}>Component 1</li>
             </ul>
             </div>
        );
      }
});
React.renderComponent(<TestApp />, document.body);

Tıklanan liste öğesinin arka planını renklendirmek istiyorum. Bunu React'te nasıl yapabilirim?

Gibi bir şey

$('li').on('click', function(){
    $(this).css({'background-color': '#ccc'});
});

Yanıtlar:


95

Neden olmasın:

onItemClick: function (event) {

    event.currentTarget.style.backgroundColor = '#ccc';

},

render: function() {
    return (
        <div>
            <ul>
                <li onClick={this.onItemClick}>Component 1</li>
            </ul>
        </div>
    );
}

Ve bu konuda daha fazla React-ive olmak istiyorsanız, seçilen öğeyi içerdiği React bileşeninin durumu olarak ayarlamak ve ardından öğenin içindeki rengini belirlemek için bu duruma başvurmak isteyebilirsiniz render:

onItemClick: function (event) {

    this.setState({ selectedItem: event.currentTarget.dataset.id });
    //where 'id' =  whatever suffix you give the data-* li attribute
},

render: function() {
    return (
        <div>
            <ul>
                <li onClick={this.onItemClick} data-id="1" className={this.state.selectedItem == 1 ? "on" : "off"}>Component 1</li>
                <li onClick={this.onItemClick} data-id="2" className={this.state.selectedItem == 2 ? "on" : "off"}>Component 2</li>
                <li onClick={this.onItemClick} data-id="3" className={this.state.selectedItem == 3 ? "on" : "off"}>Component 3</li>
            </ul>
        </div>
    );
},

Bunları <li>bir döngüye sokmak istersiniz ve li.onve li.offstillerini background-color.


React'teki manuel DOM manipülasyonu, yalnızca daha fazla soruna yol açan bir anti-modeldir . Ne event.currentTarget.style.backgroundColor = '#ccc';yaptığınızı gerçekten anlamadığınız gibi şeylerden kaçının (çoğu zaman üçüncü taraf widget'ları entegre ederken).
Emile Bergeron

61

Düşünebileceğim iki yol

var TestApp = React.createClass({
    getComponent: function(index) {
        $(this.getDOMNode()).find('li:nth-child(' + index + ')').css({
            'background-color': '#ccc'
        });
    },
    render: function() {
        return (
            <div>
              <ul>
                <li onClick={this.getComponent.bind(this, 1)}>Component 1</li>
                <li onClick={this.getComponent.bind(this, 2)}>Component 2</li>
                <li onClick={this.getComponent.bind(this, 3)}>Component 3</li>
              </ul>
            </div>
        );
    }
});
React.renderComponent(<TestApp /> , document.getElementById('soln1'));

Bu benim kişisel favorim.

var ListItem = React.createClass({
    getInitialState: function() {
        return {
            isSelected: false
        };
    },
    handleClick: function() {
        this.setState({
            isSelected: true
        })
    },
    render: function() {
        var isSelected = this.state.isSelected;
        var style = {
            'background-color': ''
        };
        if (isSelected) {
            style = {
                'background-color': '#ccc'
            };
        }
        return (
            <li onClick={this.handleClick} style={style}>{this.props.content}</li>
        );
    }
});

var TestApp2 = React.createClass({
    getComponent: function(index) {
        $(this.getDOMNode()).find('li:nth-child(' + index + ')').css({
            'background-color': '#ccc'
        });
    },
    render: function() {
        return (
            <div>
             <ul>
              <ListItem content="Component 1" />
              <ListItem content="Component 2" />
              <ListItem content="Component 3" />
             </ul>
            </div>
        );
    }
});
React.renderComponent(<TestApp2 /> , document.getElementById('soln2'));

İşte bir DEMO

Umarım bu yardımcı olur.


8
Bileşen her oluşturulduğunda bunu yapacağından, bağlama işlevi içinde bağlama uygulanması önerilmez. yaşam döngüsünün başında çalışan bir işleve taşıyabilirsiniz
jony89

1
@ jony89 .bindfazladan bir parametre almazsa kabul etti . Ama ilk durumda öyle. Başka bir yol olduğunu sanmıyorum
Dhiraj

1
Üç farklı işlev oluşturun (getComponent.bind (this, 1) sonucuyla oluşturulan), ancak bu kesin bir karar olabilir (bunu 2-3 bileşen için yapar, 20 için değil - gerçekten performans sorunu olmadığı sürece dinamik olarak oluşturmak kolaydır).
jony89

38

Es6 sözdizimini kullanarak soru başlığını yanıtlayan bir react onClick olay işleyicisini nasıl tanımladığınız aşağıda açıklanmıştır.

import React, { Component } from 'react';

export default class Test extends Component {
  handleClick(e) {
    e.preventDefault()
    console.log(e.target)
  }

  render() {
    return (
      <a href='#' onClick={e => this.handleClick(e)}>click me</a>
    )
  }
}

9
Her seferinde yeni bir işlevin oluşturulmasına neden oldukları bindiçin ne ok işlevleri ne de renderyöntemler içinde kullanılmalıdır . Bu, bileşenin durumunu değiştirme etkisine sahiptir ve değişen duruma sahip bileşenler her zaman yeniden oluşturulur. Bir bekar için abu önemli değil. Tıklanabilir öğeler içeren oluşturulan listeler için bu, çok hızlı bir şekilde önemli hale gelir. Bu yüzden özellikle karşı uyarıldı.
hippietrail

18

ECMA2015'i kullanın. Ok fonksiyonları "bunu" çok daha sezgisel hale getirir.

import React from 'react';


class TestApp extends React.Component {
   getComponent(e, index) {
       $(e.target).css({
           'background-color': '#ccc'
       });
   }
   render() {
       return (
           <div>
             <ul>
               <li onClick={(e) => this.getComponent(e, 1)}>Component 1</li>
               <li onClick={(e) => this.getComponent(e, 2)}>Component 2</li>
               <li onClick={(e) => this.getComponent(e, 3)}>Component 3</li>
             </ul>
           </div>
       );
   }
});
React.renderComponent(<TestApp /> , document.getElementById('soln1'));`

2
indexburada hiçbir şey yapmıyor mu?
northamerican

@northamerican - Hayır, sadece biraz parametre netliği eklemek için orada
itcropper

5
Bu aslında her işlemede yeni bir işlev oluşturduğu için performans açısından kötüdür. Bakınız: stackoverflow.com/questions/36677733/…
Jochie Nabuurs

1
Ve mecbur değilseniz lütfen React içinde jQuery kullanmayın!
Emile Bergeron

13

ES6 kullanıyorsanız, işte bazı basit örnek kod:

import React from 'wherever_react_is';

class TestApp extends React.Component {

  getComponent(event) {
      console.log('li item clicked!');
      event.currentTarget.style.backgroundColor = '#ccc';
  }

  render() {
    return(
       <div>
         <ul>
            <li onClick={this.getComponent.bind(this)}>Component 1</li>
         </ul>
       </div>
    );
  }
}

export default TestApp;

ES6 sınıf gövdelerinde, işlevler artık 'function' anahtar sözcüğünü gerektirmez ve virgülle ayrılmasına gerek yoktur. Dilerseniz => sözdizimini de kullanabilirsiniz.

Dinamik olarak oluşturulmuş öğelerin bir örneğini burada bulabilirsiniz:

import React from 'wherever_react_is';

class TestApp extends React.Component {

constructor(props) {
  super(props);

  this.state = {
    data: [
      {name: 'Name 1', id: 123},
      {name: 'Name 2', id: 456}
    ]
  }
}

  getComponent(event) {
      console.log('li item clicked!');
      event.currentTarget.style.backgroundColor = '#ccc';
  }

  render() {        
       <div>
         <ul>
         {this.state.data.map(d => {
           return(
              <li key={d.id} onClick={this.getComponent.bind(this)}>{d.name}</li>
           )}
         )}
         </ul>
       </div>
    );
  }
}

export default TestApp;

Dinamik olarak oluşturulan her bir öğenin benzersiz bir referans 'anahtarına' sahip olması gerektiğini unutmayın.

Ayrıca, gerçek veri nesnesini (olay yerine) onClick işlevinize geçirmek isterseniz, bunu bağlantınıza aktarmanız gerekir. Örneğin:

Yeni onClick işlevi:

getComponent(object) {
    console.log(object.name);
}

Veri nesnesine aktarım:

{this.state.data.map(d => {
    return(
      <li key={d.id} onClick={this.getComponent.bind(this, d)}>{d.name}</li>
    )}
)}

Li öğelerimi dinamik oluşturmaya çalışıyorum ve sonra bu tanımsız hale geliyor ve onClick işlevi bu nedenle bir hata veriyor.
indi

1
.Bind (this)) kullanmanız gereken yerde benzer bir cevap buldum; anonim işlevin sonunda bu, siz bağlama işlemini yapana kadar pencereyi ifade eder ...
indi


6

İle olayları işleme elemanları Tepki DOM öğeleri üzerinde olaylarını işleme çok benzer. Bazı sözdizimsel farklılıklar vardır:

  • React olayları, küçük harf yerine camelCase kullanılarak adlandırılır.
  • JSX ile bir dizi yerine olay işleyicisi olarak bir işlevi iletirsiniz.

React belgelerinde belirtildiği gibi , Olay İşleme söz konusu olduğunda normal HTML'ye oldukça benzerler, ancak React'te camelcase kullanan olay adları, gerçekten HTML olmadıklarından, JavaScript'tir, ayrıca, biz fonksiyon çağrısını geçerken fonksiyonu geçersiniz HTML için bir dize biçiminde, farklılar, ancak kavramlar oldukça benzer ...

Aşağıdaki örneğe bakın, olayın işleve nasıl aktarıldığına dikkat edin:

function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }

  return (
    <a href="#" onClick={handleClick}>
      Click me
    </a>
  );
}

3

import React from 'react';

class MyComponent extends React.Component {

  getComponent(event) {
      event.target.style.backgroundColor = '#ccc';
      
      // or you can write
      //arguments[0].target.style.backgroundColor = '#ccc';
  }

  render() {
    return(
       <div>
         <ul>
            <li onClick={this.getComponent.bind(this)}>Component 1</li>
         </ul>
       </div>
    );
  }
}

export { MyComponent };  // use this to be possible in future imports with {} like: import {MyComponent} from './MyComponent'
export default MyComponent;


Bu, esasen 11 maddelik cevapla aynı görünüyor ve bir güzel veya soruyu-neden diriltiyor?
Dave Newton

2

class FrontendSkillList extends React.Component {
  constructor() {
    super();
    this.state = { selectedSkill: {} };
  }
  render() {
    return (
      <ul>
        {this.props.skills.map((skill, i) => (
            <li
              className={
                this.state.selectedSkill.id === skill.id ? "selected" : ""
              }
              onClick={this.selectSkill.bind(this, skill)}
              style={{ cursor: "pointer" }}
              key={skill.id}
            >
            {skill.name}
            </li>
        ))}
      </ul>
    );
  }

  selectSkill(selected) {
    if (selected.id !== this.state.selectedSkill.id) {
      this.setState({ selectedSkill: selected });
    } else {
      this.setState({ selectedSkill: {} });
    }
  }
}

const data = [
  { id: "1", name: "HTML5" },
  { id: "2", name: "CSS3" },
  { id: "3", name: "ES6 & ES7" }
];
const element = (
  <div>
    <h1>Frontend Skill List</h1>
    <FrontendSkillList skills={data} />
  </div>
);
ReactDOM.render(element, document.getElementById("root"));
.selected {
  background-color: rgba(217, 83, 79, 0.8);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

@ user544079 Umarım bu demo yardımcı olabilir :) Sınıf adını değiştirerek arka plan rengini değiştirmenizi öneririm.


2

import React from 'react';

class MyComponent extends React.Component {

  getComponent(event) {
      event.target.style.backgroundColor = '#ccc';
      
      // or you can write
      //arguments[0].target.style.backgroundColor = '#ccc';
  }

  render() {
    return(
       <div>
         <ul>
            <li onClick={this.getComponent.bind(this)}>Component 1</li>
         </ul>
       </div>
    );
  }
}

export { MyComponent };  // use this to be possible in future imports with {} like: import {MyComponent} from './MyComponent'
export default MyComponent;


Bunun sorunu nasıl çözebileceğini açıklayarak bu koda daha fazla bağlam sağlayabilir misiniz?
MEDZ

1

React.createClone yöntemini kullanabilirsiniz. Bir klonunu oluşturmak yerine kendi elementinizi yaratın. Klonun yaratılması sırasında sahne enjekte edebilirsiniz. Bunun gibi bir onClick: yöntem propu enjekte edin

{ onClick : () => this.changeColor(originalElement, index) }

changeColor yöntemi, durumu kopyayla birlikte ayarlayarak işlem sırasında rengi ayarlamanıza olanak tanır.

render()
  {
    return(
      <ul>

        {this.state.items.map((val, ind) => {
          let item = <li key={ind}>{val}</li>;
          let props = { 
            onClick: () => this.Click(item, ind),
            key : ind,
            ind
          }
          let clone = React.cloneElement(item, props, [val]);
          return clone;
        })}

      </ul>
    )
  }


Klonlama tamamen gereksizdir.
Emile Bergeron

-17

Bu, JSX kullanmayan, her şeyi sıraya koyan standart olmayan (ancak çok da nadir olmayan) bir React modelidir. Ayrıca Coffeescript.

Bunu yapmanın 'tepki yolu' bileşenin kendi durumu ile olacaktır:

( c = console.log.bind console)

mock_items: [
    {
        name: 'item_a'
        uid: shortid()
    }
    {
        name: 'item_b'
        uid: shortid()
    }
    {
        name: 'item_c'
        uid: shortid()
    }
]
getInitialState: ->
    lighted_item: null
render: ->
    div null,
        ul null,
            for item, idx in @mock_items
                uid = item.uid
                li
                    key: uid
                    onClick: do (idx, uid) =>
                        (e) =>
                            # justf to illustrate these are bound in closure by the do lambda,
                            c idx
                            c uid
                            @setState
                                lighted_item: uid
                    style:
                        cursor: 'pointer'
                        background: do (uid) =>
                            c @state.lighted_item
                            c 'and uid', uid
                            if @state.lighted_item is uid then 'magenta' else 'chartreuse'
                        # background: 'chartreuse'
                    item.name

Bu örnek işe yarıyor - yerel olarak test ettim. Bu örnek kodu tam olarak benim github'umdan kontrol edebilirsiniz . Başlangıçta, ortam yalnızca kendi beyaz tahta ar-ge amaçlarım için yereldi, ancak bunun için Github'a gönderdim. Bir noktada üzerine yazılabilir, ancak bunu görmek için 8 Eylül 2016 tarihli işleme göz atabilirsiniz.

Daha genel olarak, React için bu CS / JSX olmayan modelin nasıl çalıştığını görmek istiyorsanız, buradaki son çalışmalara göz atın . Bu uygulama fikri için NodeJS, Primus, Redis ve React'i içeren bir POC'yi tam olarak uygulamak için zamanım olabilir.


arkaplanın bir dolambda olması gerekmez : Bu ifade şu şekilde de çalışır:background: if @state.lighted_item is uid then 'magenta' else 'chartreuse'
Wylie Kulik

merhaba tarayıcı konsolunda onclick'i nasıl görüntüleyebilirim?
Muneem Habib

12
CoffeeScript'i, ondan hiçbir şekilde bahsetmeyen bir soruya yanıt olarak neden kullanasınız? Herhangi bir anlam ifade etmiyor ve CoffeeScript'i bilmeyebileceği / beğenmeyebileceği için soruyu soran kişi için cevabı okumayı muhtemelen zorlaştırabilir. Belli ki olumsuz oylama.
macbem

7
Hayır ama dilin üzerine inşa edilmiş bir şey, mutlak standart değil ve kurulum ve derleme gerektiriyor. projelerinde kahve kullandığına dair hiçbir ipucu yokken cevabınızı kahve kağıdına yazmak gerçekten kötü bir seçimdi
TheRealMrCrowley

4
Coffeescript, js'nin üstündeki bir katmandır . FTFY.
machineghost
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.