วิธีการรวมวัตถุสไตล์แบบอินไลน์หลายรายการ?


214

ในการตอบสนองคุณสามารถสร้างวัตถุอย่างชัดเจนและกำหนดให้เป็นสไตล์แบบอินไลน์ กล่าวคือ ระบุไว้ด้านล่าง

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

ฉันจะรวมหลายวัตถุและกำหนดให้เข้าด้วยกันได้อย่างไร


วัตถุทั้งสองมีลักษณะอย่างไร
Ryan

คำตอบ:


399

หากคุณใช้ React Native คุณสามารถใช้สัญลักษณ์อาร์เรย์:

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

ลองดูโพสต์บล็อกของฉันโดยละเอียดเกี่ยวกับสิ่งนี้


41
น่าเศร้าที่คุณไม่สามารถทำสิ่งนี้ในปฏิกิริยาปกติ
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

@Izkata คุณกำลังทำสิ่งนี้ด้วยการตอบโต้หรือโต้ตอบกับชาวพื้นเมืองคุณสามารถโพสต์ตัวอย่างของคุณได้ไหม
Nath

ทำปฏิกิริยาเหมือนกัน<div style={{ ...LEGEND_STYLE.box_base, ...{ 'background': '#123456' } }} />
Izkata

ฉันเปลี่ยนมันต่อไปเพื่อใช้ฟังก์ชั่นตัวช่วยเช่น<div style={LEGEND_STYLE.box_gen('#123456')}นี้ดังนั้นมันจึงไม่ใช่เรื่องใหญ่สำหรับฉันเลย
Izkata

วิธีนี้ใช้ได้ผลถ้าวัตถุมีคู่คีย์ - ค่าเพียงคู่เท่านั้นแม้ว่าตัวดำเนินการสเปรดควรจะใช้ได้กับ iterables เท่านั้น! คุณอธิบายได้ไหม 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()ในทางที่ผิดซึ่งจะนำไปสู่ผลที่ไม่พึงประสงค์บางอย่าง ดูคำตอบที่นี่เป็นทางออกที่เชื่อถือได้มากขึ้น
Brandon

1
คำตอบของคุณแสดงให้เห็นถึงวิธีการใช้ Object.assign () ในทางที่ผิด นั่นอาจเป็นข้อมูลที่มีประโยชน์สำหรับบางคน แต่มันไม่ได้นำไปใช้กับตัวอย่างของฉัน ตัวอย่างนี้ไม่ได้เก็บค่าเริ่มต้นในวัตถุกลายพันธุ์แล้วนำวัตถุที่กลายพันธุ์ไปใช้ที่อื่น
qel

ไม่เห็นด้วย คุณพูดถึงการใช้สองวิธีObject.assign()ในคำตอบของคุณ ประโยคแรกในประโยคแรก ๆ นั้นเป็นตัวอย่างของการใช้ผิดวัตถุประสงค์ที่ฉันระบุ (เช่นถ้า OP ทำตามที่คุณแนะนำในcodeบล็อกแรกเขา / เธอจะกลายพันธุ์{divStyle}) วิธีที่สอง - คือห่อไว้ในฟังก์ชั่นที่คุณมีจะทำงาน แต่คำตอบไม่ได้ทำให้มันชัดเจนว่าคุณกำลังทำงานรอบ Object.assign() 's ทั่วไป 'gotcha' WRT เปลี่ยนไม่ได้ ( แต่ส่วนตัวผมคิดว่ามันเป็นเพียงเล็กน้อย ยุ่งยากในการเขียนฟังก์ชั่นไร้สัญชาติที่กำหนดเองสำหรับทุกองค์ประกอบเริ่มต้น)
แบรนดอน

โอวตกลง. นั่นเป็นเรื่องจริง ถ้าเขาต้องการนำ divStyle กลับมาใช้ใหม่โดยไม่ต้องใช้ fontSize มันจะต้องมีวัตถุว่างก่อน ฉันจะอัปเดตคำตอบ
qel

Object.assign () เป็นวิธีที่สะดวกที่สุดในการทำ concatenation :)
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>
  );
}

เราใช้ตัวดำเนินการ ES6 เพื่อรวมสองลักษณะ คุณยังสามารถใช้Object.assign ()เพื่อจุดประสงค์เดียวกันได้

สิ่งนี้ยังใช้งานได้หากคุณไม่ต้องการจัดเก็บสไตล์ของคุณในรูปแบบ

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

เราไม่สามารถส่งผ่านไปยังสไตล์?
ไฮเซนเบิร์ก

3
เพียงเพิ่มไปยังข้อมูลโค้ดสุดท้ายของคุณ {{... segmentStyle, height: '100%'}} ก็จะทำงานเช่นกัน
ลุคแบรนดอนฟาร์เรล

26

Object.assign()เป็นคำตอบที่ง่าย แต่การใช้คำตอบสูงสุด (ปัจจุบัน) ของมัน - ในขณะที่ดีสำหรับการสร้างส่วนประกอบไร้สัญชาติจะทำให้เกิดปัญหาสำหรับวัตถุประสงค์ที่ต้องการของ OP ในการรวมสองstateวัตถุ

ด้วยสองข้อโต้แย้งObject.assign()จะกลายพันธุ์วัตถุแรกในสถานที่ที่มีผลต่อการสร้างอินสแตนซ์ในอนาคต

Ex:

พิจารณาการกำหนดค่าสไตล์ที่เป็นไปได้สองแบบสำหรับกล่อง:

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

ดังนั้นเราต้องการให้กล่องทั้งหมดของเรามีสไตล์ 'กล่อง' เริ่มต้น แต่ต้องการเขียนทับกล่องด้วยสีที่แตกต่างกัน:

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

ความคิดของวัตถุที่กลายพันธุ์ในสถานที่นี้มีความสำคัญสำหรับการตอบสนองและการใช้งานที่เหมาะสมObject.assign()จะมีประโยชน์มากสำหรับการใช้ห้องสมุดเช่น Redux


1
ตัวอย่างของคุณเกี่ยวกับการใช้ Object.assign ในทางที่ผิดไม่ใช่การแสดงที่ถูกต้องของวิธีการใช้ Object.assign ในคำตอบยอดนิยม (ปัจจุบัน)
qel

ขอบคุณทำการแก้ไขเพื่อสะท้อนให้เห็นถึงลักษณะที่ผิด (ปัจจุบัน) การใช้งานที่ผิดพลาด
Brandon

1
โค้ดที่ดีตรงนั้น Object.assign ({}, this.state.showStartOverBtn? {}: this.hidden, this.btnStyle)} เงื่อนไขยังทำงานเหมือนมีเสน่ห์
steveinatorx

17

Array notaion เป็นวิธีที่ดีที่สุดในการรวมสไตล์เข้ากับ Native Native

สิ่งนี้แสดงวิธีการรวมวัตถุ 2 สไตล์เข้าด้วยกัน

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

สิ่งนี้แสดงวิธีรวมวัตถุสไตล์และคุณสมบัติเข้าด้วยกัน

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

วิธีนี้จะใช้ได้กับแอปพลิเคชันที่แปลมาเอง


2
คำถามสำหรับReactไม่ใช่React Native
Dimitar

คุณสามารถใช้ React เหมือนกันได้
Sasindu Lakshitha

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

และบรรทัดสุดท้ายนี้ทำให้เกิดข้อผิดพลาด UI อย่างแท้จริง React Native ไม่สามารถจัดการกับอาร์เรย์ที่อยู่ลึกภายในอาร์เรย์ได้ ดังนั้นฉันจึงสร้างฟังก์ชันผู้ช่วยของฉัน:

import { StyleSheet } from 'react-native';

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

ด้วยการใช้ของฉันstyleJoinerทุกที่คุณสามารถรวมสไตล์ใดก็ได้และรวมสไตล์เข้าด้วยกัน แม้กระทั่งundefinedหรือประเภทไร้ประโยชน์อื่น ๆ ไม่ก่อให้เกิดการแบ่งสไตล์


5

ฉันพบว่ามันใช้งานได้ดีที่สุดสำหรับฉัน มันแทนที่ตามที่คาดไว้

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

2

สำหรับผู้ที่มองหาวิธีแก้ปัญหานี้ใน React หากคุณต้องการใช้ตัวดำเนินการสเปรดภายในสไตล์คุณควรใช้: babel-plugin-transform-object-rest-spread

ติดตั้งโดยโมดูล npm และกำหนดค่า .abelrc ของคุณเช่น:

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

โดยพื้นฐานแล้วฉันกำลังดูสิ่งนี้ในทางที่ผิด จากสิ่งที่ฉันเห็นนี่ไม่ใช่คำถามเฉพาะ React คำถาม JavaScript มากขึ้นฉันจะรวมสองวัตถุ JavaScript เข้าด้วยกันได้อย่างไร (โดยไม่ต้องปิดกั้นคุณสมบัติที่มีชื่อคล้ายกัน)

ใน StackOverflow คำตอบนี้จะอธิบายมัน ฉันจะรวมคุณสมบัติของวัตถุ JavaScript สองรายการแบบไดนามิกได้อย่างไร

ใน jQuery ฉันสามารถใช้วิธีการขยายได้


1
การรวมวัตถุเพียงอย่างเดียวไม่เพียงพอเมื่อทำงานกับวัตถุที่มีสไตล์ CSS มีคุณสมบัติชวเลข, ปลอกตัวอักษรที่แตกต่างกัน ฯลฯ ซึ่งควรได้รับการจัดการในลำดับที่ถูกต้องโดยฟังก์ชั่นการผสาน ฉันกำลังมองหาและยังไม่พบห้องสมุดที่มีฟังก์ชั่นดังกล่าว
sompylasar

นี่คือไลบรารีที่ใช้สำหรับการขยายคุณสมบัติแบบย่อ: github.com/kapetan/css-shorthand-expandแต่นี่ไม่ใช่โซลูชันที่สมบูรณ์
sompylasar

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.