V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kenshinhu
V2EX  ›  React

React 中如何使用第三方类库

  •  
  •   kenshinhu · 2015-11-20 01:18:53 +08:00 · 11492 次点击
    这是一个创建于 3310 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

    不过这在层级很多的时候会比较麻烦, 5 级承包商要和 1 级承包商联系,就得有一个回调从 1 级一直传下来。这时可以考虑用一个独立的组件,例如 Flux ,作为它们沟通的渠道。
    就相当于这个工地的总负责人,单独安排了一个联络员,专门在各级承包商之间跑来跑去传递信息。
    anjianshi
        3
    anjianshi  
       2015-11-20 08:16:38 +08:00
    不过我用 React 时间也不长,不知道理解的对不对,哈哈
    iwege
        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
    iwege
        5
    iwege  
       2015-11-20 08:42:08 +08:00
    另外不可变数据集在 react 里面有重要的作用,简化 diff 流程。
    nigelvon
        6
    nigelvon  
       2015-11-20 10:47:24 +08:00
    楼上这些回答和楼主的问题没啥关系啊,没错有很多类库就是很难用在 React 里。不过现在 React 的第三方组件也在慢慢丰富起来,到够用的程度应该不需要太久。
    kenshinhu
        7
    kenshinhu  
    OP
       2015-11-20 10:52:06 +08:00
    @nigelvon ....简单直接粗暴我喜欢
    zythum
        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 。所以把所有手段都劫持调,自己实现。
    HowardMei
        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 革命性强,得自己移植适配
    kenshinhu
        10
    kenshinhu  
    OP
       2015-11-20 11:06:53 +08:00
    @zythum 这个也大概明白,现在在找些例子验证一下
    但像 baidu 地图这类 js 要接入 react 的确有难度
    zythum
        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>
    }
    });
    zythum
        12
    zythum  
       2015-11-20 11:11:46 +08:00
    @kenshinhu 你可以试试。反正折腾么... 233333
    kenshinhu
        13
    kenshinhu  
    OP
       2015-11-20 11:14:50 +08:00
    @zythum 对了像 componentWillUpdate 这类要 render 的方法,是不是得要更新 State 才会激发?
    zythum
        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 的方法给你中间介入的手段 ...
    kenshinhu
        15
    kenshinhu  
    OP
       2015-11-20 11:32:01 +08:00
    @zythum 那要是我需要更新 dom 是,是不是直接用 forceUpdate?但这个方法的的勾会激发哪些方法? 这个好像在文档 没有明显提及... 是不是需要从源代码上分析?
    zythum
        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
    kenshinhu
        17
    kenshinhu  
    OP
       2015-11-20 11:58:46 +08:00
    @zythum 有 朱大大的详细解释就更加清楚了,谢谢朱大大
    目前感觉用 React 还不是很上手,看来还是要做些 sideproject
    因为之前都是以 angularjs 的方式来思想怎样用 React
    导致 在学习 React 过程中,都带着后台应用程序的控件(如列表,CURD,地图显示等)来思考虑怎样做...
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2784 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 68ms · UTC 13:16 · PVG 21:16 · LAX 05:16 · JFK 08:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.