Wie kombiniere ich mehrere Inline-Stilobjekte?

213

In React können Sie ein Objekt eindeutig erstellen und als Inline-Stil zuweisen. dh. unten genannten.

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

Wie kann ich mehrere Objekte kombinieren und zusammen zuweisen?

PythonIsGreat
quelle
Wie sehen die beiden Objekte aus?
Ryan

Antworten:

396

Wenn Sie React Native verwenden, können Sie die Array-Notation verwenden:

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

Schauen Sie sich dazu meinen ausführlichen Blog-Beitrag an.

Nick
quelle
41
Leider können Sie dies nicht in regulären Reaktionen tun.
YoTengoUnLCD
8
Dies sollte die akzeptierte Antwort sein, wenn Sie React-Native
calcazar
Sie können den vorhandenen Inline-Stil leicht ändern, indem Sie die Stilnamen / -werte hinzufügen. Zum Beispiel<View style={this.state.error == false ? styles.base : [styles.base, {backgroundColor: 'red'}]} />
Gürol Canbek
Bei zwei statischen Stilen ist es StyleSheet.compose()möglicherweise effizienter , außerhalb der Renderfunktion zu arbeiten. Es wird ein neues statisches Stylesheet erstellt, das nur einmal über die Bridge gesendet wird. (Dieser Rat gilt nicht für Stile, die sich zur Laufzeit ändern oder die inline statt in einem StyleSheet sind.)
joeytwiddle
282

Sie können den Spread-Operator verwenden:

 <button style={{...styles.panel.button,...styles.panel.backButton}}>Back</button
Nath
quelle
8
Ich erhalte die Meldung "Syntaxfehler: Unerwartetes Token", die auf den ersten Punkt im ersten Spread-Operator zeigt.
Izkata
@ Izkata Tun Sie dies in reagieren oder reagieren native, könnten Sie Ihr Snippet posten
Nath
Reagieren Sie, es war so etwas wie<div style={{ ...LEGEND_STYLE.box_base, ...{ 'background': '#123456' } }} />
Izkata
Ich habe es sowieso geändert, um eine <div style={LEGEND_STYLE.box_gen('#123456')}
Hilfsfunktion
Dies funktioniert sogar, wenn das Objekt nur ein Schlüssel-Wert-Paar hat, obwohl Spread-Operatoren nur für Iterables gültig sein sollen! Kannst du erklären warum? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Tyler
47

Sie können dies mit tun Object.assign().

In Ihrem Beispiel würden Sie Folgendes tun:

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

Dadurch werden die beiden Stile zusammengeführt. Der zweite Stil ersetzt den ersten, wenn übereinstimmende Eigenschaften vorhanden sind.

Wie Brandon bemerkte, sollten Sie verwenden, Object.assign({}, divStyle, divStyle2)wenn Sie divStyleohne die darauf angewendete Schriftgröße wiederverwenden möchten.

Ich verwende dies gerne, um Komponenten mit Standardeigenschaften zu erstellen. Hier ist zum Beispiel eine kleine zustandslose Komponente mit einer Standardeinstellung margin-right:

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

Also können wir so etwas rendern:

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

Welches wird uns das Ergebnis geben:

<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>
qel
quelle
5
Diese Lösung wird möglicherweise Object.assign()auf eine Weise missbraucht , die zu unerwünschten Konsequenzen führen würde. Sehen Sie die Antwort hier eine zuverlässigere Lösung.
Brandon
1
Ihre Antwort zeigt einen Weg, Object.assign () zu missbrauchen. Das mag für manche Menschen nützlich sein, trifft aber nicht auf mein Beispiel zu. In diesem Beispiel wird die Standardeinstellung nicht in einem Objekt gespeichert, mutiert und das mutierte Objekt dann an einer anderen Stelle wiederverwendet.
Qel
nicht zustimmen. Sie sprechen Object.assign()in Ihrer Antwort zwei verschiedene Verwendungsmöglichkeiten an. Der erste in den ersten Sätzen ist ein Beispiel für den von mir identifizierten Missbrauch (dh wenn OP das getan hat, was Sie in Ihrem ersten codeBlock empfohlen haben, würde er / sie mutieren {divStyle}). der zweite Weg - das heißt, es in einer Funktion Umwickeln wie Sie haben, funktionieren wird, aber die Antwort darauf nicht klar machen , dass Sie arbeiten rund um Object.assign() ‚s gemeinsame‚Gotcha‘wrt Unveränderlichkeit (obwohl ich persönlich denke , es ist ein wenig ist umständlich, eine benutzerdefinierte zustandslose Funktion für jede Standardkomponente zu schreiben).
Brandon
Oh ok. Das ist richtig. Wenn er divStyle wiederverwenden wollte, ohne die Schriftgröße anzuwenden, musste zuerst das leere Objekt verwendet werden. Ich werde die Antwort aktualisieren.
Qel
Object.assign () ist bei weitem der bequemste Weg, um eine Verkettung zu erreichen :)
Aldobsom
29

Im Gegensatz zu React Native können wir in React keine Reihe von Stilen übergeben, wie z

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

In React müssen wir das einzelne Objekt von Stilen erstellen, bevor wir es an die Stileigenschaft übergeben. Mögen:

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

  let enhancedStyle = {
    fontSize: '38px'
  }

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

Wir haben den ES6- Spread-Operator verwendet , um zwei Stile zu kombinieren. Sie können auch Object.assign () für denselben Zweck verwenden.

Dies funktioniert auch, wenn Sie Ihren Stil nicht in einer Variablen speichern müssen

<Segment style={{...segmentStyle, ...{height:'100%'}}}>
    Your content
</Segment>
Achyut Pokhrel
quelle
Wir können Array nicht an Style übergeben?
Heisenberg
3
Nur um Ihr letztes Snippet zu ergänzen, funktioniert {{... segmentStyle, height: '100%'}} ebenfalls.
Luke Brandon Farrell
26

Object.assign()ist eine einfache Lösung, aber die Verwendung der (derzeit) besten Antwort - obwohl dies für die Herstellung zustandsloser Komponenten in Ordnung ist, führt dies zu Problemen für das vom OP gewünschte Ziel, zwei stateObjekte zusammenzuführen.

Mit zwei Argumenten Object.assign()wird das erste Objekt tatsächlich an Ort und Stelle mutiert, was sich auf zukünftige Instanziierungen auswirkt.

Ex:

Betrachten Sie zwei mögliche Stilkonfigurationen für eine Box:

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

Wir möchten also, dass alle unsere Boxen Standard-Box-Stile haben, aber einige mit einer anderen Farbe überschreiben:

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

Nach Object.assign()der Ausführung wird das Objekt 'styles.box' endgültig geändert.

Die Lösung besteht darin, ein leeres Objekt an zu übergeben Object.assign(). Auf diese Weise weisen Sie die Methode an, ein NEUES Objekt mit den Objekten zu erstellen, die Sie übergeben. Wie so:

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

Diese Vorstellung von Objekten, die an Ort und Stelle mutieren, ist für React von entscheidender Bedeutung, und die ordnungsgemäße Verwendung Object.assign()ist für die Verwendung von Bibliotheken wie Redux sehr hilfreich.

Brandon
quelle
1
Ihr Beispiel für den Missbrauch von Object.assign ist keine gültige Darstellung der Verwendung von Object.assign in der (derzeit) Top-Antwort.
Qel
danke, Änderungen vorgenommen, um zu reflektieren, welcher Aspekt (derzeit) ein Missbrauch ist
Brandon
1
schönes Stück Code genau dort. Object.assign ({}, this.state.showStartOverBtn? {}: This.hidden, this.btnStyle)} Bedingungen funktionieren auch wie ein Zauber
steveinatorx
17

Die Array-Notation ist die beste Möglichkeit, Stile in React Native zu kombinieren.

Dies zeigt, wie 2 Stilobjekte kombiniert werden.

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

Dies zeigt, wie Style-Objekt und -Eigenschaft kombiniert werden.

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

Dies funktioniert bei jeder reaktiven nativen Anwendung.

Sasindu Lakshitha
quelle
2
Die Fragen sind für React, nichtReact Native
Dimitar Tsonev
Sie können dasselbe auch für React verwenden
Sasindu Lakshitha
React unterstützt von Anfang an kein Array und funktioniert jetzt nicht mehr.
witoong623
reagieren noch nicht unterstützen kombinieren Stil wie diesen.
wütend Kiwi
12

Sie können Klassen auch mit Inline-Styling wie folgt kombinieren:

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

Tatsächlich gibt es eine formale Möglichkeit zum Kombinieren und es ist wie folgt:

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

Es gibt jedoch ein kleines Problem : Wenn eines davon von der übergeordneten Komponente übergeben wird und auf kombinierte formale Weise erstellt wurde, haben wir ein großes Problem:

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

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

Und diese letzte Zeile führt zu einem UI-Fehler. React Native kann sicherlich nicht mit einem tiefen Array innerhalb eines Arrays umgehen. Also erstelle ich meine Hilfsfunktion:

import { StyleSheet } from 'react-native';

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

Wenn Sie my styleJoinerüberall verwenden, können Sie jede Art von Stil kombinieren und Stile kombinieren. Selbst undefinedoder andere nutzlose Typen führen nicht dazu, dass das Styling beschädigt wird.

AmerllicA
quelle
5

Ich habe festgestellt, dass dies für mich am besten funktioniert. Es überschreibt wie erwartet.

return <View style={{...styles.local, ...styles.fromProps}} />
Adrian Bartholomäus
quelle
2

Wenn Sie diese Lösung in React suchen, sollten Sie Folgendes verwenden: babel-plugin-transform-object-rest-verbreiten.

Installieren Sie es per npm-Modul und konfigurieren Sie Ihre .babelrc als solche:

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

Dann können Sie wie ...

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

Weitere Informationen: https://babeljs.io/docs/en/babel-plugin-transform-object-rest-spread/

Phönix
quelle
2

Um dies noch weiter zu führen, können Sie eine klassennamenähnliche Hilfsfunktion erstellen :

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

Und verwenden Sie es dann bedingt in Ihren Komponenten:

<div style={

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

}>Hello World!</div>
Streletss
quelle
0

Im Grunde sehe ich das falsch. Soweit ich weiß, handelt es sich hierbei nicht um eine reaktionsspezifische Frage, sondern vielmehr um eine JavaScript-Frage, wie ich zwei JavaScript-Objekte miteinander kombiniere (ohne die ähnlich benannten Eigenschaften zu beeinträchtigen).

In dieser StackOverflow-Antwort wird dies erklärt. Wie kann ich Eigenschaften von zwei JavaScript-Objekten dynamisch zusammenführen?

In jQuery kann ich die Extend-Methode verwenden.

PythonIsGreat
quelle
1
Das Zusammenführen von Objekten reicht nicht aus, wenn Sie mit Objekten arbeiten, die CSS-Stile enthalten. Es gibt Kurzschrift-Eigenschaften, verschiedene Buchstaben usw., die von der Zusammenführungsfunktion in der richtigen Reihenfolge behandelt werden sollten. Ich suche und habe noch keine Bibliothek gefunden, die eine solche Funktion bietet.
Sompylasar
Hier ist eine Bibliothek, die die Erweiterung von Shorthand-Eigenschaften durchführt: github.com/kapetan/css-shorthand-expand , aber dies ist keine vollständige Lösung.
Sompylasar
0

Um die Aussagen von @PythonIsGreat zu erweitern, erstelle ich eine globale Funktion, die dies für mich erledigt:

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

Dies erweitert die Objekte tief in ein neues Objekt und ermöglicht eine variable Anzahl von Objekten als Parameter. Auf diese Weise können Sie Folgendes tun:

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

var styles = {
  base:{
    //whatever
  },
  first:{
    //whatever
  },
  second:{
    //whatever
  }
}
timthez
quelle
Eine einfache Funktion zum Zusammenführen von Objekten reicht nicht aus, wenn Sie mit Objekten arbeiten, die CSS-Stile enthalten. Siehe meinen Kommentar zur obigen Antwort.
Sompylasar
0

Möglichkeiten des Inline-Stylings:

<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>
ihm
quelle
3
React unterstützt von Anfang an kein Array und funktioniert jetzt nicht mehr.
witoong623