使用 React 组件处理我网站上的所有文本

Posted

技术标签:

【中文标题】使用 React 组件处理我网站上的所有文本【英文标题】:Using React component to handle all text on my website 【发布时间】:2020-01-12 15:32:16 【问题描述】:

在我的 React 应用程序中,为了处理我的体育分析网站不同部分所需的所有(大部分)文本,我构建了一个组件 <PageText>。整个网站都需要文字来解释图表和统计表的细节,一般来说,整个网站都需要文字,我想把所有这些文字集中在一个地方。我认为创建一个组件会比在我的 25 到 50 个不同的容器组件中散布具有不同文本/样式等的数十个(很快数百个)<p> 标签更好。

当我打电话给<PageText> 时,它看起来像这样:

<PageText usedFor='section' pageName='TeamLanding' textNum=2 />
<PageText usedFor='section' playerName=playerFullName teamName=teamNameMarket pageName='PlayerLineups' />
<PageText usedFor='table' tableName='TeamSeason' textNum=1 />
...etc

他们采用usedFortextNum 的强制性道具,以及特定文本句子中使用的十几个(并且不断增长的)可选道具。

这里是PageText 组件的全部内容(不需要阅读全部内容,只需略读结构即可):

import  Link  from 'react-router-dom';
import React from 'react';

function PageText( usedFor, pageName, tableName, teamName, playerName, confName, chartName, scope, textNum, shotData, lineupScope, numQualTeams, sizeAdj = 1 ) 

    PageText.defaultProps = 
        sizeAdj: 1,
        textNum: 1,
        confName: 'MEGA'
    ;

    let brandBlue = '#0066CC';

    // Styles
    let sectionStyle =  fontSize: `calc($sizeAdj * 1em)`, fontStyle: 'italic', lineHeight: '1.25' ;
    let tableStyle =  fontSize: `calc($sizeAdj * 0.85em)`, fontStyle: 'italic', lineHeight: '1.25', paddingTop: '3px', margin: 0 ;
    let moreInfoStyles =  padding: '8px' ;

    // each userFor + pageName pairing has 3 different texts to show. 
    let text1, text2, text3;

    // usedFor: ['section', 'table', 'moreInfo';
    // usedFor helps with segmenting the texts into groups, and are used to style the <p> tags differently based on use of text. 
    //pageName: all of the different names of pages on my website (the parent components where text will be displayed)

    if (usedFor === 'section') 
        switch (pageName) 
            case 'TeamLanding':
                text1 = <p style=sectionStyle>The tables below display team-season statistics.</p>;
                text2 = <p style=sectionStyle><span style= color: brandBlue, fontWeight: '700' >Trial Access:</span> Team-season statistics available for trial teams only - sign up for a full subscription to access statistics for all available NCAA teams.</p>;
                text3 = <p style=sectionStyle><span style= color: brandBlue, fontWeight: '700' >Tips:</span> Tables are interactive. Table headers are hoverable (help tooltip) and clickable (sort columns). Logos and names within tables are hyperlinks useful for website navigation.</p>;
                break;
            case 'TeamScatter':
                text1 = <p style=sectionStyle>Welcome to the <span style= fontWeight: '700', color: '#0066CC' >Team-Verse Logo Plotting Application</span> - designed to visually compare teams across your choice of team stats. Use the select widgets below to toggle between seasons, to filter by conference, and to select the stats for each axis. Tips - use the "Suggested Graphs" widget to automatically select between statistical pairings for the axes that intuitively go well together, or click the "Random Axes" button to randomly select statistics for the axes. Also, toggle the "Exc/Inc Opp Stats" button to add opponent stats (stats each team allowed to opponents) to the X-Axis and Y-Axis select widgets.</p>;

                break;
            case 'TeamPlayerStats':
                text1 = <p style=sectionStyle>The tables below display player-season statistics for teamName. The large yellow/orange/red numbers show each player's <span style= color: brandBlue, fontWeight: 700 > 0 - 100 percentile rating </span>in that statistic, with 100 being the best and 0 the worst. The minutes filter below can be used to change the minumum-minutes requirement to appear in the tables below. Column headers are hoverable and include a short explanation of the stat.</p>;
                text2 = <p style=sectionStyle>The Assister-Scorer Network is a graph consisting of nodes (for each player) and links (for each pair of players) that represents the frequency with which players on teamName assist each other’s baskets - the graph helps to answer the question “Who is assisting who on this team?”</p>;
                text3 = <p style=sectionStyle><span style= color: brandBlue, fontWeight: '700' >Tips:</span> Hover a node to reveal its tooltip, or click on a node to reverse the direction of the arrows / links. Use the select to choose the number of players to display in the network graph, but beware of including too many players, which will clutter the graph. Click the Show ROP (rest of players) button to display additional nodes for bench players on the team not included in the base graph.</p>;
                break;
            case 'TeamGameRecaps':
                text1 = <p style=sectionStyle>The tables below display team-game boxscore statistics for teamName. Use the select widget below to choose between the 6 different table options. Use the table headers to sort the columns, revealing the team's best and worst games for each statistic, and helping to uncover which statistics are most correlated with winning and losing games.</p>;
                text2 = <p style=sectionStyle>The graph below displays, for the selected statistic, teamName's performance in that statistic for each game, along with their 5-game rolling average for that statistic. Note that toggling the table select widget above will update the graph select widget below with different stat options for the graph.</p>;
                break;                
            case 'PlayerLanding':
                text1 = <p style=sectionStyle>The table below displays player-season statistics and percentile ratings across all division-I players. Use the select widgets to choose amongst the 5 different tables (Offensive, Defensive, Shooting Overall, Shooting By Distance, Shooting by Court Zone), and to filter these tables for players from specific conferences. Note that statistics in the <strong>Shooting By Distance</strong> and <strong>Shooting By Court Zone</strong> tables are computed using play-by-play data that is not available for all division-I basketball games.</p>;
                text2 = <p style=sectionStyle><span style= color: brandBlue, fontWeight: '700' >Trial Access:</span> Player-season statistics available for players on trial teams only - sign up for a full subscription to access statistics for all available NCAA players. Conference filter disabled on trial accounts.</p>;
                text3 = <p style=sectionStyle><span style= color: brandBlue, fontWeight: '700' >Tips:</span> Tables are interactive. Table headers are hoverable (short stat explanations) and clickable (sortable columns), and logos and player names within the table are hyperlinks useful for navigation of the platform.</p>;
                break;
            case 'PlayerScatter':
                text1 = <p style=sectionStyle>Use the player-verse scatter plotting application to compare players across chosen statistics. Use the select widgets below to toggle the various graph filters, and to change the stats on each axis. See below for additional information.</p>;
                break;
            case 'PlayerComps':
                text1 = <p style=sectionStyle>CBB Comps is a model for computing similarity scores across players using selected metrics, where scores are computed based solely on the differences between the player's percentile rankings in the selected metrics. Choose your own metrics below, and see which players are most similar to playerName across those metrics. Similarity scores range from a minimum of -100 (zero similarity) to +100 (perfect similarity).</p>;
                break;
            case 'GameRecaps':
                text1 = <p style=sectionStyle>Each team's statistical performance is summarized below, with key game statistics grouped into 6 categories: (1) Ball Control, (2) Shooting, (3) Play Style, (4) Four Factors, (5) Scoring by Play Context, and (6) Defense. Black numbers reflect the raw stat values, and the large yellow/orange/red numbers reflect each team's <span style= color: brandBlue, fontWeight: 700 > 0 - 100 percentile rating </span>for all games played by all teams in that statistic for the season, with 100 being the best game and 0 being the worst game.</p>;
                text2 = <p style=sectionStyle>Marker Charts and Heatmaps for each team's shooting performance in this game - use the button above to the right to toggle between graph types, and to toggle the level of detail in the graphs. Note that heatmaps suffer from a small-sample-size challenge for single games.</p>;
                text3 = <p style=sectionStyle>Break down each team's shooting performance at the most detailed level. Shooting by zone / by distance graphs highlight the effectiveness and frequency of team shooting by region of the court. Use the buttons above to the right to toggle between zone and distance graphs, and to toggle the level of detail in the graphs.</p>;
                break;
            default: text1 = ``; text2 = ``; text3 = ``;
        
    

    if (usedFor === 'table') 
        switch (tableName) 
            case 'TeamSeason':
                text1 = <p style=tableStyle>Black numbers reflect stat values, and large colored numbers reflect each team's <strong>scope === 'conf' ? 'Conference' : 'Division-I' ranking</strong>> in each stat, against scope === 'conf' ? `opposing teams in the $confName` : `all Division-I teams`.</p>;
                text2 = <p style=tableStyle>Due to limited availability of play-by-play data with shooting coordinates for smaller-conference schools, <strong>only numQualTeams teams</strong> qualify for detailed shooting rankings.</p>;
                text3 = <p style=tableStyle>Large colored numbers reflect each team's <strong>conference ranking</strong> in each stat, against opposing teams in the confName.</p>;
                break;
            case 'PlayerSeason': text1 = <p style=tableStyle>Black numbers reflect stat values, and large colored numbers reflect each player's <strong>0 - 100 percentile rating</strong> for each stat, across qualifying players in the top 6 conferences.</p>; break;
            case 'TeamGame': text1 = <p style=tableStyle>Black numbers reflect stat values, and large yellow/orange/red numbers reflect the team's <strong>0 - 100 percentile rating</strong> in each game, compared to games played by all teams in that stat for the season.</p>; break;
            default: text1 = ``; text2 = ``; text3 = ``;
        
    

    if (usedFor === 'moreInfo') 
        switch (pageName) 
            case 'PlayerScatter':
                text1 =
                    (<div style=moreInfoStyles>
                        <p>The Player-Verse is a scatter plotting application for comparing players across selected statistics. tables below display team-season statistics for teams that play in the top 6 division-I basketball conferences (ACC, Big East, Big 12, Big 10, SEC, Pac12), along with the OVC (Ohio Valley Conference) temporarily. Note that column headers are hoverable (include a short explanation of the stat) and clickable (to sort the columns). Tip - click on the conference logos, team logos, and team names within the tables to navigate to various pages on the website.</p>
                        <p>The tables below display team-season statistics for teams that play in the top 6 division-I basketball conferences (Ation of the stat) and clickable (to sort the columns). Tip - click on the conference logos, team logos, and team names within the tables to navigate to various pages on the website.</p>
                        <p>The tables below display team-season statistics for teams that play in the top 6 division-I basketball conferences (ACC, Big East, Big 12, Big 10, SEC, Pac12), along with the OVC (Ohio Valley Conpages on the website.</p>
                    </div>);
                break;
            case 'ShotCharts':
                text1 =
                    (<div style=moreInfoStyles>
                        <div>
                            <div className='checkbox-btn' style= display: 'inline-block' >
                                <input
                                    style= margin: '0' 
                                    type='checkbox'
                                    className='checkbox'
                                />
                                <div className='toggler' data-label-checked='Yes' data-label-unchecked='No' />
                            </div>
                            <p style= marginLeft: '10px', display: 'inline' ><strong>Appwide vs. Chartwide: </strong> Use the "Yes/No" toggle switches to switch the scope of the select widgets and other buttons between Appwide and Chartwide. Appwide widgets (the main row of selects atop the page) control all 4 shot charts at once, whereas chartwide widgets (appear upon toggling) control their specific shot chart.</p>
                        </div>
                        <p style= marginTop: '1rem' ><strong>Att Freq & FG Pct:</strong> Our "region" chart types (Zone and Dist) include the option to display either (a) net field goal percentages (FG%), or (b) net field goal attempt frequency (FGA Freq), as the metric used for coloring the graph. FG% shot charts provide insights into how effective a team shoots from a particular location, whereas FGA Freq shot charts provide insight into how frequently a team shoots from a particular location, all relative to league average.</p>
                        <p><strong>Offense & Defense:</strong> In addition to the standard offensive shot charts, the shot visualizer is also able to generate defensive shot charts at the team level via the "Offense/Defense" button, providing unique insights into the defensive shot profile that each team allows.</p>
                        <p><strong>Navigate Faster:</strong> This helper select allows you to quickly load several shot charts that pair well together with a single click. For example, selecting "Team's Top 4 Players" will identify the 4 players on the first team (the team whose shot chart is in the top-left) with the most shot attempts, and load all 4 of their shot charts. Note that each of the options in this helper select load charts for the first team, so select the team you'd like in the first chart before using the helper select.</p>
                    </div>);
                break;
            default:
                text1 = ``;
        
    

    let returnText;
    switch (textNum) 
        case 1: returnText = text1; break;
        case 2: returnText = text2; break;
        case 3: returnText = text3; break;
        default: returnText = text1;
    

    return (
        returnText
    );


export default PageText;

简而言之,我最初认为这是一种聪明的方法,因为我正在重复将&lt;p&gt; 标签放置在我的所有容器组件中的任务。然而,目前该组件感觉好像它构建得不好,而且它似乎有很大的局限性,特别是:

它不能很好地处理不同的样式。道具sizeAdj 是用来增加文本大小的道具,但是对于所有样式都使用这样的道具没有什么意义。在我的网站上,不同的 p-tags 也需要不同的边距/填充,如果该组件的默认边距/填充与所需的不匹配,我必须将 &lt;PageText&gt; 包装在仅用于的 &lt;div&gt; 标记中边距/填充。

我并没有真正重复使用这些 p 标记。组件中的每个句子在整个应用程序中通常只使用一次或两次。

组件不处理标题。因此,我在网站上也有许多临时 p-tags 和 h-tags,用于各种标题:

    <h3 className='small-graph-header'>graph1XStat.fullName</h3>
    <h3 className='shot-chart-sub-header'>Defensive Heatmap Allowed</h3>
    <h3 style= margin: '0 0 10px 0', textDecoration: 'underline', textDecorationColor: '#0066CC' >Defensive Shooting Allowed</h3>

这些&lt;h&gt; 标记本身在我的网站中也显得凌乱,因为我有时会为它们使用类名,有时还会使用内联样式。

我的一部分认为我可以通过简单地对所有不需要悬停或其他效果的 h 和 p 标签进行内联样式来简化这一点(废弃这个组件),但我也喜欢组件的想法组织这一切。有一个更好的方法吗?我很好奇在使用 React 构建的网站上组织所有文本的首选方法通常是什么?我知道在 React 中有不同的方法可以做同样的事情,但是在这里了解一般的最佳实践会很有帮助。

编辑:通过输入并重新阅读帖子,对我来说更明显的是我喜欢将文本集中在单个组件中的想法,但我没有正确设置不同的 p -标签。我也不喜欢越来越多的道具,也不喜欢访问每个句子的复杂方式(usedFor、textNum、pageName 等道具)。

【问题讨论】:

【参考方案1】:

在我公认的有限经验中,React 旨在 a) 模块化构建 DOM 结构(您的用户界面)和 b) 管理状态。

据我所知,您正在尝试使用 Reactjs 来管理事物的外观,这属于 CSS 领域,或者广义上的样式。虽然我没有针对您的代码的建议,但处理此问题的更好方法是使用众多工具包中的一种来使 CSS 更加模块化,例如 Styled、emotion 或模块化 CSS。

那里有很多选择;为了使决定更容易,请阅读他们的介绍性文档,看看是否可以将它们逐步添加到您的项目中。您始终可以创建一个分支,如果它适合您(如果适用,您的团队)。

如果您对那里的内容感到好奇,请查看更多信息:Best of JS: CSS in JS tools

【讨论】:

以上是关于使用 React 组件处理我网站上的所有文本的主要内容,如果未能解决你的问题,请参考以下文章

错误的富文本列表并合并到其他字符串 - React 网站

位跟踪 React 组件的全局上下文

使用自定义按钮组件将 Typeform 嵌入 React

网站上的实时更新 - 每秒 1 个 ajax 是不好的做法?

如何在其他网站上嵌入 React 组件?

React:如何将 Storybook .stories 放在每个组件的目录中?