在 React 中使用 Jquery 的正确方法是啥?
Posted
技术标签:
【中文标题】在 React 中使用 Jquery 的正确方法是啥?【英文标题】:What is the right way to use Jquery in React?在 React 中使用 Jquery 的正确方法是什么? 【发布时间】:2018-12-20 14:31:17 【问题描述】:我正在尝试处理一个使用大量 jQuery 的布局/模板的项目。
我已经学会了将模板与 ReactJS 项目集成,但是,我正在寻找一个可以完全替换 jQuery 的解决方案。
我的一个解决方案是在 React 的 ComponentDidMount()
或 Render()
函数中使用 jQuery 函数。
这种方法正确吗?方法对吗?
我在下面附上了一个小例子:
import React, Component from 'react';
import '../stylesheets/commonstyles.css';
import '../stylesheets/bootstrap-sidebar.css';
import '../stylesheets/sidebar1.css';
import $ from 'jquery';
class NavBar extends Component
constructor(props)
super(props);
this.openSidebar = this.openSidebar.bind(this);
openSidebar()
console.log('hello sidebar');
componentWillMount()
$(document).ready(function ()
$('#sidebarCollapse').on('click', function ()
$('#sidebar').toggleClass('active');
);
$('.search-btn').on("click", function ()
$('.search').toggleClass("search-open");
return false;
);
);
这是我的Render
函数。
/* <!--- SIDEBAR -------> */
<div class="wrapper" style=paddingTop:60>
/* <!-- Sidebar Holder --> */
<nav id="sidebar">
<div class="sidebar-header">
<h3>Dashboard</h3>
<strong>BS</strong>
</div>
<ul class="list-unstyled components">
<li class="active">
<a href="#homeSubmenu" /*data-toggle="collapse" */ aria-expanded="false">
<i class="ti-home"></i>
Home
</a>
<ul class="collapse list-unstyled" id="homeSubmenu">
<li><a href="#">Home 1</a></li>
<li><a href="#">Home 2</a></li>
<li><a href="#">Home 3</a></li>
</ul>
</li>
<li>
<a href="#" style=color:"white">
<i class="ti-align-justify" ></i>
About
</a>
<a href="#pageSubmenu" /*data-toggle="collapse" */ aria-expanded="false" style=color:"white">
<i class="ti-text"></i>
Pages
</a>
<ul class="collapse list-unstyled" id="pageSubmenu">
<li><a href="#">Page 1</a></li>
<li><a href="#">Page 2</a></li>
<li><a href="#">Page 3</a></li>
</ul>
</li>
<li>
<a href="#" style=color:"white">
<i class="ti-paragraph"></i>
Portfolio
</a>
</li>
<li>
<a href="#" style=color:"white">
<i class="ti-control-play"></i>
FAQ
</a>
</li>
<li>
<a href="#" style=color:"white">
<i class="ti-share-alt"></i>
Contact
</a>
</li>
</ul>
</nav>
/* <!-- Page Content Holder --> */
<div id="content">
</div>
</div>
【问题讨论】:
呃,别这样。使用 jQuery 或 React,不能同时使用(与 Angular 或 Vue 相同) 否,因为这并不能明确解决 OP 的问题,也不能使他们的代码正常工作。他们需要用 React 重写 everything 并完全放弃 jQuery,但我不会在我的回答中这样做:) 正如 Jeremy 所说 - 你不应该在反应中使用 jQuery。在您的示例中,您直接在 dom 中使用 jquery 安装 js 函数。任何直接的 dom 操作通常都是一个非常糟糕的主意,最终会以糟糕的渲染告终,并且随着状态的改变而消失。 删除 Jquery,用反应状态替换你的点击切换,就像这个答案:***.com/questions/42630473/react-toggle-class-onclick @JeremyThille 评论应该是答案。此外,如果这个组件在某个时候重新挂载,它将会有尽可能多的僵尸事件使您的应用程序越来越慢。为了防止这种情况,不要忘记使用$.off
。但是你不应该使用 jQuery,因为它被许多用户认为已弃用:css3/webpack/querySelector/querySelectorAll/ReactJS/vue/....
【参考方案1】:
这种方法正确吗?方法对吗?
没有。没有一种方法是正确的,也没有正确的方法可以同时使用 jQuery 和 React/Angular/Vue。
jQuery 操作 DOM,例如,选择元素并向其中添加/删除内容。通常,它会选择现有的<div>
并设置其文本。
其他框架不操作 DOM;他们从数据中生成它,并在数据发生变化时重新生成它(例如在 Ajax 调用之后)。
问题是,jQuery 不知道 React 的存在和动作,React 也不知道 jQuery 的存在和动作。
这必然会导致应用程序损坏,充满黑客和变通方法,无法维护,更不用说您必须加载两个库而不是一个。
例如,jQuery 会选择一个<button>
并添加一个.click()
监听器;但片刻之后,React/Angular/Vue 可能会在此过程中重新生成 DOM 和按钮,从而使 jQuery 的 .click()
无效。所以你会在 *** 上问一个问题,想知道为什么你的 .click()
不起作用。你最终会添加一个肮脏的setTimeout()
hack,以便延迟jQuery 的click()
处理程序附件,直到React 重新生成你的按钮。它是你通往地狱的高速公路。
解决方案:使用 jQuery OR (React/Angular/Vue),不要同时使用。
【讨论】:
虽然您对 jQuery 和 React 可能会混淆彼此的状态是正确的,但我认为说这两者不能完全一起使用是不对的。一个应用程序可以同时拥有两者,前提是它们没有被错误地混合。请更新您的答案,杰里米。逐步将 React 添加到您的堆栈中没有任何问题。 谢谢。我当时就纳闷了。那你如何替换jquery提供的动画、饼图和其他东西呢?您可以轻松替换 jquery 的元素切换功能,但动画和其他东西,如果使用 Vanilla JS 或其他框架,将模板中的那些 jquery 函数转换为 a 并使用 react 对其进行优化。 您说“jQuery 操纵 DOM”。不,你可以告诉 jQuery 去做。您可以通过多种方式使用 jQuery。硒,答案不应该是“不”。这取决于。如果开发人员知道它在做什么,则可以同时使用这两种方法。 React 文档概述了如何正确混合库:reactjs.org/docs/integrating-with-other-libraries.html【参考方案2】:这种方法正确吗?方法对吗?
没有。不要使用 jQuery 将事件侦听器附加到由 React 创建和管理的 DOM 元素。在你的 sn-p 中使用onClick'. I could not find
#sidebarCollapse`。它可能看起来像这样。
<button id="sidebarCollapse" onClick=state => this.setState( collapsed: !state.collapsed )>Collapse</button
<nav id="sidebar">
的类可能依赖于这个状态
<nav id="sidebar" className= this.state.collapsed ? "": "active" >
您会注意到,您将正在运行的操作(例如添加删除类、属性和其他 DOM 操作)移交给 React,并简单地声明事物必须如何对状态更改做出反应。其中,如果您尝试运行 jQuery 操作,您的 UI 可能最终会处于不一致的状态。
迁移可以这样完成:用 React 替换部分 UI 元素。例如,最初你可以这样做,
<!-- rest of your existing jQuery based code -->
<header id="reactManagedNavbar">
<!-- Nothing here. React will take care of DOM Elements here -->
</header>
<!-- rest of your existing jQuery based code -->
React 端可能是这样的,
// main.js
ReactDOM.render(<MyNavBar />, document.getElementById('reactManagedNavBar'))
// MyNavBar.js could have the react components
通过这种方式,您可以逐步迁移到 React,并且仍然可以同时使用 jQuery。只是不要操纵彼此的 DOM 元素。
有时您需要在 React 组件中使用 jQuery 插件(动画、可视化图表等)。使用refs!
class MyJQueryDependingComp extends React.Component
constructor(props)
super(props);
this.myRef = React.createRef();
componentDidMount()
// this.myRef.current is the dom element. Pass it to jQuery
render()
return (
/* rest of React elements */
<div ref=this.myRef />
/* rest of React elements */
);
同样,不要在 React 中触摸 jQuery 的 DOM,反之亦然。
【讨论】:
【参考方案3】:我建议你在 webpack.config 中使用提供程序插件:
使用起来非常简单,它允许您在所有项目中使用 jquery,而无需在每个文件中都导入包:
更多信息文档: https://webpack.js.org/plugins/provide-plugin/?
所以你只需要在你的 webpack.config 文件中添加这个插件:
new webpack.ProvidePlugin(
$: 'jquery',
jQuery: 'jquery'
);
【讨论】:
【参考方案4】:jQuery 和 react 只有在它们不相互交互的情况下才能很好地结合在一起。如果您选择使用 jQuery,请仅使用 jQuery 来操作 dom,而不是两者都使用。方法是在 index.html 中的 react Js 文件之外使用 jQuery 请注意:这仅在您查询的页面首先加载时才有效
【讨论】:
这个答案可能需要一点说明,也许还有一个小代码示例。以上是关于在 React 中使用 Jquery 的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
将 HTML/CSS/JS 主题应用到 React 应用程序的正确方法
在 React Native 中使用 nativeID / 使用 RCTRootView 子视图的正确方法是啥?