Come combinare più oggetti di stile in linea?


229

In React puoi creare chiaramente un oggetto e assegnarlo come stile inline. cioè. menzionato sotto.

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);

Come posso combinare più oggetti e assegnarli insieme?

Risposte:


431

Se stai usando React Native, puoi usare la notazione dell'array:

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

Controlla il mio post dettagliato sul blog su questo.


48
Purtroppo non puoi farlo in React regolare.
YoTengoUnLCD

9
Questa dovrebbe essere la risposta accettata se stai usando React-Native
calcazar

1
È possibile modificare leggermente lo stile in linea esistente aggiungendo i nomi / valori dello stile. Ad esempio,<View style={this.state.error == false ? styles.base : [styles.base, {backgroundColor: 'red'}]} />
Gürol Canbek

Per due stili statici, l'esecuzione StyleSheet.compose()al di fuori della funzione di rendering potrebbe essere più efficiente. Produrrà un nuovo foglio di stile statico che verrà inviato sul bridge solo una volta. (Questo consiglio non si applica agli stili che cambiano in fase di esecuzione, o che sono in linea invece che in un
foglio di

294

Puoi utilizzare l'operatore spread:

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

8
Ottengo "Errore di sintassi: token imprevisto", che punta al primo punto nel primo operatore di diffusione.
Izkata

@Izkata Stai facendo questo in React o Reaction Native, potresti pubblicare il tuo snippet
Nath

Reagisci, era qualcosa del tipo<div style={{ ...LEGEND_STYLE.box_base, ...{ 'background': '#123456' } }} />
Izkata

L'ho cambiato comunque per utilizzare una funzione di supporto come <div style={LEGEND_STYLE.box_gen('#123456')}comunque, quindi non è un grosso problema per me
Izkata

Funziona anche se l'oggetto ha solo una coppia chiave-valore, anche se gli operatori spread dovrebbero essere validi solo per gli iterabili! Puoi spiegare perché? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Tyler

51

Puoi farlo con Object.assign().

Nel tuo esempio, faresti:

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

Ciò unirà i due stili. Il secondo stile sostituirà il primo se sono presenti proprietà corrispondenti.

Come ha notato Brandon, dovresti usare Object.assign({}, divStyle, divStyle2)se vuoi riutilizzare divStylesenza il fontSize applicato ad esso.

Mi piace usarlo per creare componenti con proprietà predefinite. Ad esempio, ecco un piccolo componente senza stato con un valore predefinito margin-right:

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

Quindi possiamo rendere qualcosa di simile a questo:

<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>

Che ci darà il risultato:

<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
questa soluzione è potenzialmente utilizzata Object.assign()in modo improprio in un modo che porterebbe ad alcune conseguenze indesiderabili. Vedi la risposta qui una soluzione più affidabile.
Brandon

1
La tua risposta dimostra un modo per abusare di Object.assign (). Potrebbe essere un'informazione utile per alcune persone, ma non si applica al mio esempio. Questo esempio non sta memorizzando il valore predefinito in un oggetto, modificandolo e quindi riutilizzando l'oggetto mutato da qualche altra parte.
qel

disaccordo. Object.assign()nella tua risposta affronti due modi diversi di utilizzare . il primo, nelle prime frasi, è un esempio dell'abuso che ho identificato (cioè, se OP facesse quello che hai consigliato nel tuo primo codeblocco, cambierebbe {divStyle}). il secondo modo - cioè, avvolgendolo in una funzione che hai, funzionerà, ma la risposta non chiarisce che stai lavorando intorno Object.assign() al comune "gotcha" rispetto all'immutabilità (anche se personalmente penso che sia un po ' scomodo scrivere una funzione stateless personalizzata per ogni componente predefinito).
Brandon

Oh va bene. È vero. Se volesse riutilizzare divStyle senza applicare fontSize, avrebbe prima bisogno dell'oggetto vuoto. Aggiornerò la risposta.
qel

Object.assign () è di gran lunga il modo più conveniente per ottenere una concatenazione :)
aldobsom

32

A differenza di React Native, non possiamo passare array di stili in React, come

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

In React, dobbiamo creare il singolo oggetto di styles prima di passarlo alla proprietà style. Piace:

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

  let enhancedStyle = {
    fontSize: '38px'
  }

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

Abbiamo utilizzato l' operatore Spread ES6 per combinare due stili. Puoi anche usare Object.assign () per lo stesso scopo.

Funziona anche se non hai bisogno di memorizzare il tuo stile in una variabile

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

4
Solo per aggiungere al tuo ultimo snippet, anche {{... segmentStyle, height: '100%'}} funzionerà.
Luke Brandon Farrell

29

Object.assign()è una soluzione facile, ma il suo utilizzo (attualmente) migliore della risposta - anche se va bene per creare componenti senza stato, causerà problemi per l'obiettivo desiderato dell'OP di unire due stateoggetti.

Con due argomenti, Object.assign()muterà effettivamente il primo oggetto sul posto, influenzando le istanze future.

Ex:

Considera due possibili configurazioni di stile per una scatola:

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

Quindi vogliamo che tutte le nostre scatole abbiano stili 'box' predefiniti, ma vogliamo sovrascriverne alcune con un colore diverso:

// 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>

Una volta Object.assign()eseguito, l'oggetto "styles.box" viene cambiato per sempre.

La soluzione è passare un oggetto vuoto a Object.assign(). In tal modo, stai dicendo al metodo di produrre un NUOVO oggetto con gli oggetti che gli passi. Così:

// 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>

Questa nozione di oggetti che mutano sul posto è fondamentale per React e un uso corretto di Object.assign()è davvero utile per usare librerie come Redux.


1
Il tuo esempio di come utilizzare in modo improprio Object.assign non è una rappresentazione valida di come Object.assign viene utilizzato nella (attualmente) prima risposta.
qel

grazie, apportato modifiche per riflettere quale aspetto è (attualmente) un uso improprio
Brandon

1
bel pezzo di codice proprio lì. Object.assign ({}, this.state.showStartOverBtn? {}: This.hidden, this.btnStyle)} anche i condizionali funzionano come un incantesimo
steveinatorx

20

La notaion di array è il modo migliore per combinare gli stili in React Native.

Questo mostra come combinare 2 oggetti Style,

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

mostra come combinare l'oggetto Style e la proprietà,

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

Questo funzionerà su qualsiasi applicazione nativa di reazione.


2
Le domande sono per React, nonReact Native
Dimitar Tsonev il

Puoi usare lo stesso anche per React
Sasindu Lakshitha

React non supporta gli array dall'inizio e ora non funziona più.
witoong623

reagire non ancora supportare combinare stile come questo.
kiwi arrabbiato

14

In realtà, esiste un modo formale per combinare ed è come di seguito:

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

Ma c'è un piccolo problema , se uno di loro viene passato dal componente genitore ed è stato creato in modo formale combinato, abbiamo un grosso problema:

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

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

E quest'ultima riga causa un bug dell'interfaccia utente, scontroso, React Native non può gestire un array profondo all'interno di un array. Quindi creo la mia funzione di supporto:

import { StyleSheet } from 'react-native';

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

Usando my styleJoinerovunque puoi combinare qualsiasi tipo di stile e combinare stili. anche undefinedo altri tipi inutili non causano la rottura dello styling.


12

Puoi anche combinare classi con stili in linea come questo:

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

7

Ho scoperto che funziona meglio per me. Esegue l'override come previsto.

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

2

Per quelli che cercano questa soluzione in React, se vuoi usare l'operatore spread all'interno di style, dovresti usare: babel-plugin-transform-object-rest-spread.

Installalo dal modulo npm e configura il tuo .babelrc come tale:

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

Quindi puoi usare come ...

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

Maggiori informazioni: https://babeljs.io/docs/en/babel-plugin-transform-object-rest-spread/


2

Per andare oltre, potresti creare una funzione di aiuto simile a nomi di classi:

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

E poi usalo in modo condizionale nei tuoi componenti:

<div style={

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

}>Hello World!</div>

2
    const style1 = {
        backgroundColor: "#2196F3", 
    }
    
    const style2 = {
        color: "white", 
    }

    const someComponent = () => {
        return <div style={{ ...style1, ...style2 }}>This has 2 separate styles</div> 
    }
    

Notare le doppie parentesi graffe. L'operatore di diffusione è tuo amico.


1
Dovrebbe essere assolutamente accettata come risposta corretta. Salvavita!
Rob Hern,


1

Modi di styling in linea:

<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 non supporta gli array dall'inizio e ora non funziona più.
witoong623

0

Per espandere ciò che ha detto @PythonIsGreat, creo una funzione globale che lo farà per me:

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

Questo estende profondamente gli oggetti in un nuovo oggetto e consente un numero variabile di oggetti come parametri. Questo ti permette di fare qualcosa del genere:

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

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


0

È necessario unire le proprietà in object. Per esempio,

const boxStyle = {
  width : "50px",
  height : "50px"
};
const redBackground = {
  ...boxStyle,
  background: "red",
};
const blueBackground = {
  ...boxStyle,
  background: "blue",
}




 <div style={redBackground}></div>
 <div style={blueBackground}></div>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.