Birden çok satır içi stil nesnesi nasıl birleştirilir?


214

React'te açıkça bir nesne oluşturabilir ve onu bir satır içi stil olarak atayabilirsiniz. yani. aşağıda belirtilen.

var divStyle = {
  color: 'white',
  backgroundImage: 'url(' + imgUrl + ')',
  WebkitTransition: 'all', // note the capital 'W' here
  msTransition: 'all' // 'ms' is the only lowercase vendor prefix
};

var divStyle2 = {fontSize: '18px'};

React.render(<div style={divStyle}>Hello World!</div>, mountNode);

Birden çok nesneyi nasıl birleştirebilir ve birlikte atayabilirim?


İki nesne neye benziyor?
Ryan

Yanıtlar:


399

React Native kullanıyorsanız, dizi gösterimini kullanabilirsiniz:

<View style={[styles.base, styles.background]} />

Bununla ilgili detaylı blog yayınımı kontrol et.


41
Ne yazık ki bunu normal Tepki'de yapamazsınız.
YoTengoUnLCD

8
Eğer kullanıyorsanız bu kabul cevap olmalıdır Tepki-Yerli
calcazar

Stil adlarını / değerlerini ekleyerek mevcut satır içi stili biraz değiştirebilirsiniz. Örneğin,<View style={this.state.error == false ? styles.base : [styles.base, {backgroundColor: 'red'}]} />
Gürol Canbek

İki statik stil için, StyleSheet.compose()oluşturma işlevinin dışında yapmak daha verimli olabilir. Köprüden yalnızca bir kez gönderilecek yeni bir statik stil sayfası oluşturur. (Bu tavsiye, çalışma zamanında değişen veya bir StyleSheet yerine satır içi olan stiller için geçerli değildir.)
joeytwiddle

282

Forma operatörünü kullanabilirsiniz:

 <button style={{...styles.panel.button,...styles.panel.backButton}}>Back</button

8
İlk forma operatörünün ilk noktasını işaret ederek "Sözdizimi hatası: Beklenmeyen belirteç" iletisi alıyorum.
Izkata

@Izkata Bunu yerel tepkilerde mi yoksa yerel tepkilerde mi yapıyorsun, parçacığını gönderebilir misin
Nath

Tepki, böyle bir şeydi<div style={{ ...LEGEND_STYLE.box_base, ...{ 'background': '#123456' } }} />
Izkata

Yine de bir yardımcı işlevi kullanmak için yine de değiştirdim <div style={LEGEND_STYLE.box_gen('#123456')}, bu yüzden benim için çok önemli değil
Izkata

Bu, nesnenin yalnızca bir anahtar / değer çiftine sahip olması durumunda bile çalışır, ancak yayılma işleçlerinin yalnızca yinelenebilirler için geçerli olması gerekir! Nedenini açıklayabilir misin? developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Tyler

47

Bunu ile yapabilirsiniz Object.assign().

Örneğinizde şunları yapabilirsiniz:

ReactDOM.render(
    <div style={Object.assign(divStyle, divStyle2)}>
        Hello World!
    </div>,
    mountNode
);

Bu iki stili birleştirir. Eşleşen özellikler varsa ikinci stil birinci stilin yerini alacaktır.

Brandon'ın belirttiği gibi, fontSize uygulanmadan Object.assign({}, divStyle, divStyle2)yeniden kullanmak istiyorsanız kullanmalısınız divStyle.

Bunu varsayılan özelliklere sahip bileşenler yapmak için kullanmayı seviyorum. Örneğin, varsayılan olarak küçük bir durumsuz bileşen var margin-right:

const DivWithDefaults = ({ style, children, ...otherProps }) =>
    <div style={Object.assign({ marginRight: "1.5em" }, style)} {...otherProps}>
        {children}
    </div>;

Böylece böyle bir şey oluşturabiliriz:

<DivWithDefaults>
    Some text.
</DivWithDefaults>
<DivWithDefaults className="someClass" style={{ width: "50%" }}>
    Some more text.
</DivWithDefaults>
<DivWithDefaults id="someID" style={{ marginRight: "10px", height: "20px"}}>
    Even more text.
</DivWithDefaults>

Bu da bize sonucu verecektir:

<div style="margin-right:1.5em;">Some text.</div>
<div style="margin-right:1.5em;width50%;" class="someClass">Some more text.</div>
<div style="margin-right:10px;height:20px;" id="someID">Even more text.</div>

5
bu çözüm potansiyel Object.assign()olarak bazı istenmeyen sonuçlara yol açacak şekilde kötüye kullanılmaktadır. Bkz burada cevabı daha güvenilir bir çözüm.
Brandon

1
Yanıtınız, Object.assign () öğesini kötüye kullanmanın bir yolunu gösterir. Bu, bazı insanlar için yararlı bilgiler olabilir, ancak örneğim için geçerli değildir. Bu örnek, varsayılanı bir nesnede saklamak, mutasyona uğratmak, daha sonra mutasyona uğramış nesneyi başka bir yerde yeniden kullanmak değildir.
qel

katılmıyorum. Object.assign()cevabınızda iki ayrı kullanım yöntemini ele alırsınız . birincisi, ilk birkaç cümlede, tanımladığım kötüye kullanımın bir örneğidir (yani OP ilk codebloğunuzda önerdiğiniz şeyi yaptıysa , mutasyona uğrar {divStyle}). ikinci yol - yani, sahip olduğunuz bir işleve sarmak işe yarayacaktır, ancak cevap, 'ortak' gotcha 'değişmezliği üzerinde çalıştığınızı açıkça göstermez Object.assign()(kişisel olarak biraz düşünüyorum her varsayılan bileşen için özel bir durum bilgisi olmayan işlev yazmak için hantal).
Brandon

Ah tamam. Bu doğru. DivStyle'ı fontSize fontunu uygulamadan tekrar kullanmak isterse, önce boş nesneye ihtiyacı olacaktır. Cevabı güncelleyeceğim.
qel

Object.assign (), bir birleştirme elde etmek için en uygun yoldur :)
aldobsom

29

React Native'den farklı olarak, React'te,

<View style={[style1, style2]} />

React'te, style özelliğine geçirmeden önce stillerin tek nesnesini oluşturmamız gerekir. Sevmek:

const Header = (props) => {
  let baseStyle = {
    color: 'red',
  }

  let enhancedStyle = {
    fontSize: '38px'
  }

  return(
    <h1 style={{...baseStyle, ...enhancedStyle}}>{props.title}</h1>
  );
}

İki stili birleştirmek için ES6 Spread operatörünü kullandık . Aynı amaçla Object.assign () öğesini de kullanabilirsiniz .

Bu, tarzınızı bir varyasyonda saklamanız gerekmiyorsa da çalışır

<Segment style={{...segmentStyle, ...{height:'100%'}}}>
    Your content
</Segment>

Diziyi stile aktaramıyoruz?
heisenberg

3
Sadece son snippet'inize eklemek için {{... segmentStyle, height: '100%'}} da çalışır.
Luke Brandon Farrell

26

Object.assign()kolay bir çözümdür, ancak (şu anda) en iyi yanıtın kullanımı - vatansız bileşenler yapmak için iyi olsa da, OP'nin iki statenesneyi birleştirme hedefi için sorunlara neden olacaktır .

İki argümanla, Object.assign() aslında ilk nesneyi yerinde değiştirerek gelecekteki örneklemeleri etkileyecektir.

Ör:

Bir kutu için iki olası stil yapılandırmasını düşünün:

var styles =  {
  box: {backgroundColor: 'yellow', height: '100px', width: '200px'},
  boxA: {backgroundColor: 'blue'},
};

Bu yüzden tüm kutularımızın varsayılan 'kutu' stillerine sahip olmasını istiyoruz, ancak bazılarının üzerine farklı bir renk yazmak istiyoruz:

// this will be yellow
<div style={styles.box}></div>

// this will be blue
<div style={Object.assign(styles.box, styles.boxA)}></div>

// this SHOULD be yellow, but it's blue.
<div style={styles.box}></div>

bir Zamanlar Object.assign() çalıştırıldığında, 'styles.box' nesnesi iyi olarak değiştirilir.

Çözüm, boş bir nesneyi iletmektir Object.assign(). Bunu yaparken, geçtiğiniz nesnelerle YENİ bir nesne üretme yöntemini anlatıyorsunuz. Şöyle ki:

// this will be yellow
<div style={styles.box}></div>

// this will be blue
<div style={Object.assign({}, styles.box, styles.boxA)}></div>

// a beautiful yellow
<div style={styles.box}></div>

Yerinde mutasyon geçiren bu nesne kavramı React için kritik öneme sahiptir ve uygun kullanımı Object.assign()Redux gibi kitaplıkların kullanımı için gerçekten yararlıdır.


1
Object.assign öğesinin nasıl kötüye kullanılacağına ilişkin örnek, Object.assign öğesinin (şu anda) üst yanıtında nasıl kullanıldığına ilişkin geçerli bir gösterim değildir.
qel

teşekkürler, hangi yönünün (şu anda) bir yanlış kullanım olduğunu yansıtmak için düzenlemeler yaptı
Brandon

1
orada güzel bir kod parçası. Object.assign ({}, this.state.showStartOverBtn? {}: This.hidden, this.btnStyle)} şartları da bir cazibe gibi çalışıyor
steveinatorx

17

Dizi notaion, stilleri doğal tepkiyle birleştirmenin en iyi yoludur.

Bu, 2 Stil nesnesinin nasıl birleştirileceğini gösterir,

<Text style={[styles.base, styles.background]} >Test </Text>

bu, Style nesnesinin ve özelliğinin nasıl birleştirileceğini gösterir,

<Text style={[styles.base, {color: 'red'}]} >Test </Text>

Bu, herhangi bir yerel reaksiyon uygulaması üzerinde çalışacaktır.


2
Sorular Reactdeğil, değilReact Native
Dimitar Tsonev

React için de kullanabilirsiniz
Sasindu Lakshitha

React diziyi en başından beri desteklemiyor ve artık çalışmıyor.
witoong623

tepki henüz böyle birleştirme stilini desteklemiyor.
kızgın kivi

12

Sınıfları aşağıdaki gibi satır içi stille de birleştirebilirsiniz:

<View style={[className, {paddingTop: 25}]}>
  <Text>Some Text</Text>
</View>

8

Aslında, birleştirmenin resmi bir yolu var ve aşağıdaki gibi:

<View style={[style01, style02]} />

Ancak, küçük bir sorun var , bunlardan biri ana bileşen tarafından geçirilirse ve büyük bir sorunumuz varsa, resmi bir şekilde oluşturulmuşsa:

// The passing style02 from props: [parentStyle01, parentStyle02]

// Now:
<View style={[style01, [parentStyle01, parentStyle02]]} />

Ve bu son satırda UI hatası var, somurtkan, React Native bir dizi içinde derin bir dizi ile baş edemez. Böylece yardımcı fonksiyonumu oluşturuyorum:

import { StyleSheet } from 'react-native';

const styleJoiner = (...arg) => StyleSheet.flatten(arg);

styleJoinerİstediğim yeri kullanarak her türlü stili birleştirebilir ve stilleri birleştirebilirsiniz. hatta undefineddiğer yararsız türler bile stilin bozulmasına neden olmaz.


5

Bunun benim için en uygun olduğunu gördüm. Beklendiği gibi geçersiz kılar.

return <View style={{...styles.local, ...styles.fromProps}} />

2

React'ta bu çözümü arayanlar için, forma operatörünü stil içinde kullanmak istiyorsanız, şunu kullanmalısınız: babel-plugin-transform-object-rest-spread.

Npm modülü ile kurun ve .babelrc'nizi aşağıdaki gibi yapılandırın:

{
  "presets": ["env", "react"],
  "plugins": ["transform-object-rest-spread"]
}

Sonra gibi kullanabilirsiniz ...

const sizing = { width: 200, height: 200 }
 <div
   className="dragon-avatar-image-background"
   style={{ backgroundColor: blue, ...sizing }}
  />

Daha fazla bilgi: https://babeljs.io/docs/en/babel-plugin-transform-object-rest-spread/


2

Bunu daha da ileri götürmek için, sınıf isimlerine benzer bir yardımcı işlev oluşturabilirsiniz:

const styleRules = (...rules) => {
  return rules.filter(Boolean).reduce((result, rule) => {
    return { ...result, ...rule };
  }, {});
};

Ve sonra bileşenlerinizde şartlı olarak kullanın:

<div style={

  styleRules(
    divStyle,
    (window.innerWidth >= 768) && divStyleMd,
    (window.innerWidth < 768) && divStyleSm
  )

}>Hello World!</div>

0

Temel olarak buna yanlış bir şekilde bakıyorum. Gördüğüm kadarıyla, bu bir React'e özgü soru değil, daha çok iki JavaScript nesnesini nasıl bir araya getireceğime dair bir JavaScript sorusu değil (benzer şekilde adlandırılmış özellikleri klonlamadan).

Bu StackOverflow cevabında açıklar. İki JavaScript nesnesinin özelliklerini dinamik olarak nasıl birleştirebilirim?

JQuery'de expand yöntemini kullanabilirim.


1
CSS stilleri içeren nesnelerle çalışırken sadece nesneleri birleştirmek yeterli değildir. Birleştirme işlevi tarafından doğru sırada ele alınması gereken steno özellikleri, farklı harf kılıfları vb. Vardır. Aradığım ve henüz böyle bir işlev sağlayan bir kütüphane bulamadım.
sompylasar

İşte steno özellik genişletmesi yapan bir kütüphane: github.com/kapetan/css-shorthand-expand , ancak bu tam bir çözüm değil.
sompylasar

0

@PythonIsGreat'in söylediklerini genişletmek için, benim için yapacak küresel bir işlev oluşturuyorum:

var css = function(){
    var args = $.merge([true, {}], Array.prototype.splice.call(arguments, 0));
    return $.extend.apply(null, args);
}

Bu, nesneleri derinlemesine yeni bir nesneye genişletir ve değişken sayıda nesnenin parametre olarak kullanılmasına izin verir. Bu, böyle bir şey yapmanıza izin verir:

return(
<div style={css(styles.base, styles.first, styles.second,...)} ></div>
);

var styles = {
  base:{
    //whatever
  },
  first:{
    //whatever
  },
  second:{
    //whatever
  }
}

CSS stilleri içeren nesnelerle çalışırken düz nesne birleştirme işlevi yeterli değildir. Yukarıdaki cevaba yönelik yorumuma bakın.
sompylasar


0

Satır içi stil oluşturma yolları:

<View style={[styles.red, {fontSize: 25}]}>
  <Text>Hello World</Text>
</View>

<View style={[styles.red, styles.blue]}>
  <Text>Hello World</Text>
</View>

  <View style={{fontSize:10,marginTop:10}}>
  <Text>Hello World</Text>
</View>

3
React diziyi en başından beri desteklemiyor ve artık çalışmıyor.
witoong623
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.