【问题标题】:KnockoutJS not picking up jQuery .change() eventKnockoutJS 没有收到 jQuery .change() 事件
【发布时间】:2013-11-25 02:34:32
【问题描述】:

我已经阅读了所有与此相关的帖子,并在过去两天试图找出我在这里做错了什么,但没有取得多大成功。

这里以使用这个 JS 小提琴为例:http://jsfiddle.net/rniemeyer/dtpfv/ 我正在尝试实现一个脏标志。唯一的区别是我正在更改常规范围内的数据与输入字段,并使用映射插件与手动分配可观察对象。

$(document).ready(function(){

    ko.dirtyFlag = function(root, isInitiallyDirty) {
        var result = function() {},
            _initialState = ko.observable(ko.toJSON(root)),
            _isInitiallyDirty = ko.observable(isInitiallyDirty);

        result.isDirty = ko.computed(function() {
            return _isInitiallyDirty() || _initialState() !== ko.toJSON(root);
        });
        result.reset = function() {
            _initialState(ko.toJSON(root));
            _isInitiallyDirty(false);
        };
        return result;

    };

    $.getJSON('/environments/data.json', function(jsondata) {
        var mapping = {
            create: function (options) {
                var innerModel = ko.mapping.fromJS(options.data);
                for (var i=0; i < innerModel.deployments().length; i++) {
                    innerModel.deployments()[i].dirtyFlag = new ko.dirtyFlag(innerModel.deployments()[i]);
                }
                return innerModel;
            }
        }

        var viewModel = ko.mapping.fromJS(jsondata, mapping);

        self.save = function() {
            console.log("Sending changes to server: " + ko.toJSON(this.dirtyItems));  
        };

        self.dirtyItems = ko.computed(function() {
            for (var i = 0; i < viewModel().length;  i++ ) {
                return ko.utils.arrayFilter(viewModel()[i].deployments(), function(deployment) {
                    return deployment.dirtyFlag.isDirty();
                });
            }
        }, viewModel);

        self.isDirty = ko.computed(function() {
            return self.dirtyItems().length > 0;
        }, viewModel);

        self.changeTag = function (data, event) {

            // Neither .change() nor .trigger('change') work for me
            $(event.target).parents().eq(4).find('span.uneditable-input').text(data.tag).change()

            // This value never changes.
            console.log('Dirty on Change: '+self.dirtyItems().length)

        }

        ko.applyBindings(viewModel);

    });

})

这里是触发changeTag() 函数的HTML 片段,它用下拉菜单中的选项替换current_tag()。但是,这不会触发 KnockoutJS 更新。

<div>
    <span data-bind="text: current_tag() }"></span>
    <div>
        <button data-toggle="dropdown">Select Tag</button>
        <ul>
          <!-- ko foreach: $.parseJSON(component.available_tags() || "null") -->
          <li><a href="#" data-bind="click: function(data, event) { changeTag(data, event) }"></a></li>
          <!-- /ko -->
        </ul>
    </div>
</div>

我正在尝试解决这个问题的第二天。知道我在这里做错了什么吗?我应该使用输入字段而不是常规 span 元素吗?我是否需要直接更改 viewModel 的值而不是使用 jQuery 来操作 DOM? (我实际上已经尝试过了,但是更改 viewModel 然后重新绑定它似乎会减慢速度,除非我做错了)

谢谢。

【问题讨论】:

  • 到底是什么问题?你能不能把它定义得更好一点。我假设您是说您提供的小提琴是您要完成的工作的一个工作示例 - 您能否提供您的代码的小提琴?
  • @PWKad:问题是 KnckoutJS 没有像我使用 jQuery 那样获取跨度的更新。立即创建小提琴
  • 我不确定 100% 为什么要从 jQuery 更新 observable - 这违背了使用 Knockout 进行双向数据绑定的基本原则。可能有一个很好的用例,但为什么不直接使用属性更新它,而不是用 jQuery 覆盖它并可能破坏您的绑定?
  • @PWKad:这就是我在这里的原因:) 我不是开发人员,而且这是一个爱好项目,所以我不知道我在做什么。
  • @PWKad:我实际上尝试过使用类似jsondata[environment()].deployments[deployment()].current_tag = ko.dataFor(event.target).tag 的方式直接更新属性(在我的帖子底部提到),但是,除非我重新- 使用ko.mapping.fromJS(jsondata, viewModel); 绑定到整个视图模型。有没有更好的方法让它重新绑定我正在更新的元素?

标签: javascript jquery knockout.js knockout-mapping-plugin


【解决方案1】:

正如 cmets 中所说,通过 jQuery 更新值被认为是“糟糕的 Knockout 做法”,此时您也可以直接更新 observable。 Knockout 提倡数据驱动的方法。

针对您的上一条评论(尚不确定如何在堆栈溢出时回答 cmets):UI 未获取更改的原因是您分配了错误的值:

var x = ko.observable(1); // x is now observable
x = 3; // x is no longer observable. After all, you've assigned the value 3 to it. It is now just a number
x(3); // this is what you're after. x is still an observable, and you assigned a new value to it by using Knockout's parentheses syntax. If x is bound to the ui somewhere, you'll see the value 3 appear

所以你想做

jsondata[environment()].deployments[deployment()].current_tag(ko.dataFor(event.target).tag);

【讨论】:

  • 谢谢,汉斯,但它不适合我。我得到Uncaught TypeError: Property 'current_tag' of object #&lt;Object&gt; is not a function。我的映射是否以某种方式损坏并且没有从 current_tag 创建一个 observable?
  • 没关系!弄清楚了。我不得不改用viewModel()[environment()].deployments()[deployment()].current_tag(ko.dataFor(event.target).tag);。标记为已解决!再次感谢您!
猜你喜欢
  • 1970-01-01
  • 2012-10-31
  • 1970-01-01
  • 2016-11-28
  • 1970-01-01
  • 2011-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多