【问题标题】:Calling a function to change css within render() in a React Component在 React 组件中调用函数以更改 render() 中的 css
【发布时间】:2018-01-16 21:16:41
【问题描述】:

我在 React 组件中从 Spotify 返回一组信息,并希望查询返回的 JSON 并突出显示艺术家姓名中的原始搜索词。例如,如果您搜索“bus”并且返回的艺术家之一是 Kate Bush,那么这将在“Kate BUSh”中突出显示为绿色。目前我正在从 render() 中调用一个函数。但是,我得到的是:

Kate <span style="color:green">Bus</span>h

我如何让 render() 将 HTML 读取为 HTML(这样 Bus 将只是绿色)而不是呈现为文本?来自 React 组件的相关代码如下:

// Called from within render() to wrap a span around a search term embedded in the artist, album or track name
underlineSearch(displayString) {
    let searchTerm = this.props.searchTerm;

    if (displayString.indexOf(searchTerm) !== -1) {
        displayString = displayString.replace(searchTerm, '<span style="color:green">'+searchTerm+'</span>');
    }
    return displayString;
}

render() {
    return (
        <div className="Track" id="Track">
            <div className="Track-information">
                <h3>{this.underlineSearch(this.props.trackName)}</h3>
                <p>{this.underlineSearch(this.props.artistName)} | {this.underlineSearch(this.props.albumName)}</p>
            </div>
        </div>
    );
}

【问题讨论】:

  • style={{color: 'green'}} 工作吗?

标签: reactjs


【解决方案1】:

你的underlineSearch 函数需要返回 React Elements,但现在它返回的是一个字符串。您可以使用Fragment 使其工作:

// Called from within render() to wrap a span around a search term embedded in the artist, album or track name
underlineSearch(displayString) {
    const searchTerm = this.props.searchTerm;
    const indexOfSearchTerm = displayString.indexOf(searchTerm);

    let node;
    if (indexOfSearchTerm === -1) {
        node = displayString;
    } else {
        node = (
          <React.Fragment>
            {displayString.substr(0, indexOfSearchTerm)}
            <span style={{color: 'green'}}>
              {displayString.substr(indexOfSearchTerm, searchTerm.length)}
            </span>
            {displayString.substr(indexOfSearchTerm + searchTerm.length)}
          </React.Fragment>
        );
    }

    return node;
}

【讨论】:

    【解决方案2】:

    为了使您的解决方案更加可重用,您可以使用您的样式制作 underlineSearch 和包装器,以突出显示为 2 个单独的组件。更重要的是,您可以使用regex 搜索多次出现的searchTerm。发现了一个类似的 SO 问题here。我根据您的需要稍微调整了其中一个答案,但所有功劳都归功于this 用于突出显示较长文本中字符串匹配的惊人而简洁的解决方案。这是代码:

    const Match = ({ children }) => (
      <span style={{'color':'green'}}>{children}</span>
    );
    
    const HighlightMatches = ({ text, searchTerm }) => {
      let keyCount = 0;
    
      let splits = text.split(new RegExp(`\\b${searchTerm}\\b`, 'ig'));
      let matches = text.match(new RegExp(`\\b${searchTerm}\\b`, 'ig'));
      let result = [];
    
      for (let i = 0; i < splits.length; ++i) {
        result.push(splits[i]);
        if (i < splits.length - 1) {
          result.push(<Match key={++keyCount}>{matches[i]}</Match>);
        }
      }
    
      return (
        <p>{result}</p>
      );
    };
    

    然后在你的主组件中渲染你可以做的所有事情:

    render() {
       <div className="Track" id="Track">
          <div className="Track-information">
            <h3>
              <HighlightMatches text={this.props.trackName} searchTerm={this.props.searchTerm}/>
            </h3>
            <p>
              <HighlightMatches text={this.props.artistName} searchTerm={this.props.searchTerm} /> |
              <HighlightMatches text={this.props.albumName} searchTerm={this.props.searchTerm} />
          </div>
        </div>
    }
    

    对我来说,这似乎是解决问题的最类似react 的方法:)

    【讨论】:

      【解决方案3】:

      虽然你可以使用dangerouslySetInnerHTML(),但顾名思义它是极其危险的,因为它容易受到XSS攻击,例如:

      {artist: "Kate Bush<script> giveMeAllYourCookies()</script>"}
      

      您可以将 displayString 拆分为一个数组并进行渲染。

      请注意,我对underlineSearch 的实现有问题,如果匹配不止一个,将无法工作。

      class Main extends React.Component {
        underlineSearch(displayString) {
          let searchTerm = this.props.searchTerm;
          var index = 0;
          var results = [];
          var offset = 0;
          while(true) {
            const index = displayString.indexOf(searchTerm, offset);
            if(index < 0) {
              results.push(<span>{displayString.substr(offset)}</span>);
              break;
            }
            results.push(<span> {displayString.substr(offset, index)}</span>);
            results.push(<strong style={{color: 'green'}}> {displayString.substr(index, searchTerm.length)}</strong>);
            offset = index + searchTerm.length;
          }
          return results;
        }
        
        render() {
          return <div>
                      <h3>{this.underlineSearch(this.props.trackName)}</h3>
                      <p>{this.underlineSearch(this.props.artistName)} | {this.underlineSearch(this.props.albumName)}</p>
      
          </div>
        }
      
      }
      
      ReactDOM.render(<Main
        trackName="Magic Buses"
        artistName="Kate Bush"
        albumName="Kate Bush Alubm"
        searchTerm="Bus"
      />, document.getElementById('main'))
      <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='main'></div>

      【讨论】:

        猜你喜欢
        • 2018-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-23
        • 1970-01-01
        • 2016-09-08
        • 1970-01-01
        相关资源
        最近更新 更多