【问题标题】:jQuery Selectors with React is ok?带有 React 的 jQuery 选择器可以吗?
【发布时间】:2017-10-20 14:16:24
【问题描述】:

我知道混合使用 jQuery 和 ReactJS 是不可取的,因为 ReactJS 不知道 jQuery 对 DOM 所做的任何修改。但是,如果您只使用 jQuery 来轻松方便地查询 DOM 和查找节点,而将所有 DOM 编辑留给 ReactJS 会怎样。除了 jQuery 是一个大库之外,还有其他缺点吗?

一个示例用例是在安装下拉菜单组件时设置事件侦听器,以检查用户是否单击了菜单外的任何位置,以便菜单可以关闭。 jQuery .parents() 方法是一种非常方便的方法来检查单击目标是否是菜单容器元素的子元素。在ReactJSvanilla JavaScript 中是否有一种简单的方法可以做到这一点?

这里是这个例子的代码示例:

handleClick = e => {
  const element = $(e.target)
  if( !( element.parents('.menu').length || element.hasClass('menu'))) {
    this.setState({ menuOpen: false })
  }
}

componentWillUpdate (nextProps, nextState) {
  if(nextState.menuOpen && !this.state.menuOpen) {
    document.addEventListener('click', this.handleClick, false)
  } else if (!nextState.menuOpen && this.state.menuOpen) {
    document.removeEventListener('click', this.handleClick, false)
  }
}

【问题讨论】:

标签: javascript jquery reactjs


【解决方案1】:

是的,我想说在 React 中使用 jQuery 有一些缺点。

VDOM diffing 算法会混淆

这是你提到的。是的,如果您只使用 read-only 属性会很好,但除非您针对的是较旧的浏览器,否则 document.querySelector 的重量会更轻。

您引入的每个依赖项,尤其是像图书馆这样大的依赖项,都应该经过仔细审查。详情请见the website obesity epedemic

此外,“我只将它用于阅读,让 React 完成其余工作”的想法会给您的代码增加一层明显的混乱,我们将在下一个示例中看到。

你放弃了 React 的模式

在我看来,更大的问题是放弃 React 的模式。用一句话来描述 React,我会说:

React 是一个基于组件的库,用于生成源自state 输入的 HTML、CSS 和 JavaScript 功能。

假设我有一个简单的UserProfile 组件。该组件将包含一些关于用户的数据,包括接收或不接收推送通知的开关:

// Please note this is simplified pseudo-code, and will likely not work
class UserProfile extends Component {
  state = {
    name: 'Bob',
    profilePic: 'someurl.com/profile-pic',
    isReceivingNotifications: false
  }

  updateReceivingNotifications = () => {
    this.setState({ isReceivingNotifications: !this.state.isReceivingNotifications })
  }

  render() {
    const { name, profilePic, isReceivingNotifcations } = this.state;
    return (
      <div>
        <h2>{name}</h2>
        <img src={profilePic} />
        <input type="checkbox" checked={isReceivingNotifications} onChange={this.updateReceivingNotifications} />
      </div>
    );
  }
}

很简单,组件的表示是从组件的状态派生出来的。如果isReceivingNotifcations 为真,则复选框将被选中。

让我们用所提议的设计模式来看看这个相同的例子:

class UserProfile extends Component {
  state = {
    name: 'Bob',
    profilePic: 'someurl.com/profile-pic',
    isReceivingNotifications: false
  }

  componentDidMount() {
    const checkBox = document.getElementById('my-checkbox');
    const that = this;
    // Use a regular function to bind the this context to the checkbox instead of component
    checkBox.addEventListener('change', function() {
      if (this.checked) {
         that.setState({ isReceivingNotifcations: true });
      } else {
         that.setState({ isReceivingNotifcations: false });
      }
    });
  }

  render() {
    const { name, profilePic, isReceivingNotifcations } = this.state;
    return (
      <div>
        <h2>{name}</h2>
        <img src={profilePic} />
        <input
          type="checkbox"
          checked={isReceivingNotifications}
          id="my-checkbox"
          />
       </div>
    );
  }
}

第一个更简洁,无论你如何使用 jQuery 或任何你将使用的 DOM 操作库来格式化它。

这是一个人为的例子,但每次我在现实生活中看到这个版本时,都会变得一团糟。

最后,为什么?

花点时间学习一下 React 设计模式。我建议thinking in React。 jQuery 应该是最后的手段,因为我认为您使用 React 是有原因的。

一个例外是你在 React 中使用的 jQuery 库

在这种情况下,除了重写库之外,您别无选择。正如this article 中强调的那样,您应该编写一个包装器组件以使其符合 React。

【讨论】:

  • 当然,对于所有用户交互都包含在该组件中的组件,DOM 查询是不必要的。但是,如果您需要一个组件来感知在它之外发生的点击怎么办?您可以找到一些 HOC 来检查点击是否发生在外部,但它们可能自己在内部使用 DOM 查询。也许不是 JQuery,而是一个 DOM 查询。更重要的是,如果需求更加复杂怎么办?如果我需要知道点击是否发生在当前组件之外的某个特定组件中怎么办?反应实现会很复杂
  • 我会说这是使用不太常见的场景来证明更常见的场景。不太常见的情况是组件之外的组件操作(模式、菜单等)。现在,我们有 portals 来处理这个确切的场景。
  • 我们使用 React 是因为它是主流并且在很大程度上是炒作,我认为
【解决方案2】:

我是否正确地说您的问题归结为:查询浏览器 DOM 以获取您将在 React 中使用的信息是否可以? 由于虚拟 DOM 总是与浏览器 DOM 同步,所以在浏览器 DOM 中进行只读查找肯定不错。事实上,如果您想添加交互性或用户事件处理,您有时需要在浏览器 DOM 而不是虚拟 DOM 上执行此操作。

那么至于使用哪个库:除了jQuery,还有minifiedjs之类的更轻量级的选择。

【讨论】:

  • 是的,这是正确的,我正在检查使用类似 jQuery 的库进行浏览器 DOM 查找是否存在任何缺陷。你的建议是,如果有的话,没有任何主要的,所以没关系。我会等着看是否有人可以提出其他任何建议,否则我会将您的标记为答案。谢谢!
  • 这里需要注意的一点是,React 已经有一个API for accessing DOM,你应该更喜欢它而不是像 jQuery 这样的东西。
猜你喜欢
  • 1970-01-01
  • 2012-08-08
  • 1970-01-01
  • 1970-01-01
  • 2015-11-20
  • 2014-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多