一些JQuery插件不仅会向DOM节点添加行为,还会对其进行更改。例如,引导开关转向
<input type="checkbox" name="my-checkbox" checked>
变成像
<div class="bootstrap-switch bootstrap-switch-wrapper bootstrap-switch-on bootstrap-switch-large bootstrap-switch-animate"> <div class="bootstrap-switch-container"> <span class="bootstrap-switch-handle-on bootstrap-switch-primary">ON</span> <label class="bootstrap-switch-label"> </label> <span class="bootstrap-switch-handle-off bootstrap-switch-default">OFF</span> <input type="checkbox" name="download-version" checked="" data-size="large" data-on-text="3" data-off-text="2.0.1"> </div> </div>
与
$("[name='my-checkbox']").bootstrapSwitch();
哪个与React不兼容:
Uncaught Error: Invariant Violation: findComponentRoot(..., .0): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser), usually due to forgetting a <tbody> when using tables or nesting <p> or <a> tags. ...<omitted>...`.
是否有推荐的技术将这些插件合并到React组件中?还是他们从根本上打破了React的假设并且无法使用它?
不,React会对在React之外修改自己的组件dom结构的任何事物产生严重的反应(haha)。这是您永远不想做的事情。推荐的解决方案是在react中复制您尝试使用jquery或类似插件进行的操作的功能。
话虽如此,对于在某些情况下您无法做到这一点的特定情况,有一种合理的方法可以做到这一点,但这实际上意味着将一些未反应的dom包裹在react中。
例:
var Example = React.createClass({ componentDidMount: function() { var $checkboxContainer = $(this.refs.checkboxContainer.getDOMNode()); var $checkbox = $('<input />').prop('type', 'checkbox'); $checkboxContainer.append($checkbox); $checkbox.bootstrapSwitch({}); }, render: function() { return ( <div> <div ref="checkboxContainer"></div> </div> ) } });
当然,现在您正在使用嵌套的div渲染组件。嵌套div第一次安装到dom时,嵌套将由jquery附加到其复选框,然后该复选框还将在其上执行我们的jquery插件。
这个特定的示例组件没有什么意义,但是您可以看到它如何集成到一个更复杂的组件中,同时仍然允许您重新渲染并响应状态更改等。您只是失去了直接对事件/修改做出反应的能力就反应而言,该复选框内的内容不存在。
现在,在上面的示例中,如果您需要一些反应逻辑来添加/删除嵌套的div,则必须在插入的div周围具有相同的逻辑,以负责重新插入复选框并使用来重新初始化该复选框。 jQuery插件。但是,由于react仅在需要时修改dom,因此除非您执行某种操作以使容器div导致将其删除/重新呈现到dom的方式进行修改,否则不会删除此插入的dom内容。这意味着您仍然可以访问该容器div等的react中的所有事件。
您还可以利用该componentDidMount函数来将事件或回调绑定到复选框本身上的特定交互。只要确保componentWillUnmount在特定情况下在组件生命周期中的正确位置或有意义的任何位置正确地取消绑定它们即可。
componentDidMount
componentWillUnmount