为什么在Blaze事件处理程序中未定义`this`?

时间:2017-01-05 12:26:04

标签: javascript meteor meteor-blaze

我陷入了对实习消息的回复函数:email reply-sending函数工作正常(如果我在代码中手动选择to字段),但是当我选择时我失败了要回复的邮件,要使用我的contact-messages自动选择email集合(字段Meteor.methods)中的电子邮件。

用几句话说:

  • var to = "bob@bob.com" =>确定
  • var to = this.email =>没有抓住价值

以下是我在回复表单提交和方法

上的活动

事件(无法捕获var to = this.email

Template.ContactReplyModal.events({
    'click .send-message':function(e) {
        e.preventDefault();
        Meteor.call('replyMessage', this._id, function(error) {
            if(error) {
                Bert.alert({
                    title: 'Error',
                    message: error.reason,
                    type: 'danger'
                });
            } else {
                var to = this.email;
                var from = "my@mail.com";
                var subject = $('#reply-subject').val();
                var message = $('#reply-message').val();

                if(message != '' && subject != '') {
                    Meteor.call('sendEmailContact', to, from, subject, message, function (error) {
                        if(error) {
                            Bert.alert({
                                title: 'Error',
                                message: error.reason,
                                type: 'danger'
                            });
                        } else {
                            $('#reply-message').val('');
                            $('#reply-subject').val('');
                            Bert.alert({
                                title: 'Success',
                                message: 'Message sended.',
                                type: 'success'
                            });
                        }
                    });
                } else {
                    Bert.alert({
                        title: 'Error',
                        message: 'Message error.',
                        type: 'danger'
                    });
                }
            }
        });
    },
    //Close events for ContactReplyModal
    'click .close-login': ()=> {
        Session.set('nav-toggle-contactreply', '');
    },
    'click .modal-overlay-contactreply': ()=> {
        Session.set('nav-toggle-contactreply', '');
    }
});

方法(此处使用replyMessage功能)

//Contact Method
Meteor.methods({
    insertMessage: function(message) {
        ContactMessages.insert(message);
    },
    openMessage: function(messageId) {
        ContactMessages.update({_id: messageId}, {$set: {new: false}});
    },
    replyMessage: function(messageId) {
        ContactMessages.findOne({_id: messageId});
    },
    deleteMessage: function(messageId) {
        ContactMessages.remove({_id: messageId});
    }
});

修改

变量email与箭头功能的绑定不起作用。

所以也许这是捕获变量的问题?

我无法阅读console.log (this);console.log (this.email);undefined

以下是我的留言集。

"_id": "6c3478WugEajr6zaw",
  "name": "bob",
  "email": "bob@bob.com",
  "message": "This is a try.",
  "submitted": "2017-01-05T15:19:04.642Z",
  "new": true

我真的不明白,因为下面这个事件适用于openMessage方法(因此正确的信息可以从其他人那里正确识别)

//CLIENTSIDE  
  'click .open-message':function() {
            Meteor.call('openMessage', this._id, function(error) {
                if(error) {
                    Bert.alert({
                        title: 'Error',
                        message: error.reason,
                        type: 'danger'
                    });
                }
            });
        }

//SERVERSIDE

    Meteor.methods({
        insertMessage: function(message) {
            ContactMessages.insert(message);
        },
        openMessage: function(messageId) {
            ContactMessages.update({_id: messageId}, {$set: {new: false}});
        },
        replyMessage: function(message) {
            ContactMessages.findOne({_id: message});
        },
        deleteMessage: function(messageId) {
            ContactMessages.remove({_id: messageId});
        }
    });

编辑2

如所提出的,在模板& js链接到。该方法已经展示,也是收集数据的一个例子。

模板(contact-reply.html

<template name="ContactReply">
    <h3>Reply</h3>
    <h3>To: {{email}}</h3>
    <input class="form-control" type="text" name="reply-subject" id="reply-subject" placeholder="Subject"/>
    <br>
    <textarea class="form-control" name="reply-message" id="reply-message" rows="6"></textarea>
    <br>
    <button class="btn btn-success send-message">Send</button>

</template>


<template name="ContactReplyModal">
    <div class="contactreply-modal {{$.Session.get 'nav-toggle-contactreply'}}">
        <i class="fa fa-close close-login"></i>
        <h3>Send a reply</h3>
        {{> ContactReply}}
    </div>
    <div class="modal-overlay-contactreply"></div>
</template>

js模板(contact-reply.js

import './contact-reply.html';




Template.ContactReplyModal.events({
    'click .send-message':function(e) {
        e.preventDefault();
        console.log(this);
        Meteor.call('replyMessage', this._id, (error) => {
            if(error) {
                Bert.alert({
                    title: 'Error',
                    message: error.reason,
                    type: 'danger'
                });
            } else {
                console.log (this.email);
                const to = this.email;
                var from = "my@mail.com";
                var subject = $('#reply-subject').val();
                var message = $('#reply-message').val();

                if(message != '' && subject != '') {
                    Meteor.call('sendEmailContact', to, from, subject, message, (error) => {
                        if(error) {
                            Bert.alert({
                                title: 'Error',
                                message: error.reason,
                                type: 'danger'
                            });
                        } else {
                            $('#reply-message').val('');
                            $('#reply-subject').val('');
                            Bert.alert({
                                title: 'Success',
                                message: 'Message sended.',
                                type: 'success'
                            });
                        }
                    });
                } else {
                    Bert.alert({
                        title: 'Error',
                        message: 'Message error.',
                        type: 'danger'
                    });
                }
            }
        });
    },
    //Close events for ContactReplyModal
    'click .close-login': ()=> {
        Session.set('nav-toggle-contactreply', '');
    },
    'click .modal-overlay-contactreply': ()=> {
        Session.set('nav-toggle-contactreply', '');
    }
});

2 个答案:

答案 0 :(得分:1)

首先,确保data context是正确的非常重要。 模板中的每个元素都使用特定的数据上下文进行渲染。如果您在模板事件处理程序中定位它们,则数据上下文将通过this提供给处理程序。

如果您定位未由当前模板呈现的元素(例如,由第三方库呈现或属于子模板),则不会进行数据竞赛,这是导致您的数据上下文为undefined)的原因。

修复后,假设数据上下文(外部函数的this)确实是您在事件处理程序中所期望的(即,具有email字段),您需要使其可用于回调。您可以在局部变量中捕获它并使其在闭包中可用,或者用箭头函数进行词汇绑定:

Template.ContactReplyModal.events({
    'click .send-message':function(e) {
        e.preventDefault();
        console.log(this); // to make sure that it is what you are expecting.
        Meteor.call('replyMessage', this._id, (e) => { // note the arrow function
            if(e) {
                // ...
            } else {
                const to = this.email;
                // ...
                if(message != '' && subject != '') {
                    Meteor.call('sendEmailContact', to, from, subject, message, (e) => {
                        if(e) {
                            // ...
                        } else {
                            // ...
                        }
                    });
                } else {
                    // ...
                }
            }
        });
    },
    // ...
});

但是,使用多个嵌套方法调用似乎不是一个好主意。在单个方法调用中完成所有操作可能会更好。

答案 1 :(得分:0)

您无法使用此模板事件访问模板变量,您可以通过事件中的第二个参数访问它们,这是您的代码,希望它能够正常工作

Template.ContactReplyModal.events({
'click .send-message'(e, instance) {
e.preventDefault();
Meteor.call('replyMessage', this._id, function(error) {
    if(error) {
        Bert.alert({
            title: 'Error',
            message: error.reason,
            type: 'danger'
        });
    } else {
        var to = instance.email;
        var from = "my@mail.com";
        var subject = $('#reply-subject').val();
        var message = $('#reply-message').val();

        if(message != '' && subject != '') {
            Meteor.call('sendEmailContact', to, from, subject, message, function (error) {
                if(error) {
                    Bert.alert({
                        title: 'Error',
                        message: error.reason,
                        type: 'danger'
                    });
                } else {
                    $('#reply-message').val('');
                    $('#reply-subject').val('');
                    Bert.alert({
                        title: 'Success',
                        message: 'Message sended.',
                        type: 'success'
                    });
                }
            });
        } else {
            Bert.alert({
                title: 'Error',
                message: 'Message error.',
                type: 'danger'
            });
        }
    }
});

}, });