Knockout.js 使用自定义bindingHandler的文本输入水印

Knockout.js 使用自定义bindingHandler的文本输入水印,knockout.js,watermark,Knockout.js,Watermark,我一直在尝试创建一个自定义bindingHandler,我可以使用它为文本输入字段提供水印行为 我所说的watermark的意思是:为文本字段添加默认值,这些默认值在聚焦时被删除,如果文本字段仍然为空,则在模糊时被替换 我已经成功地实现了这一点,如本JSFIDLE中所示: 关于此解决方案,我有3个问题: 是否有办法更改它,以便我只需声明一次水印值?目前,我必须将其放置在声明绑定的位置,并且我还必须在viewModel中使用相同的值初始化可观察对象,否则它将没有初始值 是否有更好的方法来获取元素值

我一直在尝试创建一个自定义bindingHandler,我可以使用它为文本输入字段提供水印行为

我所说的
watermark
的意思是:为文本字段添加默认值,这些默认值在聚焦时被删除,如果文本字段仍然为空,则在模糊时被替换

我已经成功地实现了这一点,如本JSFIDLE中所示:

关于此解决方案,我有3个问题:

  • 是否有办法更改它,以便我只需声明一次水印值?目前,我必须将其放置在声明绑定的位置,并且我还必须在viewModel中使用相同的值初始化可观察对象,否则它将没有初始值
  • 是否有更好的方法来获取元素值绑定到的底层可观察对象。我目前正在使用allBindingsAccessor获取它,但我觉得这不对。最初我只是使用jquery
    $(element).val(“”)
    设置值,但这也感觉不对。哪种方法最好,还是有更好的方法
  • 有人知道或知道这个问题的现有解决方案吗?我是在重新发明轮子吗

  • 我认为您使用的所有绑定都是不必要的。事实上,我认为水印根本不需要意识到可观察性,因为这是水印通常做的事情,即
    占位符
    属性

    这对你有用吗

    ko.bindingHandlers.watermark = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            var value = valueAccessor(), allBindings = allBindingsAccessor();
            var defaultWatermark = ko.utils.unwrapObservable(value);
            var $element = $(element);
    
            setTimeout(function() {
                $element.val(defaultWatermark);}, 0);
    
            $element.focus(
                function () {
                    if ($element.val() === defaultWatermark) {
                        $element.val("");
                    }
                }).blur(function () {
                    if ($element.val() === '') {
                        $element.val(defaultWatermark)
                    }
                });
        }
    };
    


    希望这能有所帮助。

    只要你的应用程序逻辑非常简单,前面的方法就可以了。请注意,解决方案会弄乱你的视图模型的值,这些值是可以观察到的,它们可以有订阅或计算关联到它,所以通过更改值,你可以更改你的视图模型。这是一个不更新视图模型的不同解决方案

    ko.bindingHandlers.fakePlaceHolderWhenNeedIt = {
        init: function (element, valueAccessor, allBindings, vm) {
         if (!Modernizr.input.placeholder) {
            var placeHolderVal = $(element).attr("placeholder");
    
            if (placeHolderVal != null || placeHolderVal != '') {
    
                var $element = $(element);
                var value = valueAccessor()
                var valueUnwrapped = ko.utils.unwrapObservable(value);
    
    
                $element.keyup(function () {
                    var inputValue = $(this).val();
                    var $watermark = $(this).prev('.ie-placeholder');
                    if (inputValue == null || inputValue == '') {
                        $watermark.show();
                    }
                    else {
                        $watermark.hide();
                    }
                });
    
                var display = valueUnwrapped != null || valueUnwrapped != '' ? "block" : "none";
                var left = $element.position().left;
                var top = $element.position().top;
                var paddingLeft = $element.css('padding-left');
                var paddingRight = $element.css('padding-right');
                var paddingTop = $element.css('padding-top');
                var paddingBottom = $element.css('padding-bottom');
    
                var height = $element.css('height');
                var placeHolder = '<div class="ie-placeholder" style="position:absolute;left:' + left + ';top:' + top + ';padding-top: ' + paddingTop + ';padding-bottom: ' + paddingBottom + ';padding-left: ' + paddingLeft + ';padding-right: ' + paddingRight + ';height: ' + height + ';line-height:' + height + ';display:' + display + ';">' + placeHolderVal + '</div>';
    
                $(placeHolder).click(function () { $element.focus(); }).insertBefore(element);
            }
        }
    },
    update: function (element, valueAccessor, allBindings, vm) {
        if (!Modernizr.input.placeholder) {
            var placeHolderVal = $(element).attr("placeholder");
    
            if (placeHolderVal != null || placeHolderVal != '') {
                var $element = $(element);
                var value = valueAccessor()
                var valueUnwrapped = ko.utils.unwrapObservable(value);
    
                var $watermark = $element.prev('.ie-placeholder');
                if (valueUnwrapped == null || valueUnwrapped == '') {
                    $watermark.show();
                }
                else {
                    $watermark.hide();
                }
            }
        }
    }
    
    ko.bindingHandlers.fakePlaceholder WhenneEdit={
    init:函数(元素、valueAccessor、allBindings、vm){
    if(!modernizer.input.placeholder){
    变量占位符val=$(元素).attr(“占位符”);
    如果(占位符val!=null | |占位符val!=''){
    变量$element=$(element);
    var value=valueAccessor()
    var valueUnwrapped=ko.utils.unwrapObservable(值);
    $element.keyup(函数(){
    var inputValue=$(this.val();
    var$watermark=$(this.prev('.ie占位符');
    如果(inputValue==null | | inputValue==“”){
    $watermark.show();
    }
    否则{
    $watermark.hide();
    }
    });
    变量显示=valueUnwrapped!=null | | valueUnwrapped!=“块”:“无”;
    var left=$element.position().left;
    var top=$element.position().top;
    var paddingLeft=$element.css('padding-left');
    var paddingRight=$element.css('padding-right');
    var paddingTop=$element.css('padding-top');
    var paddingBottom=$element.css('padding-bottom');
    var height=$element.css('height');
    变量占位符=“”+占位符val+“”;
    $(占位符)。单击(函数(){$element.focus();});
    }
    }
    },
    更新:函数(元素、valueAccessor、allBindings、vm){
    if(!modernizer.input.placeholder){
    变量占位符val=$(元素).attr(“占位符”);
    如果(占位符val!=null | |占位符val!=''){
    变量$element=$(element);
    var value=valueAccessor()
    var valueUnwrapped=ko.utils.unwrapObservable(值);
    var$watermark=$element.prev('.ie占位符');
    如果(valueUnwrapped==null | | valueUnwrapped==“”){
    $watermark.show();
    }
    否则{
    $watermark.hide();
    }
    }
    }
    }
    
    是的,这几乎与我更改为使用allBindingsAccessor之前的情况完全相同。在尝试设置初始值时,我缺少了
    setTimeout
    。您能否简要解释一下为什么需要这样做?另外,您知道是否有更好的方法?或者您认为这是一种好(足够)的方法(就整个解决方案而言)?例如,我注意到有一个hasfocus绑定(内置)。这可能是一种更好的方法吗?如果您想支持旧浏览器,我认为这种方法很好。对于新浏览器,只需使用占位符属性。需要setTimeout,因为在设置输入值之前,KO内部使用setTimeout。这意味着您的代码在KO代码设置值之前运行,因此您需要设置再次超时以确保您的代码在执行过程中是最后一个。非常感谢您的解释和帮助。哇。我不希望找到完整的解决方案。谢谢!关于设置超时非常有趣,我直到现在才意识到这是必需的。谢谢。