knockout.js和Firefox在登录表单上保存密码

knockout.js和Firefox在登录表单上保存密码,firefox,knockout.js,Firefox,Knockout.js,Firefox使用我的用户名/密码填充表单。这是使用knockout.js绑定输入,但不会更新这种填充的值。我是不是在页面加载时遗漏了什么?当它填充并且用户点击提交时,值为空 (function (app, $, undefined) { app.viewModel = app.viewModel || {}; app.login = {}; app.viewModel.login = { userName: ko.observable(''),

Firefox使用我的用户名/密码填充表单。这是使用knockout.js绑定输入,但不会更新这种填充的值。我是不是在页面加载时遗漏了什么?当它填充并且用户点击提交时,值为空

(function (app, $, undefined) {

    app.viewModel = app.viewModel || {};
    app.login = {};

    app.viewModel.login = {
        userName: ko.observable(''),
        password: ko.observable(''),
        returnUrl: ''
    };

    app.viewModel.login.submit = function () {
        sso.login(app.viewModel.login.userName(), app.viewModel.login.password(), app.viewModel.login.returnUrl);
    };

    app.login.init = function (returnUrl) {

        app.viewModel.login.returnUrl = returnUrl;

        ko.applyBindings(app.viewModel);
    };

})(window.app = window.app || {}, jQuery);

我在过去处理这个问题的方法是使用
值的包装器
绑定,从元素的当前值初始化值

它看起来是这样的(这一个被简化为只处理可见光):

因此,您将使用
valueWithInit
而不是
value
。您只需要确保在自动完成之前不会调用ko.applyBindings


我发现这里的解决方案并不令人满意。尽管这种方法相当有趣,但当用户稍后选择帐户时,浏览器确实允许使用存储的凭据(例如,如果存储了多个凭据),这种方法会失败。当你开始输入密码并删除以恢复原始密码(至少在Firefox中)时,它也失败了。 此外,我并不真的喜欢超时来给浏览器时间——只是没有那么好

我的解决方案: 这不是真的,但我想我还是分享了

在提交回调中登录之前,只需手动更新我们的模型。 使用jQuery,类似于
self.password($(“#password”).val())
的东西应该可以做到这一点

或者,使用现有绑定,触发更改事件似乎也能起作用-例如
$(“#password”).change()

优点:

  • 仅适用于凭据字段,因此对于您的站点可能是一次性的
  • 是简单和干净的-一个或两个线在适当的地方
  • 无论浏览器、凭证设置或使用模式如何,似乎总是可靠地工作
缺点:

  • 再次打破了Knockout.js提供的良好分离
  • 这不是一个解决方案,而是一个变通办法
我会坚持到现在,因为我发现它只是可靠的工作。最好让Knockout直接重新评估绑定,而不是手动存储值或通过更改事件触发值。但到目前为止我还没有找到任何东西

只需提前一点思考-当浏览器自动完成任何表单(例如,像地址)时,也会出现同样的问题-这意味着执行上述操作的某种通用功能会很好(可能在表单的每个输入字段上调用更改触发器)

编辑: 一些快速代码演示了这个想法

HTML:

<form id="myForm" data-bind="submit: login">
    Email: <input type="text" data-bind="value: email" /><br/>
    Password: <input type="password" data-bind="value: password" /><br/>
    <button type="submit">Login</button>
</form>

Knouckout.js需要处理
输入
事件。很有趣,但它成功了,谢谢!setTimeout(函数(){ko.applyBindings(app.viewModel);},1000);我想在此基础上再接再厉。如果为同一表单保存了两个凭据,则此操作无效。当您选择用户名时,它会填充密码,但密码不会反映在viewmodel中。你必须手动删除它并输入它。我在下面通过重新绑定它来处理它。app.viewModel.login.userName.subscribe(函数(){ko.applyBindings(app.viewModel);});当您手动输入密码时,会在文本框中填充密码,但可观察到的密码不会更新。我原以为applyBindings会起作用,但实际上它会将页面绑定两次。我不能只更新密码的文本框吗?我试过小提琴,如果你为多个用户保存密码并尝试在他们之间切换,它就不起作用了。在chrome 25.0.1354.0(开发频道)中测试
<form id="myForm" data-bind="submit: login">
    Email: <input type="text" data-bind="value: email" /><br/>
    Password: <input type="password" data-bind="value: password" /><br/>
    <button type="submit">Login</button>
</form>
function ViewModel() {
    var self = this;

    self.email = ko.observable("");
    self.password = ko.observable("");

    self.login = function() {
        $("#myForm").find("input").change();

        //Now the observables contain the recent data
        alert(ko.mapping.toJSON(self));
    };
}