Як поєднувати кілька об’єктів стилю вбудованого стилю?


214

У React ви можете чітко створити об'єкт і призначити його як стиль вбудованого. тобто. згадані нижче.

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

Як я можу поєднати кілька об'єктів та призначити їх разом?


Як виглядають два об’єкти?
Райан

Відповіді:


399

Якщо ви використовуєте React Native, ви можете використовувати позначення масиву:

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

Ознайомтесь з моєю детальною публікацією в блозі про це.


41
На жаль, ви не можете цього зробити в звичайному React.
YoTengoUnLCD

8
Це має бути прийнята відповідь, якщо ви використовуєте React-Native
calcazar

Ви можете трохи змінити існуючий стиль вбудованого тексту, додавши імена стилів / значення. Наприклад,<View style={this.state.error == false ? styles.base : [styles.base, {backgroundColor: 'red'}]} />
Gürol Canbek

Для двох статичних стилів виконання StyleSheet.compose()поза функцією візуалізації може бути ефективнішим. Він створить нову статичну таблицю стилів, яка буде надіслана через міст лише один раз. (Ця порада не поширюється на стилі, які змінюються під час виконання, або які є вбудованими, а не в StyleSheet.)
joeytwiddle

282

Ви можете використовувати оператор спред:

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

8
Я отримую "Помилка синтаксису: Несподіваний маркер", вказуючи на першу крапку в першому операторі поширення.
Ізката

@Izkata Ви робите це в реагуванні або реагуєте на місцевих людей, чи можете ви опублікувати свій фрагмент
Nath

Реагуйте, це було щось на кшталт<div style={{ ...LEGEND_STYLE.box_base, ...{ 'background': '#123456' } }} />
Ізката

Я все-таки змінив це, щоб використовувати помічницьку функцію, як і в <div style={LEGEND_STYLE.box_gen('#123456')}будь-якому випадку, тому для мене це не велика справа
Ізката

Це навіть працює, якщо в об'єкта є лише одна пара ключ-значення, хоча оператори розповсюдження повинні бути дійсними лише для ітерабелів! Чи можете ви пояснити, чому? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Тайлер

47

Ви можете це зробити за допомогою Object.assign().

У вашому прикладі ви зробите:

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

Це об'єднає два стилі. Другий стиль замінить перший, якщо є відповідні властивості.

Як зазначив Брендон, вам слід скористатися, Object.assign({}, divStyle, divStyle2)якщо ви хочете повторно використовувати їх divStyleбез застосованого до нього шрифту.

Мені подобається використовувати це для створення компонентів із властивостями за замовчуванням. Наприклад, ось невеликий компонент без стану з замовчуванням margin-right:

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

Тож ми можемо зробити щось подібне:

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

Що дасть нам результат:

<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
це рішення потенційно може неправильно Object.assign()використовувати таким чином, що призведе до небажаних наслідків. Дивіться відповідь тут більш надійне рішення.
Брендон

1
Ваша відповідь демонструє спосіб неправильного використання Object.assign (). Це може бути корисною інформацією для деяких людей, але це не стосується мого прикладу. Цей приклад - це не збереження за замовчуванням об’єкта, його вимкнення, потім повторне використання мутованого об'єкта деінде.
qel

не згоден. Ви звертаєтесь до двох окремих способів використання Object.assign()у своїй відповіді. перше, в перших кількох реченнях, є прикладом неправильного використання, яке я виявив (тобто, якщо ОП зробив те, що ви порадили у своєму першому codeблоці, він / вона мутуватиме {divStyle}). другий спосіб - тобто, перетворивши його на функцію, як у вас є, буде працювати, але відповідь не дає зрозуміти, що ви працюєте над Object.assign() незмінною wrt незмінності wrt (хоча особисто я думаю, що це мало громіздко написати спеціальну функцію без стану для кожного компонента за замовчуванням).
Брендон

О, добре. Це правда. Якщо він хотів повторно використовувати divStyle, не застосовуючи fontSize, спочатку знадобиться порожній об’єкт. Я оновлю відповідь.
qel

Object.assign () - це найзручніший спосіб досягти конкатенації :)
aldobsom

29

На відміну від React Native, ми не можемо передавати масив стилів у React, як

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

У React нам потрібно створити єдиний об’єкт стилів, перш ніж передати його до властивості стилю. Подібно до:

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

  let enhancedStyle = {
    fontSize: '38px'
  }

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

Ми використовували оператор Spread ES6 для поєднання двох стилів. Ви також можете використовувати Object.assign () для тих же цілей.

Це також працює, якщо вам не потрібно зберігати свій стиль у варі

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

Ми не можемо передати масив стилю?
heisenberg

3
Просто для додання останнього фрагмента {{... segmentStyle, висота: '100%'}} також буде працювати.
Люк Брендон Фаррелл

26

Object.assign()це просте рішення, але використання (на даний момент) основної відповіді на це - хоч і чудово для створення компонентів без громадянства, спричинить проблеми для бажаної мети ОП - об'єднання двох stateоб'єктів.

За допомогою двох аргументів Object.assign()фактично буде вимкнено перший об'єкт на місці, впливаючи на майбутні моменти.

Наприклад:

Розглянемо два можливих конфігурації стилю для поля:

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

Отже, ми хочемо, щоб усі наші поля мали стилі "box" за замовчуванням, але ми хочемо перезаписати деякі з іншого кольору:

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

Після Object.assign()виконання об'єкт 'styles.box' змінюється назавжди.

Рішення - передати порожній об’єкт Object.assign(). Роблячи це, ви говорите про спосіб створення НОВОГО об'єкта з об'єктами, які ви передаєте йому. Так:

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

Це поняття об'єктів, що мутують на місці, є критичним для React, і правильне використання Object.assign()дуже корисне для використання таких бібліотек, як Redux.


1
Ваш приклад того, як неправильно використовувати Object.assign, не є дійсним уявленням про те, як Object.assign використовується в (на даний момент) верхній відповіді.
qel

спасибі, внесені зміни, щоб відобразити, який аспект є (зараз) зловживанням
Брендон

1
приємний фрагмент коду прямо там. Object.assign ({}, this.state.showStartOverBtn? {}: This.hidden, this.btnStyle)} умовні умови також працюють як шарм
steveinatorx

17

Масив notaion - це найкращий спосіб поєднання стилів у реакції рідного.

Тут показано, як поєднувати 2 об'єкти стилю,

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

це показує, як поєднувати об’єкт і властивість стилю,

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

Це буде працювати над будь-яким природним додатком, що реагує.


2
ReactReact Native
Димитар Цонев

Ви можете використовувати те ж саме для React
Сасінду Лакшита

React не підтримує масив спочатку, і тепер він більше не працює.
witoong623

реагувати ще не підтримують комбінований стиль, як це.
сердитий ківі

12

Ви також можете комбінувати класи з вбудованим стилем так:

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

8

Насправді існує формальний спосіб поєднання, і це як нижче:

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

Але є невелике питання , якщо один з них передається материнським компонентом, і він був створений комбінованим формальним способом, у нас є велика проблема:

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

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

І в цьому останньому рядку виникає помилка у користувальницькому інтерфейсі, похмура, React Native не може мати справу з глибоким масивом всередині масиву. Тому я створюю свою помічну функцію:

import { StyleSheet } from 'react-native';

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

Використовуючи моє styleJoinerмісце, ви можете комбінувати будь-який тип стилю та комбінувати стилі. навіть undefinedчи інші непотрібні типи не спричиняють порушення стилізації.



2

Для тих, хто шукає це рішення в React, Якщо ви хочете використовувати оператор розповсюдження всередині стилю, слід використовувати: babel-plugin-transform-object-rest-rest-spread.

Встановіть його за допомогою модуля npm та налаштуйте свій .babelrc як такий:

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

Тоді ви можете використовувати як ...

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

Більше інформації: https://babeljs.io/docs/en/babel-plugin-transform-object-rest-spread/


2

Щоб зробити це ще більше, ви можете створити допоміжну функцію, схожу на назви класів :

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

А потім використовуйте його умовно у своїх компонентах:

<div style={

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

}>Hello World!</div>

0

Тому я в основному дивлюся на це неправильно. З того, що я бачу, це не конкретно-реактивне питання, а більше питання JavaScript в тому, як я поєдную два об'єкти JavaScript разом (без клобірування аналогічно названих властивостей).

У цій відповіді StackOverflow це пояснюється. Як я можу динамічно об'єднати властивості двох об’єктів JavaScript?

У jQuery я можу використовувати метод розширення.


1
Просто об'єднання об’єктів недостатньо при роботі з об'єктами, що містять стилі CSS. Існують скорочені властивості, різні обкладинки літер тощо, з якими слід обробляти у правильному порядку функцією злиття. Я шукаю та ще не знайшов бібліотеки, яка б надала таку функцію.
sompylasar

Ось бібліотека, яка виконує скорочення властивостей скорочення: github.com/kapetan/css-shorthand-expand , але це не є повним рішенням.
сомпіласар

0

Щоб розгорнути те, що сказав @PythonIsGreat, я створюю глобальну функцію, яка зробить це для мене:

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

Це глибоко розширює об'єкти в новий об'єкт і дозволяє змінювати кількість об'єктів як параметри. Це дозволяє зробити щось подібне:

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

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

Функції простого об'єднання об'єктів недостатньо при роботі з об'єктами, що містять стилі CSS. Дивіться мій коментар до відповіді вище.
sompylasar


0

Способи стильної стилізації:

<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 не підтримує масив спочатку, і тепер він більше не працює.
witoong623
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.