【问题标题】:knockout view model properties undefined in onAfterRender functiononAfterRender 函数中未定义的淘汰视图模型属性
【发布时间】:2011-10-20 17:00:32
【问题描述】:

我有一个类似于下面的视图模型,当 onAfterRender 被 Knockout 触发时,视图模型中的函数(也称为 onAfterRender)被执行,但是 this.gridColumns、this.gridOptions 的值是未定义的,无论如何要解决这个问题?我宁愿保留对象函数而不是使用对象字面量。

我这样创建视图模型:

var model = new i2owater.viewmodels.AlarmsForViewModel(somedata);

并调用 ko.applyBindings(model);

这是我的视图模型:

viewModel = function (serverData) {
var alarmGrid = {};

function onAfterRender() {
    var that = this;
    this.alarmGrid = new i2owater.Slickgrid();

    // this.gridColumns and this.gridOptions are both undefined
    this.alarmGrid.setupGrid("#alarmsGrid", [], this.gridColumns, this.gridOptions);
};

return {
    data: data,
    tabs: tabs,
    selectedPriority: selectedPriority,
    company: company,
    zone: zone,
    rows: rows,
    alarmPeriod: alarmPeriod,
    //alarmGrid: alarmGrid,
    gridColumns: [{ id: "id", name: "ID", field: "id", sortable: true },
        { id: "date", name: "Date", field: "date", sortable: true },
        { id: "description", name: "Description", field: "description"}],
    gridOptions: {
        editable: true,
        enableCellNavigation: true,
        asyncEditorLoading: true,
        forceFitColumns: false,
        topPanelHeight: 25,
        rowHeight: 40
    }
    onAfterRender: onAfterRender
};

};

【问题讨论】:

    标签: javascript knockout.js


    【解决方案1】:

    有几种方法可以确保this 在这种情况下是正确的。

    一种选择是创建一个result 变量,将您的函数绑定到该变量,然后返回result

    var result = {
        data: data,
        tabs: tabs,
        selectedPriority: selectedPriority,
        company: company,
        zone: zone,
        rows: rows,
        alarmPeriod: alarmPeriod,
        //alarmGrid: alarmGrid,
        gridColumns: [{ id: "id", name: "ID", field: "id", sortable: true },
            { id: "date", name: "Date", field: "date", sortable: true },
            { id: "description", name: "Description", field: "description"}],
        gridOptions: {
            editable: true,
            enableCellNavigation: true,
            asyncEditorLoading: true,
            forceFitColumns: false,
            topPanelHeight: 25,
            rowHeight: 40
        }
    };
    
    result.onAfterRender = onAfterRender.bind(result);
    
    return result;
    

    否则,您可以像这样构建它,而不是返回匿名对象字面量:

    viewModel = function (serverData) {
        var alarmGrid = {};
    
        function onAfterRender() {
            var that = this;
            this.alarmGrid = new i2owater.Slickgrid();
    
            // this.gridColumns and this.gridOptions are both undefined
            this.alarmGrid.setupGrid("#alarmsGrid", [], this.gridColumns, this.gridOptions);
        };
    
        this.data = data;
        this.tabs = tabs;
        this.selectedPriority = selectedPriority;
        this.company = company;
        this.zone = zone;
        this.rows = rows;
        this.alarmPeriod = alarmPeriod;
        this.gridColumns = [{ id: "id", name: "ID", field: "id", sortable: true },
                { id: "date", name: "Date", field: "date", sortable: true },
                { id: "description", name: "Description", field: "description"}];
        this.gridOptions = {
            editable: true,
            enableCellNavigation: true,
            asyncEditorLoading: true,
            forceFitColumns: false,
            topPanelHeight: 25,
            rowHeight: 40
        };
        this.onAfterRender = onAfterRender.bind(this);
    };
    

    或使用类似 KO 1.3 ko.utils.extend 的扩展函数来扩展当前的 this,如:

    viewModel = function (serverData) {
        var alarmGrid = {};
    
        function onAfterRender() {
            this.alarmGrid = new i2owater.Slickgrid();
            this.alarmGrid.setupGrid("#alarmsGrid", [], this.gridColumns, this.gridOptions);
        };
    
        ko.utils.extend(this, {
            data: data,
            tabs: tabs,
            selectedPriority: selectedPriority,
            company: company,
            zone: zone,
            rows: rows,
            alarmPeriod: alarmPeriod,
            //alarmGrid: alarmGrid,
            gridColumns: [{ id: "id", name: "ID", field: "id", sortable: true },
                { id: "date", name: "Date", field: "date", sortable: true },
                { id: "description", name: "Description", field: "description"}],
            gridOptions: {
                editable: true,
                enableCellNavigation: true,
                asyncEditorLoading: true,
                forceFitColumns: false,
                topPanelHeight: 25,
                rowHeight: 40
            }
            onAfterRender: onAfterRender.bind(this)
        });
    };
    

    另外,使用bind 的替代方法是在构造函数的开头使用var self = this;,然后在onAfterRender 函数中使用self

    【讨论】:

    • 不确定我是否遗漏了什么,这对未定义的 this.gridColumns 有何影响?
    • 看了你的例子后,我回到了绘图板,发现我可以使用 onAfterRender(renderedNodesArray, bindingContext) 绑定上下文允许我访问 gridOptions 和 gridColumns 等。感谢您的指点。跨度>
    • 哦,是的,这是一个不错的选择,因为这种类型的函数将自动传递给 bindingContext。对于其他功能,您需要执行上述选项之一。你能关闭这个吗?
    猜你喜欢
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    • 2013-02-28
    • 2016-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    相关资源
    最近更新 更多