Knockout observable 在函数内部不可访问

Posted

技术标签:

【中文标题】Knockout observable 在函数内部不可访问【英文标题】:Knockout observable is not accessible inside function 【发布时间】:2021-02-17 10:46:20 【问题描述】:

所以我在 Magento 2.3.4 中使用 Knockout,我在初始化时设置了一个自定义的 observable 值,然后我试图访问该 observable 并更改函数内的值。每次我尝试时,我都会不断收到“它不是一个函数”,它不会让我检索和读取当前的可观察值,或者设置一个新值。当我尝试在其上运行 .isObservable() 时,它会出现错误。我已经查看了如何做到这一点的各种示例,并尝试了所有这些示例,但没有一个有效。目前我的淘汰赛 JS 表单是这样的:

define([
'jquery',
'uiComponent',
'ko'
], function($, Component, ko) 
'use strict';

return Component.extend(
   defaults: 
       template: 'Shmoop_Cms/career-form'
   ,
    progressText: ko.observable(false),

    initialize: function() 
       var self = this;

       this._super();

           this.progressText('1 of 15 questions completed');

        return this;
    ,

    showNext: function() 
       let dataIndex = parseInt($('.quiz-card.show').attr('data-index')) + 1;
       alert(ko.isObservable(this.progressText));
       alert(this.progressText());
       
       this.progressText(dataIndex + ' of 15 questions completed');
    

);

);

我可以在初始化函数中设置 progressText 值而没有问题,并且它在那里识别出它是一个可观察的。为什么它说它不是“showNext”函数内部的可观察对象?

仅供参考,我也尝试在我的函数中添加“var self = this”,我也尝试过“self.progressText()”而不是“this.progressText()”,但没有任何效果。

请帮忙。

已编辑:顺便说一下,我的模板如下所示:

<div class="career-quiz-wrapper">
<!-- ko if: quizQuestions -->
<form class="career-quiz-form" data-bind="foreach: quizQuestions">
    <div class="quiz-card" data-bind="attr: 'data-question-uuid': uuid, 'data-index': index , css: index == 0 ? 'show' : 'hide'">
        <h2 class="display-heading title">How important is it to you to...</h2>
        <div class="lead main-text" data-bind="html: question"></div>
        <div class="choices">
            <div class="row-bar">
                <input type="range" data-anchor="range" class="custom-range" min="0" max="100" value="50" autocomplete="off" data-bind="event:  change: $parent.adjustRangeSlider ">
            </div>
            <div class="row-options">
                <div class="option-section" data-bind="foreach: choiceUUIDs">
                    <div class="choice-option-button">
                        <a class="option-button" data-bind="click: $parents[1].choiceClicked, attr:  'data-choice-uuid': UUID, 'data-range-value': rangeValue, title: textOption , text: textOption, css: (i && i == 2) ? 'selected' : ''"></a>
                    </div>
                </div>
                <div class="mobile-bar">
                    <input type="range" data-anchor="range" class="custom-range" min="0" max="100" value="50" autocomplete="off" data-bind="event:  change: $parent.adjustRangeSlider ">
                </div>
            </div>
        </div>
        <div class="choice-buttons">
            <div class="choice-button">
                <a data-bind="click: $parent.showCareers" class="blue-link" title="Show Careers">Show Careers</a>
            </div>
            <!-- ko if: index == ($parent.quizQuestions().length - 1) -->
                <div class="choice-button">
                    <a class="pink-button results-button" data-bind="click: $parent.getResults" title="Get Results">Get Results <i class="fa fa-cog fa-spin d-none"></i></a>
                </div>
            <!-- /ko -->
            <!-- ko ifnot: index == ($parent.quizQuestions().length - 1) -->
                <div class="choice-button">
                    <a class="pink-button next-question" data-bind="click: $parent.showNext" title="Next Question">Next Question</a>
                </div>
            <!-- /ko -->
        </div>
        <div class="quiz-progress">
            <p class="progress-text" data-bind="text: $parent.progressText"></p>
        </div>
    </div>
</form>
<!-- /ko -->
<!-- ko ifnot: quizQuestions -->
<div class="error-message">
    <p>
        Sorry, something went wrong. I guess you'll have to figure out what to do on your own..
    </p>
</div>
<!-- /ko -->

【问题讨论】:

你在哪里以及如何绑定你的 showNext 函数,你能提供模板吗? 我已经添加了我的模板来展示我是如何被 showNext 函数绑定的。 【参考方案1】:

我以前遇到过 javascript 对象文字的问题,可能会这样处理。不确定这是否有效,因为我没有测试过。

define([
  'jquery',
  'uiComponent',
  'ko'
], function($, Component, ko) 
  'use strict';
  var self = this;
  self.progressText = ko.observable(false);

  function initialize() 
    this._super();
    self.progressText('1 of 15 questions completed');
    return this;
  

  function showNext() 
    let dataIndex = parseInt($('.quiz-card.show').attr('data-index')) + 1;
    alert(ko.isObservable(self.progressText));
    alert(self.progressText());

    self.progressText(dataIndex + ' of 15 questions completed');
  
  
  return Component.extend(
    defaults: 
      template: 'Shmoop_Cms/career-form'
    ,
    progressText: self.progressText,
    initialize: initialize,
    showNext: showNext
  );
);

【讨论】:

以上是关于Knockout observable 在函数内部不可访问的主要内容,如果未能解决你的问题,请参考以下文章

knockout从函数中访问observable

Knockout双向绑定

在 knockout.js 中将 observable 从一个视图模型传递到另一个视图模型

从javascript函数更新Knockout viewmodel表单输入绑定

在 knockout.js 中更改 observable 但不通知订阅者

Knockout:从observable中删除所有订阅