React 中如何使用第三方类库

2015-11-20 01:18:53 +08:00
 kenshinhu

最近都在学习 react,但在学习过程中发现 React 的确有些坑的地方.尤其在第三方类库方面,由于 React 中的 jsx 不能对父级 DOM 修改进行修改,这个可能会影响到第三方类库的集成.

感觉不单单是不能对父级 DOM 修改的原因,还有因为其在初始化时渲染过程中仅对当前节点的 DOM 进行操作,可想而知如要面对需要修改父级节点时会很困难(尤其是像 WebEditor 这种类库),而且目前对于 React 的 WebEditor 好像也没有.

相对 AngularJS,虽然也要对某些类库进行 Directive 转换,但比 React 应该会容易转换些,不知道 大家对这个有什么看法呢?

已经研究好了几天了,感觉 React 要是做单页应用的确有难度(可能我用得不多,还要挖掘 React 的实用性).

但 React 组件化的想法的确是好的,但要切换过来的确要蛮费劲的.

11500 次点击
所在节点    React
17 条回复
xcv58
2015-11-20 04:51:25 +08:00
anjianshi
2015-11-20 08:11:39 +08:00
楼主可能还没熟悉 React 的思维模式。
React 中的 Component 嵌套就像建筑工地盖楼时一个个包工头层层分包。
小包工头只负责自己的这一块,不能擅自去动上级的东西。
但是他可以和上级沟通(通过上级传过来的回调),让上级进行一些调整,方便自己继续干活。

不过这在层级很多的时候会比较麻烦, 5 级承包商要和 1 级承包商联系,就得有一个回调从 1 级一直传下来。这时可以考虑用一个独立的组件,例如 Flux ,作为它们沟通的渠道。
就相当于这个工地的总负责人,单独安排了一个联络员,专门在各级承包商之间跑来跑去传递信息。
anjianshi
2015-11-20 08:16:38 +08:00
不过我用 React 时间也不长,不知道理解的对不对,哈哈
iwege
2015-11-20 08:40:48 +08:00
先給楼主编辑器的答案:
http://react-china.org/t/react/2674/14

react 本身的概念不多,但是配合 redux 就有几个重要的概念可以理解一下,其实就是后端单一数据库+模版渲染的概念集合:
1. 单一数据源,不是说子元素改父元素,而是所有的都只能把数据放一个数据源,所有的都是更改那个数据源,类似后端的 db 的概念。
2. 永远从上到下渲染,就是子元素的状态,如果不是过程状态,永远从上到下,比如拖拽中的数据可以不用反馈,但是拖拽结果数据一定从上到下。
3. higher-order React component 负责逻辑和数据处理,普通的 component 只负责渲染。官方的 react-reply 的集成就是用的这个概念。
4. @anjianshi 说的基本上是对的,上级一般是 higher-order React component , redux 那边又叫做 container component ,是一个虚拟状态的 dom ,本身可以不用产生任何的真实 dom 。
5. 传递过程当中下级用到上级的回调,可以采用 context 来传递,具体的据说还没定下来,但是官方已经有文档了 http://facebook.github.io/react/docs/context.html
iwege
2015-11-20 08:42:08 +08:00
另外不可变数据集在 react 里面有重要的作用,简化 diff 流程。
nigelvon
2015-11-20 10:47:24 +08:00
楼上这些回答和楼主的问题没啥关系啊,没错有很多类库就是很难用在 React 里。不过现在 React 的第三方组件也在慢慢丰富起来,到够用的程度应该不需要太久。
kenshinhu
2015-11-20 10:52:06 +08:00
@nigelvon ....简单直接粗暴我喜欢
zythum
2015-11-20 10:56:45 +08:00
我大概清楚了。你想在一个模块内使用第三方的代码。第三方的代码是强 dom 控制的,没发使用 react 的 vdom 。那么就是需要自己写一个 reactClass 来封装一下。在这个 class 做特殊生命周期处理做适配。

首先 componentDidMount 和 componentWillUnmount 做这个第三方代码的 初始化 和 析构 工作,当然 html 还是写在 render 里面。
然后把 shouldComponentUpdate 直接 return false, 使得改变 props 和 states 时不会自行更新 dom 。但是一旦这么设置你就不能监听 props 和 states 改变了。所以需要自行在 componentWillUpdate 和 componentDidUpdate 里面实现。

但是 shouldComponentUpdate 并不能拦住全部,文档说了, This method is not called for the initial render or when forceUpdate is used. 所以以防万一谁 forceUpdate ,所以认为一旦 update 就直接这个模块析构再初始化
componentWillUpdate: function() { this.componentWillUnmount(); }
componentDidUpdate: function() { this.componentDidMount(); }

不知道你能不能看懂, 朱一的语文不是很好。但是应该能看懂吧....

总结就是。这个模块不能通过 react 内部逻辑去改变 dom 。所以把所有手段都劫持调,自己实现。
HowardMei
2015-11-20 10:56:51 +08:00
vuejs 作者曾经谈到过这个问题: http://vuejs.org/guide/comparison.html

"Another issue with React is that because DOM updates are completely delegated to the Virtual DOM, it ’ s a bit tricky when you actually want to control the DOM yourself (although theoretically you can, you ’ d be essentially working against the library when you do that). For applications that needs ad-hoc custom DOM manipulations, especially animations with complex timing requirements, this can become a pretty annoying restriction. "

简单来说,可直接操作 DOM 的只有 React Virtual Dom 管理器,其它库的操作都必须经过它代理,所以才有 React-Bootstrap 这种东西存在的必要,看 https://github.com/react-bootstrap/react-bootstrap/tree/master/src/utils 里面,全是拼接胶水。

想直接用第三方库,可以选择 vuejs 这类不用 virtual dom 的, reactjs 革命性强,得自己移植适配
kenshinhu
2015-11-20 11:06:53 +08:00
@zythum 这个也大概明白,现在在找些例子验证一下
但像 baidu 地图这类 js 要接入 react 的确有难度
zythum
2015-11-20 11:10:59 +08:00
撸个伪代码大概这样

React.createClass({
getDefaultProps: function() {
return {
onSelectedStyleStateChange: function () {},
contentText: ''
};
},
componentDidMount: function () {
this.states.editor = new RichEditor( React.findDOMNode(this) );
this.states.editor.on('select', onSelectedStyleStateChange);
this.states.editor.addContent(this.props.contentText);
},
componentWillUnmount: function() {
this.states.editor.destroy();
},
componentWillUpdate: function () {
return false;
},
componentWillUpdate: function() {
this.componentWillUnmount();
},
componentDidUpdate: function() {
this.componentDidMount();
},
render: function () {
return <div className="editview"></div>
}
});
zythum
2015-11-20 11:11:46 +08:00
@kenshinhu 你可以试试。反正折腾么... 233333
kenshinhu
2015-11-20 11:14:50 +08:00
@zythum 对了像 componentWillUpdate 这类要 render 的方法,是不是得要更新 State 才会激发?
zythum
2015-11-20 11:22:35 +08:00
react 内部其实 调 render 只有 初始化的时候、调用 setState 的时候、外面更新 props 或者直接调用 forceUpdate 。调用 render 方法会返回目前的 vdom ,然后 react 比较现在和之前的 vdom 的差异,然后更新 dom 。

调用 setState 的时候、外面更新 props 时会通过 shouldComponentUpdate, componentWillReceiveProps componentWillReceiveProps 的方法给你中间介入的手段 ...
kenshinhu
2015-11-20 11:32:01 +08:00
@zythum 那要是我需要更新 dom 是,是不是直接用 forceUpdate?但这个方法的的勾会激发哪些方法? 这个好像在文档 没有明显提及... 是不是需要从源代码上分析?
zythum
2015-11-20 11:50:08 +08:00
@kenshinhu 如果你是用第三方代码。不是 vdom 的。就要不要用 react 内部的方式去更新 dom 。因为会导致第三方操作 dom 的时候 dom 被 react 删掉导致悲剧。

其实 https://facebook.github.io/react/docs/component-specs.html 文档还是挺清楚的。但是都在边边角角些的。如果你要知道内部逻辑就只能看源码了。
但是基本就是下面的逻辑(如果说的不对。大大纠正)。

createElement -> componentWillMount -> render -> 生成 html -> innerHTML 填充 -> componentDidMount

props 变更 -> componentWillReceiveProps -> shouldComponentUpdate -> render -> diff(内部) -> change dom

setState -> shouldComponentUpdate -> render -> diff(内部) -> change dom

forceUpdate -> render -> diff(内部) -> change dom
kenshinhu
2015-11-20 11:58:46 +08:00
@zythum 有 朱大大的详细解释就更加清楚了,谢谢朱大大
目前感觉用 React 还不是很上手,看来还是要做些 sideproject
因为之前都是以 angularjs 的方式来思想怎样用 React
导致 在学习 React 过程中,都带着后台应用程序的控件(如列表,CURD,地图显示等)来思考虑怎样做...

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/237501

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX