从外部脚本文件附加事件侦听器

时间:2017-11-27 14:06:47

标签: javascript reactjs

我从经典HTML转到了React。

我的经典HTML有外部JavaScript,甚至在$(document).ready()上附加了听众。这不再起作用,因为在React呈现元素之前会触发$(document).ready()

要将偶数侦听器附加到React页面,我尝试使用componentDidMount(),如下所示,但偶数侦听器未被附加。

reactJS.js:

var React = require('react');
var ReactDOM = require('react-dom');


class Question extends React.Component {
    render() {
        ...
    }
}

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {data: []};
    }

    loadQuestionsFromServer() {
        $.ajax({
            url: this.props.url,
            datatype: 'json',
            cache: false,
            success: function(data) {
                this.setState({data: data});
            }.bind(this)
        })
    }

    componentWillMount() {
        this.loadQuestionsFromServer();
    }

    componentDidMount() {
        alert("component did mount");
        window.attach_listeners();
    }

    render() {
        return (
            <div>
                <h1>Hello React</h1>
                <ul>
                    {this.state.data.map(function(question, i) {
                        return <Question key={i} question={question} />
                    })}
                </ul>
            </div>
        );
    }
}

ReactDOM.render(
    <App url='/questions/test.json'/>,
    document.getElementById('app')
);

运行console.log()时有一个attach_listeners();我看到componentDidMount()确实触发了它。

如果我在控制台中手动输入window.attach_listeners();,则可以正常工作。

attach_listeners()过早触发可能吗?当弹出alert()下的componentDidMount()时,我仍然看不到该页面。但componentDidMount()会在render()我想到之后。

非常感谢任何帮助。

编辑: 请参阅下文,了解attach_listeners();的基本概念。这是一个外部JavaScript文件,据我所知,它正确加载。

function attach_listeners() {
    $('input.answer').keydown(function(event) {
        ...
    });

    $("a.answer").click(function() {
        ...
    });

    $("a.showanswer").click(function() {
        ...
    });

    $("input").focus(function(e) {
        ...
    });
};

1 个答案:

答案 0 :(得分:0)

当您注册事件时,尚未从服务器加载数据,Question组件尚未安装,因此事件根本不附加到任何事件上。

<强>解释

  1. componentWillMount中,您从服务器请求数据,这是正确的并且是推荐的,但请求是异步的,只有在从服务器返回数据时状态才会更改。
  2. componentDidMount时,数据不可用,因此DOM中呈现的唯一元素是h1ul(内部没有元素)。
  3. 您注册了componentDidMount生命周期方法中的事件,因为DOM中没有这样的元素,回调没有注册。
  4. 返回数据,调用setState方法,并使用新数据更新状态。
  5. App组件重新呈现新状态,Question组件(及其DOM元素input.answer,...)得到呈现。因为这是在您注册事件后发生的,所以回调没有附加到它们。
  6. 现在,安装所有元素。您调用attach_listeners方法并将事件侦听器正确附加到元素上。
  7. <强>解决方案:

    1. 推荐的React方式:您应该将回调作为App组件的方法,并将其传递到Question方法中的render组件中,如this
    2. attach_listeners方法调用放入componentDidUpdate。这样,您的回调肯定会被注册,但您必须注意,如果您的组件再次被重新呈现,回调将被注册两次或更多次,因为componentDidUpdate被调用后除第一次以外每次重新投降。
    3. attach_listener id个参数仅附加到id的元素。向id的每个Question添加attach_listener,并将componentDidMount来自Question组件的id与其$(document).ready(function() { $("#submenu2").click(function() { $("#window1").hide(); $("#window2").show(); }); $("#submenu1").click(function() { $("#window2").hide(); $("#window1").show(); }); });作为参数。