Javascript 未捕获类型错误:视图不是构造函数

Javascript 未捕获类型错误:视图不是构造函数,javascript,jquery,backbone.js,Javascript,Jquery,Backbone.js,我有一个未捕获的类型错误:UserRegisterView不是构造函数。我不理解这个错误。我查看了所有代码,但没有找到它。 对不起,我英语不好,请帮帮我 谢谢你的回答 已更新 UserRegisterView在这里 var UserRegisterView=Backbone.View.extend({ 型号:用户, el:'表格', 活动:{ '单击输入[id=“infoWeek”]:'infoWeek', '单击输入[id=“infoMonth”]:'infoMonth' }, infoWee

我有一个未捕获的类型错误:UserRegisterView不是构造函数。我不理解这个错误。我查看了所有代码,但没有找到它。 对不起,我英语不好,请帮帮我

谢谢你的回答

已更新

UserRegisterView在这里

var UserRegisterView=Backbone.View.extend({
型号:用户,
el:'表格',
活动:{
'单击输入[id=“infoWeek”]:'infoWeek',
'单击输入[id=“infoMonth”]:'infoMonth'
},
infoWeek:function(){
这个.el.find(“#dayOfMonth”).hide();
这个。render();
},
infoMonth:function(){
此.el.find(“#dayOfWeek”).hide();
这个。render();
}
});
var AddUserView=Backbone.View.extend({
el:$(“.page”),
活动:{
'单击#saveUser':'saveUser'
},
saveUser:function(){
var user=新用户();
user.set({
用户名:$(“#用户名”).val(),
lastName:$(“#lastName”).val(),
regNumber:$(“#regNumber”).val(),
密码:$(“#密码”).val(),
部门名称:$(“#部门名称”).val(),
电子邮件:$(“#电子邮件”).val(),
角色:$(“#角色”).val()
});
user.save();
if(document.getElementById('isOpen')。选中){
user.set(“isOpen”,$(“#isOpen”).val(“1”);
user.save();
}否则{
user.set(“isOpen”,$(“#isOpen”).val(“0”);
user.save();
}
if(document.getElementById('dayOfWeek')。选中){
user.set(“dayOfWeek”,$(“#dayOfWeek”).val();
user.save();
}else if(document.getElementById('dayOfMonth')。选中){
user.set(“dayOfMonth”,$(“#dayOfMonth”).val();
user.save();
}
$(“#用户名”).val(“”);
$(“#firstName”).val(“”);
$(“#lastName”).val(“”);
$(“#regNumber”).val(“”);
$(“#密码”).val(“”);
$(“#部门名称”).val(“”);
$(“#email”).val(“”);
$(“#isOpen”).val(“”);
$(“#dayOfWeek”).val(“”);
$(“#月日”).val(“”);
},
render:function(){
var=这个;
var template=handlebar.compile(UserRegister);
var myHtml=template(that.model.toJSON());
那.$el.html(myHtml);
归还这个;
}
});
返回{
AddUserView:AddUserView,
UserRegisterView:UserRegisterView
};
});
路由器用户函数

定义([
“jquery”,
“下划线”,
"骨干",,
“把手”,
“旋转”,
“应用程序/模型/登录模型”,
“应用程序/视图/登录视图”,
'应用程序/视图/用户注册视图'
],函数($,
_,
骨干,
车把,
纺纱机,
登录,
LoginView,
用户注册视图
) {
var Router=Backbone.Router.extend({
路线:{
“搜索”:“搜索”,
'login':'login',
‘旅行’:‘旅行’,
“用户”:“用户”,
“菜单”:“菜单”,
“家”
},
用户:函数(){
disposeView(新的UserRegisterView().render());
}
util.js上的dispose.view

功能配置视图(视图){
Backbone.View.prototype.close=函数(){
这个。解除绑定();
此.undelegateEvents();
};
/*Şu anki viewi yok et*/
if(this.currentView!==未定义){
this.currentView.close();
}
/*耶尼视图奥卢图尔*/
this.currentView=视图;
this.currentView.delegateEvents();
返回此.currentView;
}
发生了什么事 您的
UserRegisterView
模块返回一个包含两个构造函数的对象

使用此模块时,您得到的是上面的对象

define([
    // ...
    'app/views/UserRegisterView'
], function(
    // ...
    UserRegisterView // value of the return in the module
) {
因此,您通过调用它
UserRegisterView
来误导自己,因为它不是构造函数,而是包含构造函数的对象

要以当前模块设置方式获取新的
UserRegisterView
视图实例,您需要这样调用它:

var userView = new UserRegisterView.UserRegisterView();
或创建
AddUserView
实例:

var addView = new UserRegisterView.AddUserView();
解决
  • 拆分模块,每个视图构造函数一个
  • 更改名称,使其至少不会产生误导(如
    UserViewsModule

其他改进 也就是说,可以对主干代码进行其他改进

var UserRegisterView = Backbone.View.extend({
    // that's useless (if not used) and not a view property.
    // model: User,

    // don't use `el` like that, especially when using the view as a shared Constructor
    el: '#form',
    events: {
        'click input[id="infoWeek"]': 'onInfoWeekClick',
        'click input[id="infoMonth"]': 'onInfoMonthClick'
    },

    initialize: function() {
        // Cache jQuery object of the view's element
        this.$dayOfMonth = this.$("#dayOfMonth");
        this.$dayOfMonth = this.$("#dayOfMonth");
        // also use the shortcut function instead of `this.$el.find()`
    }

    onInfoWeekClick: function(e) {
        this.$dayOfMonth.hide();
        // calling render here is useless unless your using it as a parent
        // view, where the child view overrides the render function.
    },

    onInfoMonthClick: function(e) {
        this.$dayOfMonth.hide();
    }
});
disposeView
功能可以简化:

function disposeView(view) {
    var current = this.currentView;
    if (current) current.close();
    current = this.currentView = view;
    current.delegateEvents();
    return current;
}
不要每次调用函数时都更改默认主干视图原型。相反,只需添加一次函数

_.extend(Backbone.View.prototype, {
    close: function() {
        this.unbind();
        this.undelegateEvents();
    },
    // any other function you want to add can go here.
});
在另一个回答中,我将详细介绍

您已经在使用jQuery,所以不要使用JavaScript DOM API
document.getElementById('isOpen')
和jQuery选择器
$('isOpen')

我对下面的视图做了一些改进。花点时间自己创建一些实用函数(如
reset
getValues
),以简化代码流程并封装复杂性

var AddUserView = Backbone.View.extend({
    el: $(".page"),
    events: {
        'click #saveUser': 'saveUser'
    },
    // compile the template once while creating the view class
    template: Handlebars.compile(UserRegister),

    // get the selector string out of the code and place them in one place
    // easy to change and maintain.
    fields: {
        username: "#username",
        firstName: "#firstName",
        lastName: "#lastName",
        regNumber: "#regNumber",
        password: "#password",
        deparmentName: "#deparmentName",
        email: "#email",
        isOpen: "#isOpen",
        dayOfWeek: "#dayOfWeek",
        dayOfMonth: "#dayOfMonth",
    },

    render: function() {
        this.$el.html(this.template(this.model.toJSON()));
        // cache jQuery object of every field once after a render
        this.field = _.reduce(this.fields, function(fields, selector, key) {
            fields['$' + key] = this.$(selector);
            return fields;
        }, {}, this);
        return this;
    },
    reset: function() {
        // reset all the fields once without repeating code.
        _.each(this.field, function($field) {
            $field.val("");
        });
        return this;
    },
    getValues: function(keys) {
        // get the value of multiple fields returned in a nice object
        // ready to be sent to a Backbone model.
        return _.reduce(keys, function(data, key) {
            data[key] = this.field[key].val();
            return data;
        }, {}, this);
    },

    saveUser: function() {
        var field = this.field,
            user = new User(this.getValues([
                'username',
                'lastName',
                'regNumber',
                'password',
                'departmentName',
                'email',
                'role',
            ]));

        user.set({ isOpen: field.$isOpen.is(':checked') });

        if (field.$dayOfWeek.is(':checked')) {
            user.set("dayOfWeek", field.$dayOfWeek.val());
        } else if (field.$dayOfMonth.is(':checked')) {
            user.set("dayOfMonth", field.$dayOfMonth.val());
        }

        user.save();
        this.reset();
    },
});
在下面的代码片段中,您将上下文(
this
)放入一个局部变量中。我看到了很多,我可以说90%的时候我在堆栈溢出问题上看到它,这是没有意义的。它明显地尖叫着复制粘贴

请告诉我,您看到您正在将
这个
放入
那个
,然后在整个函数中使用
那个
,然后仍然返回
这个

在动态创建的回调中需要对象时,将上下文放入局部变量非常有用

render: function() {
    var that = this; // this is available here
    setTimeout(function() {
        // here this is not available.
        that.handleCallback();
    }, 10);
    // here we are in the same context as the first line.
    return this;
}

我在任何地方都看不到
UserRegisterView
。还有,为什么对
user.save()
调用那么多?为什么混合使用
getElementById
调用和jQuery调用?很抱歉,编辑错误。我能在一次保存中保存多个文本框吗()方法?和yh混合了一点,但这对我来说很容易。这是个问题吗?但是在
retur中仍然有
UserView:UserRegisterView
render: function() {
    var that = this;
    // ...
    that.$el.html(myHtml);
    return this;
}
render: function() {
    var that = this; // this is available here
    setTimeout(function() {
        // here this is not available.
        that.handleCallback();
    }, 10);
    // here we are in the same context as the first line.
    return this;
}