【问题标题】:AngularJS service parent separate referenceAngularJS服务父单独参考
【发布时间】:2015-10-26 03:30:15
【问题描述】:

我正在使用 AngularJS 服务来存储来自多个页面的数据,以便一起提交。请参阅下面的代码。

在我的 Chrome 控制台中,如果我观察到 checkoutData.shipping,我会返回带有数据的正确对象。如果我观察checkoutData.data 我得到一个空对象,它的运输属性是空白的。

这些应该指向同一个对象,对吧?为什么它可以使用 .shipping 而不是 .data?设置这种方式的原因是运输页面只关心 .shipping,而最终页面需要 .data 中的所有内容。

(function() {
    angular.module('app').factory('checkoutData', [function() {
        var data = {
            carrierId: null,
            serviceTypeId: null,
            shippingCost: {},
            billingOptionId: null,
            shipping: {},
            billing: {},
            cart: null
        };
        var inputForms = {};
        var options = {
            shippingOptions: null,
            billingOptions: null,
            selectedShippingOption: null
        };
        var staticContent = {
            billing: {},
            cart: {},
            shipping: {}
        };
        return {
            data: data,
            shipping: data.shipping,
            inputForms: inputForms,
            cart: data.cart,
            billingOptionId: data.billingOptionId,
            billingOptions: options.billingOptions,
            carrierId: data.carrierId,
            serviceTypeId: data.serviceTypeId,
            shippingOptions: options.shippingOptions,
            staticContentBilling: staticContent.billing,
            staticContentCart: staticContent.cart,
            staticContentShipping: staticContent.shipping,
            selectedShippingOption: options.selectedShippingOption,
            setValid: function(formName, valid) {
                inputForms[formName].valid = valid;
            },
            initializeForm: function(formName) {
                inputForms[formName] = {};
            },
            formInitialized: function (formName) {
                return inputForms[formName] != null;
            }
        }
    }]);
})();

【问题讨论】:

  • 从哪里控制它们的价值,一个控制器?
  • 如果您在控制器中使用您的工厂,您将获得 checkoutData.shipping 一个空对象,因为它是空的,而对于 checkoutData.data,您将获得对象 {shippingCost: {...}, shipping: {...}, ... } 请看看在这个jsfiddle
  • 我无法重现您的问题。 checkoutData.shippingcheckoutData.data.shipping 在出厂时没有任何区别。你如何“观察”这些价值观?什么时候?
  • 你确定你是在工厂里操作你的shipping对象,而不是把它重新分配给别的东西吗?在代码中的其他任何地方执行checkoutData.shipping = x 会破坏对内部data 变量的引用。也许您根本不应该公开属性,而应该为它们设置 getter 和 setter?
  • 另外,您可以创建两个使用相同数据模型但以不同方式输出数据的工厂,一种方式用于您的运输页面,另一种方式用于“最终”页面。您的问题是双重的:数据绑定和尝试创建可以以多种不同方式使用的万能数据。为什么不修改结束页面以在您使用数据时以相同的方式使用数据?乱搞这些乱七八糟的东西似乎相当愚蠢,而且正如你所看到的那样,过于复杂了。

标签: javascript angularjs angularjs-service


【解决方案1】:

让事情变得更简单的一个建议是将数据模型与方法分开。并且没有必要尝试在同一个工厂中保留对同一个对象的多个引用。例如ng-model="checkoutModule.data.shipping.firstName" 没有错。是不是比较啰嗦?是的。这是错的吗?没有。

所以可能是这样的

angular.module('app').factory('checkoutData', [function() {
    return {
        dataModel: {
            carrierId: null,
            serviceTypeId: null,
            shippingCost: {},
            shipping: {}, // This should be databound to an object from "shippingOptions", removing the need for "selectedShippingOption"
            billing: {}, // This should be databound to an object from "billingOptions", removing the need for "billingOptionId"
            cart: null
        },
        options: {
            shippingOptions: null,
            billingOptions: null
        },
        inputForms: {}
    };
}]);

为您的数据和

angular.module('app').factory('checkoutModule', ['checkoutData', function(checkoutData) {
    return {
        data: checkoutData.dataModel,
        options: checkoutData.options,
        inputForms: checkoutData.inputForms,
        setValid: function(formName, valid) {
            checkoutData.inputForms[formName].valid = valid;
        },
        initializeForm: function(formName) {
            checkoutData.inputForms[formName] = {};
        },
        formInitialized: function (formName) {
            return checkoutData.inputForms[formName] != null;
        }
    }
}]);

对于将这一切联系在一起的工厂。

【讨论】:

    【解决方案2】:

    据我所知,除了使用以下内容之外,没有其他方法可以设置 data.shipping 的值:

    checkoutData.shipping = {"country" : "Sweden"};
    

    这将导致checkoutData.shipping 指向一个新对象,checkoutData.shipping 将返回该对象:

    {"country" : "Sweden"};
    

    但是 checkoutData.data 将返回原始的空 shipping 对象,因为我们尚未更新该值。

    如果您改为在 checkoutData 服务中创建一个用于设置运费值的函数:

    setShipping : function(s){
        data.shipping = s
    },
    

    并使用它来设置运输数据,您将从checkout.datacheckout.shipping 获得所需的值。

    看看这个进行演示:jsfiddle

    【讨论】:

    • 如果 OP 做了checkoutData.data.shipping = {"country" : "Sweden"} 它应该更新引用的对象。但是,是的,这似乎是一种非常脆弱的方法。 Setter 和 getter 将是优先的。或者使用数据绑定/设置器将该部分拆分为自己的服务。
    • 我的猜测是,这不是 OP 正在做的事情。而这种数据模型似乎只是造成诸如此类的混乱的秘诀。
    • @Jan 使用 checkoutData.data.shipping = {country: 'Sweden} 将对象设置为新引用;不会更新工厂,因为它是单例,并且 checkoutData.shipping 的值已分配给原始参考。让它工作的唯一方法是使 checkoutData.shipping 成为始终读取 data.shipping 的方法,或者使用 Object.defineProperty 使其成为 getter 属性,或者使用方法 setShipping 复制传递对象的所有属性,以便原始引用被维护
    • 我不确定是否可以使用单独的 getter 和 setter,因为我在 AngularJS 模板中进行双向数据绑定。例如,我的模板将具有 ng-model="checkoutData.shipping.firstName" 并且 2 方式绑定效果很好。例如,当我以编程方式设置数据时,我正在按照您指出的“checkoutData.shipping = { firstName: "Ryan" }" 进行操作。这似乎是 data 和 data.shipping 引用不同对象的情况。
    猜你喜欢
    • 1970-01-01
    • 2011-01-10
    • 2014-07-19
    • 2012-11-03
    • 1970-01-01
    • 2011-08-12
    相关资源
    最近更新 更多