Các kiểu CSS nội tuyến trong React: cách thực hiện: hover?


178

Tôi khá thích mẫu CSS nội tuyến trong React và quyết định sử dụng nó.

Tuy nhiên, bạn không thể sử dụng các công :hovercụ chọn và tương tự. Vì vậy, cách tốt nhất để thực hiện tô sáng khi di chuột trong khi sử dụng các kiểu CSS nội tuyến là gì?

Một đề xuất từ ​​#reactjs là có một Clickablethành phần và sử dụng nó như thế này:

<Clickable>
    <Link />
</Clickable>

Clickablemột hoveredtrạng thái và chuyển nó dưới dạng đạo cụ cho Liên kết. Tuy nhiên, Clickable(cách tôi thực hiện nó) kết thúc tốt đẹp Linktrong một divđể nó có thể thiết lập onMouseEnteronMouseLeavevới nó. Điều này làm cho mọi thứ hơi phức tạp một chút (ví dụ: spanđược bọc trong một divhành vi khác với span).

đó có phải là cách dễ hơn?


1
Bạn hoàn toàn đúng - cách duy nhất để mô phỏng: bộ chọn di chuột vv với kiểu nội tuyến là sử dụng onMouseEnteronMouseLeave. Về việc thực hiện chính xác điều đó - hoàn toàn phụ thuộc vào bạn. Để xem ví dụ cụ thể của bạn, tại sao không làm cho <Clickable/>trình bao bọc a span?
Chris Houghton

3
Tôi sẽ đề nghị sử dụng các biểu định kiểu bên ngoài cùng với plugin ExtractText Webpack, điều này sẽ giúp bạn chạy lâu hơn nếu bạn muốn ServerRender nếu không bạn có thể dùng thử Radium github.com/FormidableLabs/radium
abhirathore2006 17/8/2016

Hiện nay theo kiểu Component là giải pháp tốt nhất để mô phỏng tất cả các khả năng của css / SCSS trong phản ứng.
Ahmad Behzadi

Câu trả lời:


43

Tôi đang ở trong tình trạng tương tự. Thực sự thích mô hình giữ kiểu dáng trong các thành phần nhưng trạng thái di chuột có vẻ như trở ngại cuối cùng.

Những gì tôi đã làm là viết một mixin mà bạn có thể thêm vào thành phần cần trạng thái di chuột. Mixin này sẽ thêm một thuộc tính mới hoveredvào trạng thái thành phần của bạn. Nó sẽ được đặt thành truenếu người dùng di chuyển qua nút DOM chính của thành phần và đặt nó trở lạifalse nếu người dùng rời khỏi phần tử.

Bây giờ trong chức năng kết xuất thành phần của bạn, bạn có thể làm một cái gì đó như:

<button style={m(
     this.styles.container,
     this.state.hovered && this.styles.hover,
)}>{this.props.children}</button>

Bây giờ mỗi lần trạng thái của hovered trạng thái thay đổi, thành phần sẽ xuất hiện lại.

Tôi cũng đã tạo một repo hộp cát cho cái này mà tôi sử dụng để tự kiểm tra một số mẫu này. Kiểm tra xem nếu bạn muốn xem một ví dụ về việc thực hiện của tôi.

https://github.com/Sitebase/cssinjs/tree/feature-interaction-mixin


3
không phải là một giải pháp tốt để chạy lâu hơn, Radium sẽ là lựa chọn tốt hơn hoặc sử dụng biểu định kiểu bên ngoài
abhirathore2006

16
@ abhirathore2006 Radium hoạt động theo cách tương tự và câu hỏi cụ thể là làm thế nào để làm điều này mà không cần sử dụng biểu định kiểu bên ngoài
Charlie Martin

Sẽ không có ý nghĩa hơn khi sử dụng một toán tử trải vanilla?
PAT-O-MATION

102

Tôi nghĩ onMouse Entry và onMouseLeave là những cách để đi, nhưng tôi không thấy sự cần thiết phải có một thành phần trình bao bọc bổ sung. Đây là cách tôi thực hiện nó:

var Link = React.createClass({
  getInitialState: function(){
    return {hover: false}
  },
  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },
  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else {
      linkStyle = {backgroundColor: 'blue'}
    }
    return(
      <div>
        <a style={linkStyle} onMouseEnter={this.toggleHover} onMouseLeave={this.toggleHover}>Link</a>
      </div>
    )
}

Sau đó, bạn có thể sử dụng trạng thái di chuột (đúng / sai) để thay đổi kiểu của liên kết.


1
Điều này có vẻ bao trùm :hovernhưng không phải:focus
Adam T Ink

3
@AdamT mực phản ứng có một onFocussự kiện; vì vậy bạn có thể làm điều tương tự :focusnhư :hover, ngoại trừ thay vì cần onMouseEnteronMouseLeavebạn chỉ cầnonFocus
Jonathan

7
Xin lưu ý rằng phương thức này buộc thực thi trên luồng chính trong khi các sự kiện CSS điển hình được xử lý hiệu quả hơn nhiều.
Hampus Ahlgren

53

Đi dự tiệc muộn nhưng đi kèm với giải pháp. Bạn có thể sử dụng "&" để xác định kiểu cho hover nth Child, v.v.

day: {
    display: "flex",
    flex: "1",
    justifyContent: "center",
    alignItems: "center",
    width: "50px",
    height: "50px",
    transition: "all 0.2s",
    borderLeft: "solid 1px #cccccc",

    "&:hover": {
      background: "#efefef"
    },
    "&:last-child": {
      borderRight: "solid 1px #cccccc"
    }
},

1
Đây không phải là một giải pháp, câu hỏi là làm thế nào để làm điều đó với css INLINE, không phải với một biểu định kiểu riêng biệt.
Emmy

34
Anh bạn, hãy nhìn kỹ hơn. Đây là phong cách nội tuyến.
Jarosław Wlazło

15
Điều này không hoạt động với React. Bạn cần một thư viện bổ sung như các thành phần theo kiểu.
GG.

3
Nó không hoạt động với phong cách nội tuyến, ví dụ này mang lại sự nhầm lẫn. Nếu nó thực sự hoạt động, vui lòng cung cấp một ví dụ tốt hơn với thành phần đầy đủ.
Alexandre

2
Thông minh! Hoạt động như một lá bùa!
Fyodor

26

Bạn có thể sử dụng Radium - nó là một công cụ nguồn mở cho các kiểu nội tuyến với ReactJS. Nó thêm chính xác các bộ chọn bạn cần. Rất phổ biến, hãy xem thử - Radium trên npm


Tôi vừa xem qua bài đăng này, bạn sẽ triển khai Radium như thế nào trong tình huống sau đây? module.exports = React.createClass({ displayName: 'App',})

1
@Rkhayat Bạn có thể bọc nó module.exports = Radium(React.createClass({ displayName: 'App',}))hoặc gán lớp cho một giá trị và thêm trình @Radiumtrang trí bên trên nó như các tài liệu đề cập đến github.com/FormidableLabs/radium#usage
pbojinov 23/2/2016

Ngoài ra còn có thứ tuyệt vời này được gọi là CSS;)
Pixelomo

11

Hỗ trợ CSS đầy đủ chính xác là lý do số lượng thư viện CSSinJS khổng lồ này, để thực hiện điều này một cách hiệu quả, bạn cần tạo CSS thực tế chứ không phải kiểu nội tuyến. Ngoài ra các kiểu nội tuyến chậm hơn nhiều trong phản ứng trong một hệ thống lớn hơn. Tuyên bố miễn trừ trách nhiệm - Tôi duy trì JSS .


9

Made Style It - một phần - vì lý do này (những người khác không đồng ý với việc thực hiện các lib / cú pháp và kiểu dáng nội tuyến khác thiếu hỗ trợ cho các giá trị thuộc tính tiền tố). Hãy tin rằng chúng ta có thể chỉ cần viết CSS bằng JavaScript và có các thành phần hoàn toàn tự chứa HTML-CSS-JS. Với các chuỗi mẫu ES5 / ES6 bây giờ chúng ta có thể và nó cũng có thể đẹp! :)

npm install style-it --save

Cú pháp chức năng ( JSFIDDLE )

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    return Style.it(`
      .intro:hover {
        color: red;
      }
    `,
      <p className="intro">CSS-in-JS made simple -- just Style It.</p>
    );
  }
}

export default Intro;

Cú pháp JSX ( JSFIDDLE )

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    return (
      <Style>
      {`
        .intro:hover {
          color: red;
        }
      `}

        <p className="intro">CSS-in-JS made simple -- just Style It.</p>
      </Style>
    );
  }
}

export default Intro;

Tôi nhận thấy trên ví dụ Cú pháp JSX, liên kết JSFiddle có mã chính xác, nhưng ví dụ hiển thị ở đây thiếu dấu ngoặc đóng sau thẻ đóng kiểu và việc thụt lề có thể bị tắt do dấu ngoặc đơn bị thiếu.
bradleygsmith

8

Thêm vào câu trả lời của Jonathan , đây là các sự kiện để tập trung vào trạng thái tập trung và trạng thái hoạt động, và việc sử dụng onMouseOverthay vì onMouseEntersau này sẽ không bong bóng nếu bạn có bất kỳ yếu tố con nào trong mục tiêu mà sự kiện đang được áp dụng.

var Link = React.createClass({

  getInitialState: function(){
    return {hover: false, active: false, focus: false}
  },

  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },

  toggleActive: function(){
    this.setState({active: !this.state.active})
  },

  toggleFocus: function(){
    this.setState({focus: !this.state.focus})
  },

  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else if (this.state.active) {
      linkStyle = {backgroundColor: 'blue'}
    } else if (this.state.focus) {
      linkStyle = {backgroundColor: 'purple'}
    } 

    return(
      <div>
        <a style={linkStyle} 
          onMouseOver={this.toggleHover} 
          onMouseOut={this.toggleHover} 
          onMouseUp={this.toggleActive} 
          onMouseDown={this.toggleActive} 
          onFocus={this.toggleFocus}> 
          Link 
        </a>
      </div>
    )
  }

7

Đây là giải pháp của tôi bằng cách sử dụng React Hook. Nó kết hợp toán tử lây lan và toán tử ternary.

style.js

export default {
  normal:{
    background: 'purple',
    color: '#ffffff'
  },
  hover: {
    background: 'red'
  }
}

Nút.js

import React, {useState} from 'react';
import style from './style.js'

function Button(){

  const [hover, setHover] = useState(false);

  return(
    <button
      onMouseEnter={()=>{
        setHover(true);
      }}
      onMouseLeave={()=>{
        setHover(false);
      }}
      style={{
        ...style.normal,
        ...(hover ? style.hover : null)
      }}>

        MyButtonText

    </button>
  )
}


6

Đây có thể là một bản hack hay để có kiểu nội tuyến bên trong một thành phần phản ứng (và cũng sử dụng: hàm CSS hover):

...

<style>
  {`.galleryThumbnail.selected:hover{outline:2px solid #00c6af}`}
</style>

...

5

Kiểm tra kiểu chữ nếu bạn đang sử dụng React với typecript.

Dưới đây là mã mẫu cho: di chuột

import {style} from "typestyle";

/** convert a style object to a CSS class name */
const niceColors = style({
  transition: 'color .2s',
  color: 'blue',
  $nest: {
    '&:hover': {
      color: 'red'
    }
  }
});

<h1 className={niceColors}>Hello world</h1>

4

Bạn có thể sử dụng các mô-đun css như là một thay thế và các mô-đun css phản ứng bổ sung cho ánh xạ tên lớp.

Bằng cách đó, bạn có thể nhập kiểu của mình như sau và sử dụng css bình thường trong phạm vi cục bộ cho các thành phần của mình:

import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './table.css';

class Table extends React.Component {
    render () {
        return <div styleName='table'>
            <div styleName='row'>
                <div styleName='cell'>A0</div>
                <div styleName='cell'>B0</div>
            </div>
        </div>;
    }
}

export default CSSModules(Table, styles);

Dưới đây là một ví dụ mô-đun css webpack


FYI: Nếu bạn đang sử dụng Meteor, hãy xem gói này: github.com/nathantreid/meteor-css-modules . Tôi đang sử dụng nó bản thân mình có thành công lớn cho đến nay.
Xoắn ốc

Đây là một cách tuyệt vời để tạo kiểu cho các thành phần phản ứng, nhưng không hoàn toàn cung cấp cho bạn tất cả quyền kiểm soát các kiểu nội tuyến. Ví dụ: bạn không thể thay đổi :hoverkiểu trong thời gian chạy như bạn có thể với Radium hoặc một onMouseOvergiải pháp dựa trên khác
Charlie Martin

4

onMouseOver và onMouseLeave với setState thoạt đầu có vẻ như hơi quá sức đối với tôi - nhưng vì đây là cách phản ứng hoạt động, nó có vẻ là giải pháp dễ dàng và sạch sẽ nhất đối với tôi.

ví dụ, hiển thị một máy chủ css theo chủ đề, cũng là một giải pháp tốt và giữ cho các thành phần phản ứng sạch hơn.

nếu bạn không phải nối các kiểu động vào các phần tử (ví dụ như theo chủ đề), bạn không nên sử dụng các kiểu nội tuyến mà thay vào đó sử dụng các lớp css.

đây là quy tắc html / css truyền thống để giữ cho html / JSX sạch và đơn giản.


4

Cách đơn giản là sử dụng toán tử ternary

var Link = React.createClass({
  getInitialState: function(){
    return {hover: false}
  },
  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },
  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else {
      linkStyle = {backgroundColor: 'blue'}
    }
    return(
      <div>
        <a style={this.state.hover ? {"backgroundColor": 'red'}: {"backgroundColor": 'blue'}} onMouseEnter={this.toggleHover} onMouseLeave={this.toggleHover}>Link</a>
      </div>
    )
  }

1

Với việc sử dụng các móc:

const useFade = () => {
  const [ fade, setFade ] = useState(false);

  const onMouseEnter = () => {
    setFade(true);
  };

  const onMouseLeave = () => {
    setFade(false);
  };

  const fadeStyle = !fade ? {
    opacity: 1, transition: 'all .2s ease-in-out',
  } : {
    opacity: .5, transition: 'all .2s ease-in-out',
  };

  return { fadeStyle, onMouseEnter, onMouseLeave };
};

const ListItem = ({ style }) => {
  const { fadeStyle, ...fadeProps } = useFade();

  return (
    <Paper
      style={{...fadeStyle, ...style}}
      {...fadeProps}
    >
      {...}
    </Paper>
  );
};

0

Tôi sử dụng một giải pháp hack-ish khá hay cho một trong những ứng dụng gần đây hoạt động cho mục đích của mình và tôi thấy nó nhanh hơn việc viết các chức năng cài đặt di chuột tùy chỉnh trong vanilla js (mặc dù, tôi nhận ra, có thể không phải là cách thực hành tốt nhất trong hầu hết các môi trường ..) Vì vậy, trong trường hợp bạn vẫn quan tâm, ở đây đi.

Tôi tạo một phần tử cha mẹ chỉ để giữ các kiểu javascript nội tuyến, sau đó một đứa trẻ có className hoặc id mà biểu định kiểu css của tôi sẽ bám vào và viết kiểu di chuột trong tệp css chuyên dụng của tôi. Điều này hoạt động vì phần tử con chi tiết hơn nhận các kiểu js nội tuyến thông qua kế thừa, nhưng có các kiểu di chuột được ghi đè bởi tệp css.

Về cơ bản, tập tin css thực tế của tôi tồn tại cho mục đích duy nhất là giữ hiệu ứng di chuột, không có gì khác. Điều này làm cho nó khá ngắn gọn và dễ quản lý, và cho phép tôi thực hiện các thao tác nặng trong các kiểu thành phần React nội tuyến của mình.

Đây là một ví dụ:

const styles = {
  container: {
    height: '3em',
    backgroundColor: 'white',
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'stretch',
    justifyContent: 'flex-start',
    borderBottom: '1px solid gainsboro',
  },
  parent: {
    display: 'flex',
    flex: 1,
    flexDirection: 'row',
    alignItems: 'stretch',
    justifyContent: 'flex-start',
    color: 'darkgrey',
  },
  child: {
    width: '6em',
    textAlign: 'center',
    verticalAlign: 'middle',
    lineHeight: '3em',
  },
};

var NavBar = (props) => {
  const menuOptions = ['home', 'blog', 'projects', 'about'];

  return (
    <div style={styles.container}>
      <div style={styles.parent}>
        {menuOptions.map((page) => <div className={'navBarOption'} style={styles.child} key={page}>{page}</div> )}
      </div>
    </div>
  );
};


ReactDOM.render(
  <NavBar/>,
  document.getElementById('app')
);
.navBarOption:hover {
  color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"></div>

Lưu ý rằng kiểu nội tuyến "con" không có tập thuộc tính "màu". Nếu có, điều này sẽ không hoạt động vì kiểu nội tuyến sẽ được ưu tiên hơn biểu định kiểu của tôi.


0

Tôi không chắc chắn 100% nếu đây là câu trả lời, nhưng đây là mẹo tôi sử dụng để mô phỏng hiệu ứng CSS: hover với màu sắc và hình ảnh nội tuyến.

`This works best with an image`

class TestHover extends React.PureComponent {
render() {
const landingImage = {     
"backgroundImage": "url(https://i.dailymail.co.uk/i/pix/2015/09/01/18/2BE1E88B00000578-3218613-image-m-5_1441127035222.jpg)",
"BackgroundColor": "Red", `this can be any color`
"minHeight": "100%",
"backgroundAttachment": "fixed",
"backgroundPosition": "center",
"backgroundRepeat": "no-repeat",
"backgroundSize": "cover", 
"opacity": "0.8", `the hove trick is here in the opcaity slightly see through gives the effect when the background color changes`
    }

  return (
    <aside className="menu">
        <div className="menu-item">
          <div style={landingImage}>SOME TEXT</div>
        </div>
    </aside>
      ); 
  }
}
ReactDOM.render(
    <TestHover />,
  document.getElementById("root")
);

CSS:

.menu {
top: 2.70em;
bottom: 0px;
width: 100%;
position: absolute;
}

.menu-item {
cursor: pointer;
height: 100%;
font-size: 2em;
line-height: 1.3em;
color: #000;
font-family: "Poppins";
font-style: italic;
font-weight: 800;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
}

Trước khi di chuột

.menu-item:nth-child(1) {
color: white;
background-color: #001b37;
} 

Khi di chuột

.menu-item:nth-child(1):hover {
color: green;
background-color: white;
}

Ví dụ: https://codepen.io/roryfn/pen/dxyYqj?editors=0011


0
<Hoverable hoverStyle={styles.linkHover}>
  <a href="https://example.com" style={styles.link}>
    Go
  </a>
</Hoverable>

Trong đó Hoverable được định nghĩa là:

function Hoverable(props) {
  const [hover, setHover] = useState(false);

  const child = Children.only(props.children);

  const onHoverChange = useCallback(
    e => {
      const name = e.type === "mouseenter" ? "onMouseEnter" : "onMouseLeave";
      setHover(!hover);
      if (child.props[name]) {
        child.props[name](e);
      }
    },
    [setHover, hover, child]
  );

  return React.cloneElement(child, {
    onMouseEnter: onHoverChange,
    onMouseLeave: onHoverChange,
    style: Object.assign({}, child.props.style, hover ? props.hoverStyle : {})
  });
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.