Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/457.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在敲除js后向视图模型添加新属性_Javascript_Model View Controller_Knockout.js_Viewmodel_Knockout Mapping Plugin - Fatal编程技术网

Javascript 在敲除js后向视图模型添加新属性

Javascript 在敲除js后向视图模型添加新属性,javascript,model-view-controller,knockout.js,viewmodel,knockout-mapping-plugin,Javascript,Model View Controller,Knockout.js,Viewmodel,Knockout Mapping Plugin,我不太擅长击倒js,所以我可能错过了一些东西 我的用例: 我有一个简单的视图模型 <body> <hr /> <div> <label for=""> Basic :</label> <input type="text" name="" data-bind="value: basic" id="txtBasic" /> </div>

我不太擅长击倒js,所以我可能错过了一些东西

我的用例:

我有一个简单的视图模型

     <body>
    <hr />
    <div>
      <label for="">
            Basic :</label>
      <input type="text" name="" data-bind="value: basic" id="txtBasic" />
    </div>
    <div>
      <label for="">
            HRA :</label>
      <input type="text" name="" data-bind="value: hra" id="txtHra" />
    </div>
    <div>
      <div style="background-color:silver;">
        <hr />
        <label for="">
          <input type="button" data-bind="click : generateModelValue" value="Generate Runtime Property" />
          <input type="button" data-bind="click : tryRebind" value="Try Rebinding with clean node" />
<br>
                DA :</label>
         <input type="text" name="" id="txtDa" data-bind="value: $data.da"><br><br></div>

      </div> 
      <hr />
      <div>
        <label for="">
                Tax :</label>
        <input type="range" name="" id="rangeTax" min="0" max="30" value="0" data-bind="value: tax" />
        <span id="spanTax">[Tax%]</span>
      </div>
      <div>
        <input type="button" value="Calculate" id="btnCalculate" data-bind="click: computeSalary" />
      </div>
      <div>
        <div id="divResult" data-bind="text: salary">
                [Salary]</div>
      </div>
    </div>
    <script>

            myViewModel={
                basic: ko.observable(1000),
                hra: ko.observable(10),

                tax: ko.observable(10),
                salary: ko.observable('Yet to be calculated'),
                computeSalary: function () {
                    this.salary(this.basic()+this.da()+this.hra());
                },
                generateModelValue: function () {
                  debugger;
                    this.da=ko.observable("123");
                },
                tryRebind: function () {
                  debugger;
                  alert("Why do i have to call this to update the view model");
                    ko.cleanNode($('body')[0]);
                    ko.applyBindings(myViewModel,$('body')[0]);
                }
            };

            ko.applyBindings(myViewModel,$('body')[0]);


        </script>
  </body>


基本: HRA:

DA:


税款: [税率%] [薪金] myViewModel={ 基本值:可观测(1000), hra:ko.可观察(10), 税项:可观察到的ko(10), 工资:可观察到的(尚待计算), computeSalary:函数(){ this.salary(this.basic()+this.da()+this.hra()); }, generateModelValue:函数(){ 调试器; 此.da=ko.可观察(“123”); }, tryRebind:函数(){ 调试器; 警报(“为什么我必须调用此命令来更新视图模型”); ko.cleanNode($('body')[0]); 应用绑定(myViewModel,$('body')[0]); } }; 应用绑定(myViewModel,$('body')[0]);
我想在运行时添加一个属性(在本例中为“da”)。因此为了使该示例易于阅读,我将在我的模型上调用“generateModelValue”函数,该函数将在“myViewModel”上添加一个带有样本值“123”的“da”属性

这成功地创建了一个新的可观察属性(我用console.log检查过)但不更新用户界面

因此,在这次单击之后,我调用了视图模型上的另一个函数,该函数将尝试执行ko.cleanNode($('body')[0]),后面是ko.applyBindings(myViewModel,$('body')[0])然后更新UI


我的问题:

我是否必须调用clean节点,或者有更好的方法在viewmodel更新后立即更新UI

我的怀疑:

  • 我不认为使用干净的节点是实现这一点的好方法
  • 如果对象太复杂或太大,会导致性能问题吗
  • 我正在使用
    在我的HTML中(这样当我使用viewModel中不可用的属性调用applyBinding时不会抛出未定义的错误)
    是否确实需要$数据(有其他选择吗?)
  • 访问的帖子:
    (我不太确定我是否理解这篇文章。如果推荐的话,我会再看一遍,因为我也在使用映射插件将普通json响应从AJAX调用转换为observable视图模型,但我的实现有点不同)

    现场扑救:


    编辑:
    为什么我需要做到这一点-

    因为在调用ko.applybinding时,我的viewModel总是小于HTML标记中所需的数据绑定属性,因此会抛出未定义的错误(我使用$data来避免此错误)

    因此,在ko.applyBinding(html元素)中传递的最终html视图将是构成屏幕的几个较小html片段的联合

    在调用apply binding时不可能收集所有视图模型属性,因为视图模型的复杂性会随着用户交互(Ajax调用)的增加而增加

    我希望它是明确的。如果不是,我正在创建一个相同的plunkr。将很快更新

    更新
    新普朗克

    在上面的段落中

    <div data-bind="visible: $data.da">
             You will see this section only if the da property is available on the view model
             </div>
    
    
    只有在视图模型上的da属性可用时,才能看到此部分
    
    将在应用绑定时存在于DOM中,但“da”的值将不存在。
    在一些用户交互之后,视图模型将被更新,因为对象将通过ajax调用接收新属性(例如,prunkr中的da)。因此将显示da部分。

    我认为您误解了击倒的工作方式。有些情况下,例如动态列表等,并非所有的可观测数据都能立即可用。然而,您的可观察性只是模型上的一个属性。该可观察值应与
    basic
    hra
    一起创建。延迟它的创建没有任何好处

    将代码更改为:

    myViewModel = {
        basic: ko.observable(1000),
        hra: ko.observable(10),
        da: ko.observable(null),
    
    如果要表示在函数
    generateModeValue
    之前未设置该值,则让
    null
    表示该值,或创建另一个布尔可观察值,该函数可以设置该值。例如:

    myViewModel = {
        basic: ko.observable(1000),
        hra: ko.observable(10),
        da: ko.observable(null),
        daIsSet: ko.observable(false),
        ...
        generateModelValue: function () {
            debugger;
            this.da("123");
            this.daIsSet(true);
        },
        ...
    

    同样,可以动态添加可观察对象(使用数组或其他方法),但这种情况不需要这种功能。希望这能为您澄清一些概念。

    在运行时添加属性需要您调用应用绑定

    然而,如果你愿意放弃最初的设计,答案很简单

    我假设您的薪资组成部分都有一个通用模型,可以让您推导出它们将如何添加到薪资计算中。没有细节,我称之为工资部分

      function salaryComponent(n,v,t){
           this.Name = ko.observable(n);
           this.Value = ko.observable(v);
           this.Type = ko.observable(t);
       }
    
    如果您需要按类型自定义显示,我将向salary组件添加一个类型描述符,然后使用

    <div data-bind="foreach: salaryComponents">
        <!-- ko if: type() == 1 -->
           <data-bind="template: {name:'Da-template',data:$data}
       <!-- /ko -->
    </div>
    
    对模型使用此设计允许按薪资类型使用多个模板来创建复杂的UI显示,并允许向视图模型中添加不需要再次调用应用绑定的组件

    哦,还有最后一件事,没有理由
       myViewModel={
                basic: ko.observable(1000),
                hra: ko.observable(10),
    
                tax: ko.observable(10),
                salary: ko.observable('Yet to be calculated'),
                //dynamic salary components 
                salaryComponents: ko.observableArray(),
    
                computedSalary = ko.computed(function(){
                    var base = this.basic()+this.hra();
                    ko.utils.arrayForEach(salaryComponents(), function(item) {
                        base+=item.Value()
                    });
                    return base;
                }
                generateModelValue: function () {
                   salaryComponents.push(new salaryComponent('Da',123,1));
                },
            };
    
      computedSalary = ko.computed(function(){
                    var base = this.basic()+this.hra();
                    ko.utils.arrayForEach(salaryComponents(), function(item) {
                        base+=item.Value()
                    });
                    return base;
       }