React-如何实现页面范围的操作?

时间:2019-03-29 10:55:24

标签: javascript reactjs

我需要实现一个全页面词典(针对站点中的每个页面),这样,当悬停在词典中出现的单词时,旁边会出现一个带有定义的小框。

一种方法是将网站中的每个文本都包裹在一个循环文本的组件上,并添加所需的效果。

但是,使用jQuery,我可以通过遍历页面中所有文本的全页操作来减少工作量。

  1. 在React中有一种合适的方法来实现页面范围的操作吗?

  2. 是否有可能(即推荐)混合使用react和jQuery

谢谢

1 个答案:

答案 0 :(得分:1)

一个被动的方法概述:

  1. 具有顶级组件Dictionary,该组件呈现Provider,公开了一个功能,该功能允许使用上下文的其他组件在字典中查找单词。

  2. 创建一个组件Explanation,该组件使用Dictionary提供的上下文,并检查该单词的描述是否存在,如果存在,则会在悬停时呈现弹出框。

示例:

const tokenize = (text, dictionary) => {
    return text
        .split(/(\b\w+\b)/gi)
        .map(word => {
            const description = dictionary[word];

            if (!description) return word;

            return (
                <span title={description} className="dashed">
                    {word}
                </span>
            );
        })
        .reduce((acc, current, idx) => {
            if (typeof acc[acc.length - 1] === 'string' && typeof current === 'string') {
                acc[acc.length - 1] += current;
                return acc;
            }

            acc.push(current);
            return acc;
        }, []);
};

const DictionaryContext = createContext({getDescription: () => null});

// holds the words and exposed function to look a word up
const Dictionary = ({words, children}) => {
    const getTokens = useCallback(text => tokenize(text, words), [words]);
    return <DictionaryContext.Provider value={{getTokens}}>{children}</DictionaryContext.Provider>;
};

// gets the explanation from the context and renders it as a title
const Explanation = ({children}) => {
    const {getTokens} = useContext(DictionaryContext);
    if (!children) return null;
    return getTokens(children);
};

实时示例:

Edit 0xvj2o2k4n

但是您仍然需要将整个文本包装到一个这样做的组件中。这是由于反应如何进行。它是声明性的,它描述了在编译时显示数据的每种可能方式。但是实际上,我发现这是更好的设计,因为您应该将文本明确标记为可能具有解释。

  

是否有可能(即推荐)混合使用react和jQuery

这是可能的,但由于概念根本不同,因此我将尽量避免这种情况。 React会保留DOM的内部表示形式,如果它是由外部例如通过jQuery会产生难以预料的意外结果。 React和jQuery绝对不合适。

编辑:

这是相同代码的更强大的版本(感谢@Elia Weiss),它支持:

  1. Unicode
  2. 多个单词短语
  3. 处理非文本对象

Edit n3qz2r80lj