【问题标题】:Custom bindings are not working as expected自定义绑定未按预期工作
【发布时间】:2018-03-09 07:38:28
【问题描述】:

我有一个 textarea 元素,它具有样式属性的特定属性 ->overflow:hidden;resize:none 和 height:20px。在这种情况下,当我在多行上有长文本时,我的 textarea 将只显示第一行。我的想法是,当我点击它时,我想让它调整大小,以使整个文本可见。我正在使用 Knockout JS,但我无法意识到我的绑定有什么问题。

function TextAreaVM() {
    this.active = ko.observable(false);
    
    this.text = ko.observable("Something\nnew line\nanother new line");

    this.setActive = function(){
        this.active(true);
    };

    this.notActive = function(){
        this.active(false);
    };

    ko.bindingHandlers.maximize ={
        update: function(element,valueAccessor){
            element.style.height = element.style.scroolHeight + "px";
        }
    };

    ko.bindingHandlers.minimize={
        update: function(element,valueAccessor){
            element.style.height = "20px";
        }
    };

}

ko.applyBindings(new TextAreaVM());
#txtarea-id{
    resize: none;
    overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<!DOCTYPE html>
<html>
<head>
<style>
</style>
</head>
<body>
<textarea id="txtarea-id" class="txtarea-class" height="20px" 
            data-bind="text: text, 
            event: {focus: setActive, blur: notActive},
            maximize: (active() == true),
            minimize: (active() == false)"
            readonly="true"></textarea>
<textarea id="txtarea-second" class="txtarea-class" height="20px" 
            width="50px" readonly="true">This is the first line and it should appear only on the first row&#13;&#10;This line shuld appera only o the second row!</textarea>
</body>
</html>

我也尝试过element.style.scroolHeight.toString()data-bind="maximize: active(), minimize: !active()" 之类的东西,但它们都不起作用。此外,我 100% 确定我的布尔值“活动”正常工作(我尝试使用 Chrome 进行调试,它的行为符合我的要求->当我点击文本区域时它是真的,当我点击外部时它是假的)。

【问题讨论】:

    标签: javascript html knockout.js data-binding


    【解决方案1】:

    代码只有三个小问题:

    1. 在您的问题中,您有两个名为 maximize 的绑定。将其中一个重命名为minimize 以避免冲突。

    2. 在绑定处理程序中,您没有在设置元素高度之前验证 valueAccessor 的值。结果,每次active observable 发生变化时,都会触发两个绑定处理程序。所以最后调用的处理程序将覆盖前一个处理程序的结果。所以你永远不会看到高度变化。

    3. 您在scroolHeight 中有错字。应该是element.scrollHeight

    ko.bindingHandlers.maximize = {
      update: function(element, valueAccessor) {
        if(valueAccessor()) {
         element.style.height = element.scrollHeight + "px";
        }
      }
    };
    
    ko.bindingHandlers.minimize = {
      update: function(element, valueAccessor) {
        if(valueAccessor()) {
          element.style.height = "20px";
        }
      }
    };
    
    function TextAreaVM() {
      this.active = ko.observable(false);
    
      this.text = ko.observable("Something\nnew line\nanother new line");
    
      this.setActive = function() {
        this.active(true);
      };
    
      this.notActive = function() {
        this.active(false);
      };
    }
    
    ko.applyBindings(new TextAreaVM());
    #txtarea-id {
      resize: none;
      overflow: hidden;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <!DOCTYPE html>
    <html>
    
    <head>
      <style>
    
      </style>
    </head>
    
    <body>
      <textarea id="txtarea-id" class="txtarea-class" height="20px" data-bind="text: text, 
                event: {focus: setActive, blur: notActive},
                maximize: (active() == true),
                minimize: (active() == false)" readonly="true"></textarea>
    </body>
    
    </html>

    更新

    当您对多个元素使用单个绑定时,您必须验证该元素是具有焦点的元素。所以将element === document.activeElement 添加到if 条件就足够了。我已经更新了 sn-p,对您的代码(在 cmets 中发布)进行了细微更改,以展示它是如何工作的。

    ko.bindingHandlers.resize = {
      update: function(element, valueAccessor) {
        if (valueAccessor() && element === document.activeElement) {
          element.style.height = element.scrollHeight + "px";
        } else {
          element.style.height = "20px";
        }
      }
    };
    
    function TextAreaVM() {
      this.active = ko.observable(false);
    
      this.text = ko.observable("Something\nnew line\nanother new line");
    
      this.setActive = function() {
        this.active(true);
      };
    
      this.notActive = function() {
        this.active(false);
      };
    }
    
    ko.applyBindings(new TextAreaVM());
    .txtarea-class {
      resize: none;
      overflow: hidden;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <!DOCTYPE html>
    <html>
    
    <head>
      <style>
    
      </style>
    </head>
    
    <body>
      <textarea id="txtarea-id" class="txtarea-class" height="20px" data-bind="text: text, 
                event: {focus: setActive, blur: notActive},
                resize: active()" readonly="true"></textarea>
                
    
      <br/>
      <textarea id="txtarea-id2" class="txtarea-class" height="20px" data-bind="text: text, 
                event: {focus: setActive, blur: notActive},
                resize: active()" readonly="true"></textarea>
    </body>
    
    </html>

    【讨论】:

    • 还有一个问题:如果我只想使用这样的一个绑定:data-bind="text: text, event: {focus: setActive, blur: notActive}, resize: (active() == true || active() == false)" 并且在我的视图模型中我有这样的东西:ko.bindingHandlers.resize = { update: function(element,valueAccessor){ if(active() == true) { element.style.height = element.scrollHeight + "px"; } else{ element.style.height = "20px"; } } };
    • 我有更多的 textarea 实例,它会选择所有实例并将所选实例的高度应用于所有实例。我应该怎么做才能将所需的高度仅应用于选定的高度。谢谢!
    • @BogdanV 它应该可以通过一些更改正常工作。我已经更新了我的答案以展示它是如何工作的。
    • 非常感谢您的帮助。它奏效了,非常感谢您的帮助。您知道吗,有什么方法可以自定义文本区域,这样当文本超出时它不会添加新行最大宽度,所以在overflow-x的情况下,我可以看到整个文本在x上滚动。谢谢!
    • 对不起,我没听懂。您可能应该发布一个新问题。
    【解决方案2】:

    我不是淘汰赛专家,但你定义了两次:

    ko.bindingHandlers.maximize ={
        update: function(element,valueAccessor){
            element.style.height = "20px";
        }
    };
    

    意味着只考虑最后一个(而这个是最后一个)。

    【讨论】:

    • 糟糕。很抱歉,这是一个错误。我编辑了代码以便看起来与原始代码完全相同。
    猜你喜欢
    • 2020-12-23
    • 1970-01-01
    • 2022-11-11
    • 1970-01-01
    • 2017-01-01
    • 2021-10-22
    • 2015-11-24
    • 1970-01-01
    • 2010-09-19
    相关资源
    最近更新 更多