KnockoutJS-错误:不得递归调用计算出的“纯”值

时间:2018-10-19 11:56:18

标签: knockout.js

在我的js文件中添加了几行代码之后,却出现了错误Error: A 'pure' computed must not be called recursively,但我不知道为什么。这是文件的开头:

import knockout from 'knockout';
import BaseViewModel from '../checkout/base';
import Is from '../is';
import jQuery from 'jquery';

const AddressViewModel = ((ko, is, $) => {

    const CountryCode = {
        CANADA: 'CA',
        USA: 'US'
    };

    const CITY_ENTER_OTHER = 'Enter Other City';

    class AddressViewModel extends BaseViewModel {

        constructor() {
            super();

            this.addressId = ko.observable();
            this.locationDescription = ko.observable();
            this.addressLine1 = ko.observable();
            this.addressLine2 = ko.observable();
            this.postalCode = ko.observable();
            this.cityEntered = ko.observable();
            this.citySelected = ko.observable();
            this.cityOptions = ko.observableArray();
            this.countryCode = ko.observable();
            this.state = ko.observable();
            this.province = ko.observable();
            this.addressTypeCode = ko.observable();
            this.alreadyChecked = ko.observable(false);
            this.stateCheck = ko.observable(false);
            this.initialValueUsed = ko.observable(false);

            this._initComputedValues();
            this._initSubscribers();
        }

        _initComputedValues() {
            // this next code is what I added that is causing the error
            this.addressLine1 = ko.pureComputed({
                read: this._readAddressLine1,
                write: this._writeAddressLine1,
                owner: this
            });
            this.postalCode = ko.pureComputed({
                read: this._readPostalCode,
                write: this._writePostalCode,
                owner: this
            });

我最近添加了以this.开头的最后两个块。稍后,我还在文件中添加了读/写定义。在_initComputedValues函数之外,我还添加了以下内容:

_readAddressLine1() {
        let address = this.addressLine1();
        let returnValue = this.replaceSpecialCharacters(address);
        return returnValue;
    }

    _writeAddressLine1(address) {
        this.addressLine1(address);
    }

    _readPostalCode() {
        let postalCode = this.postalCode();
        let returnValue = this.replaceSpecialCharacters(postalCode);
        return returnValue;
    }

    _writePostalCode(postalCode) {
        this.postalCode(postalCode);
    }

现在在添加该代码之后,就是我开始遇到该错误的时候。

最后,我的replaceSpecialCharacters函数来自另一个名为convert-special-characters.js的文件:

import BaseViewModel from '../checkout/base';

const CharacterViewModel = (() => {

    class CharacterViewModel extends BaseViewModel {

        constructor() {
            super();

            this._initComputedValues();

        }

        _initComputedValues() {
            this.createConversionMap = this._createConversionMap.bind(this);
            this.replaceSpecialCharacters = this._replaceSpecialCharacters.bind(this);
        }

        _createConversionMap() { // from https://stackoverflow.com/a/49139933/571723

            let map = {};

            // Open-quotes: http://www.fileformat.info/info/unicode/category/Pi/list.htm
            map[0x2018] = '\'';
            map[0x201B] = '\'';
            map[0x201C] = '"';
            map[0x201F] = '"';

            // Close-quotes: http://www.fileformat.info/info/unicode/category/Pf/list.htm
            map[0x2019] = '\'';
            map[0x201D] = '\"';

            // Primes: http://www.fileformat.info/info/unicode/category/Po/list.htm
            map[0x2032] = '\'';
            map[0x2033] = '"';
            map[0x2035] = '\'';
            map[0x2036] = '"';

            map[0x2014] = '-'; // iOS 11 also replaces dashes with em-dash
            map[0x2013] = '-'; // and "--" with en-dash

            return map;
        }

        _replaceSpecialCharacters(value) {
            let conversionMap = this.createConversionMap;
            let returnValue = '';

            for (let i = 0; i < value.length; i++) {
                let replacement = conversionMap[value.charAt(i)];
                if (replacement) {
                    returnValue = value.replace(value.charAt(i), replacement);
                }
            }
            return returnValue;
        }


    }

    return CharacterViewModel;
})();

export default CharacterViewModel;

1 个答案:

答案 0 :(得分:2)

您已在顶部将addressLine1声明为可观察对象,然后在以后进行计算时再次声明了它。我猜这些应该是两个不同的属性?计算版本试图返回可观察值的值,这就是正在发生的递归。您不能将计算用途本身用作背景字段。

this.addressLine1 = ko.observable();

...

this.addressLine1 = ko.pureComputed({
    read: this._readAddressLine1,
    write: this._writeAddressLine1,
    owner: this
});

...

_readAddressLine1() {
    let address = this.addressLine1();
    let returnValue = this.replaceSpecialCharacters(address);
    return returnValue;
}

计算只是具有自动触发器的函数;它永远不会存储值。让它在其定义内使用自己的值就是要它求解x,其中x是x的某个函数。如果它没有给您带来有用的编译错误,则会出现堆栈溢出。您可能应该将可观察对象重命名为_addressLine1之类,因此代码为:

this._addressLine1 = ko.observable();

this.addressLine1 = ko.pureComputed({
    read: this._readAddressLine1,
    write: this._writeAddressLine1,
    owner: this
});

...

_readAddressLine1() {
    let address = this._addressLine1();
    let returnValue = this.replaceSpecialCharacters(address);
    return returnValue;
}
_writeAddressLine1(address) {
    this._addressLine1(address);
}