最近都在学习 react,但在学习过程中发现 React 的确有些坑的地方.尤其在第三方类库方面,由于 React 中的 jsx 不能对父级 DOM 修改进行修改,这个可能会影响到第三方类库的集成.
感觉不单单是不能对父级 DOM 修改的原因,还有因为其在初始化时渲染过程中仅对当前节点的 DOM 进行操作,可想而知如要面对需要修改父级节点时会很困难(尤其是像 WebEditor 这种类库),而且目前对于 React 的 WebEditor 好像也没有.
相对 AngularJS,虽然也要对某些类库进行 Directive 转换,但比 React 应该会容易转换些,不知道 大家对这个有什么看法呢?
已经研究好了几天了,感觉 React 要是做单页应用的确有难度(可能我用得不多,还要挖掘 React 的实用性).
但 React 组件化的想法的确是好的,但要切换过来的确要蛮费劲的.
1
xcv58 2015-11-20 04:51:25 +08:00
|
2
anjianshi 2015-11-20 08:11:39 +08:00
楼主可能还没熟悉 React 的思维模式。
React 中的 Component 嵌套就像建筑工地盖楼时一个个包工头层层分包。 小包工头只负责自己的这一块,不能擅自去动上级的东西。 但是他可以和上级沟通(通过上级传过来的回调),让上级进行一些调整,方便自己继续干活。 不过这在层级很多的时候会比较麻烦, 5 级承包商要和 1 级承包商联系,就得有一个回调从 1 级一直传下来。这时可以考虑用一个独立的组件,例如 Flux ,作为它们沟通的渠道。 就相当于这个工地的总负责人,单独安排了一个联络员,专门在各级承包商之间跑来跑去传递信息。 |
3
anjianshi 2015-11-20 08:16:38 +08:00
不过我用 React 时间也不长,不知道理解的对不对,哈哈
|
4
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 |
5
iwege 2015-11-20 08:42:08 +08:00
另外不可变数据集在 react 里面有重要的作用,简化 diff 流程。
|
6
nigelvon 2015-11-20 10:47:24 +08:00
楼上这些回答和楼主的问题没啥关系啊,没错有很多类库就是很难用在 React 里。不过现在 React 的第三方组件也在慢慢丰富起来,到够用的程度应该不需要太久。
|
8
zythum 2015-11-20 10:56:45 +08:00 1
我大概清楚了。你想在一个模块内使用第三方的代码。第三方的代码是强 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 。所以把所有手段都劫持调,自己实现。 |
9
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 革命性强,得自己移植适配 |
10
kenshinhu OP @zythum 这个也大概明白,现在在找些例子验证一下
但像 baidu 地图这类 js 要接入 react 的确有难度 |
11
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> } }); |
13
kenshinhu OP @zythum 对了像 componentWillUpdate 这类要 render 的方法,是不是得要更新 State 才会激发?
|
14
zythum 2015-11-20 11:22:35 +08:00
react 内部其实 调 render 只有 初始化的时候、调用 setState 的时候、外面更新 props 或者直接调用 forceUpdate 。调用 render 方法会返回目前的 vdom ,然后 react 比较现在和之前的 vdom 的差异,然后更新 dom 。
调用 setState 的时候、外面更新 props 时会通过 shouldComponentUpdate, componentWillReceiveProps componentWillReceiveProps 的方法给你中间介入的手段 ... |
15
kenshinhu OP @zythum 那要是我需要更新 dom 是,是不是直接用 forceUpdate?但这个方法的的勾会激发哪些方法? 这个好像在文档 没有明显提及... 是不是需要从源代码上分析?
|
16
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 |
17
kenshinhu OP @zythum 有 朱大大的详细解释就更加清楚了,谢谢朱大大
目前感觉用 React 还不是很上手,看来还是要做些 sideproject 因为之前都是以 angularjs 的方式来思想怎样用 React 导致 在学习 React 过程中,都带着后台应用程序的控件(如列表,CURD,地图显示等)来思考虑怎样做... |