集成第三方库

    我为这个示例挑选了 这个 jQuery 插件。它将无序列表转换成可以管理标签的输入框:

    转换成:

    要运行起来,我们需要引入 jQueyr、jQuery UI 和 tag-it 插件。这是运行的代码:

    选择 DOM 元素,然后调用 tagit()

    现在,我们来创建一个简单的 React 应用,它将使用 jQuery 插件:

    首先,我们要做的就是强制 Tags 组件进行单通道渲染。这是因为当 React 在实际 DOM 中添加完容器元素后,我们想将控制权交给 jQuery 。如果不做控制的话,那么 React 和 jQuery 将会操纵同一个 DOM 元素而彼此之间不知情。要实现单通道渲染,我们需要使用生命周期方法 shouldComponentUpdate,像这样:

    1. class Tags extends React.Component {
    2. shouldComponentUpdate() {
    3. return false;
    4. }
    5. ...

    这里永远都返回 false ,我们想让组件知道永远不进行重新渲染。定义 shouldComponentUpdate 对于 React 组件来说,是让其知道是否触发 render 方法。这适用于我们的场景,因为我们想使用 React 来添加 HTML 标记,添加完后就不想再依靠 React 。

    React 提供了 API 来访问实际 DOM 节点。我们需要在相应的节点上使用 ref 属性,稍后可以通过 this.refs 来访问 DOM 。componentDidMount 是最适合初始化 tag-it 插件的生命周期方法。这是因为当 React 将 render 方法返回的结果挂载到 DOM 时才调用此方法。

    上面的代码和 shouldComponentUpdate 一起使用就会使 React 渲染出有两项的 <ul> ,然后 tag-it 会其转换成标签可编辑的插件。

    假如说我们想要通过代码来为已经运行的 tag-it 插件添加新标签。这种操作将由 React 组件触发,并需要使用 jQuery API 。我们需要找到一种方式将数据传递给 Tags 组件,但同时还要保持单通道渲染。

    1. class App extends React.Component {
    2. constructor(props) {
    3. this._addNewTag = this._addNewTag.bind(this);
    4. this.state = {
    5. tags: ['JavaScript', 'CSS' ],
    6. newTag: null
    7. };
    8. _addNewTag() {
    9. this.setState({ newTag: this.refs.field.value });
    10. }
    11. render() {
    12. return (
    13. <div>
    14. <p>Add new tag:</p>
    15. <div>
    16. <input type='text' ref='field' />
    17. <button onClick={ this._addNewTag }>Add</button>
    18. </div>
    19. <Tags
    20. tags={ this.state.tags }
    21. newTag={ this.state.newTag } />
    22. </div>
    23. );
    24. }
    25. }

    我们使用内部状态来存储新添加的标签名称。每次点击按钮时,我就更新状态并触发 Tags 组件的重新渲染。但由于 shouldComponentUpdate 的存在,页面上不会有任何的更新。唯一的变化就是得到 属性的新值,另一个生命周期方法 componentWillReceiveProps 会捕获到属性的新值:

    .tagit('createTag', newProps.newTag) 是纯粹的 jQuery 代码。如果想调用第三方库的方法,componentWillReceiveProps 是个不错的选择。

    下面是 Tags 组件的完整代码:

    1. class Tags extends React.Component {
    2. componentDidMount() {
    3. this.list.tagit();
    4. }
    5. shouldComponentUpdate() {
    6. return false;
    7. }
    8. componentWillReceiveProps(newProps) {
    9. this.list.tagit('createTag', newProps.newTag);
    10. }
    11. render() {
    12. return (
    13. <ul ref='list'>
    14. {
    15. this.props.tags.map(
    16. (tag, i) => <li key={ i }>{ tag } </li>
    17. )
    18. }
    19. </ul>
    20. );
    21. }
    22. };