AngularJS:尝试使用ngClass造成怪异的功能和性能问题,动态地应用指令 [英] AngularJS: Attempt to dynamically apply directive using ngClass causing weird functional and performance issues

查看:178
本文介绍了AngularJS:尝试使用ngClass造成怪异的功能和性能问题,动态地应用指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要求


  1. 我想,作为用户类型,阿拉Facebook的评论框垂直膨胀或收缩一个textarea。

  2. 当文本​​区域失去焦点会收缩至一条线(带省略号如果内容溢出)和再扩展到在重新聚焦输入的文本的大小(此功能在Facebook上未找到)

请注意:点击textarea的究竟应该preserve插入位置在哪里用户点击,当控件接收焦点其中precludes格为textarea的任何动态交换

尝试解决方案

我已经进入一个AngularJS实现,所以...


  1. 使用等宽的角弹性插件。尼斯。<​​/ li>
  2. 二企图...

    • 尝试:&LT; textarea的NG-重点=isFocussed =真正的NG-模糊=isFocussed =假NG-CLASS =MSD弹:isFocussed&GT;&LT; / textarea的&GT; 失败,因为纳克级触发器没有再 - 加后级的元素 $编译,所以角弹性永远不会调用

    • 尝试A:创建一个具有所需的重新自定义指令 - 在类中添加 $编译。我用<一个href=\"http://stackoverflow.com/questions/19230011/class-directive-not-working-when-using-ng-class-to-load-the-directive\">this通过hassassin 解决方案。具有以下问题失败


尝试乙问题

下面的企图B的的jsfiddle 注意角度v1.2.15使用

我。消失文本


  • 去拨弄

  • 类型到一个文本区域

  • 模糊焦点的文本区域(如点击其他文本区域)

  • 焦点回到上包含文本,文本区域

  • 结果:文本消失! (不期望或期望)

二。越来越多的过度循环和最终的浏览器崩溃


  • 点击到一个文本区域

  • 点击进入另一个

  • 重复上面,只要你能,直到浏览器停止响应,你会得到CPU 100%或无响应脚本警告。

  • 您会发现它开始时确定,但会变得更糟更单击

  • 我证实了这一点使用:XP / Firefox的V27,XP /铬V33中,Win7 /镀铬V33

我的调查至今

似乎 traverseScopesLoop 在AngularJS开始v1.2.15的12012行,失控,循环数百次。我把的console.log 刚下做{//遍历范围循环线和时钟十万环路只需点击

奇怪的是,我没有得到在角v1.0.4同样的问题。请参见本的jsfiddle 是相同的,除了角版本

我登录这是一个 AngularJS错误并就立刻把它关闭,因为我倒是没有表明它是在角本身。

中的错误

问题


  1. 有另一种方式来解决这个问题,以避免在尝试B中的图案?

  2. 有没有尝试实现B中的更好的办法?有没有活动上计算器发出后hassassin提供我用的解决方案

  3. 在我的code。与尝试B中的问题,棱角分明的弹性,hassassin的code,还是我执行这一切?如何在未来的调试这样我就可以鱼为自己鸭preciate提示。我一直在使用Chrome的调试和Batarang半天已经没有多少成功。

  4. 它看起来明智的做出特色请求AngularJS团队在尝试的模式呢?既然你可以在类中添加角指令和ngClass可以动态地添加类,似乎只有自然的解决问题的方式。


解决方案

您得太多严重此,我想不出你会需要动态地添加/删除指令任何理由,你可以很容易地,该指令里面,检查它是否应该做任何事情。所有你需要做的就是


  1. 使用弹性插件,你正在使用

  2. 使用您自己的指令重置高度/加省略号时,它不具有焦点。

因此​​,像这样将工作(而不是pretty,但只是把它在一起):
http://jsfiddle.net/ss6Y5/8/

  angular.module(应用程序,['monospaced.elastic'])。指令(dynamicClass',函数($编译){
  返回{
    适用范围:{ngModel:'='},
    要求:ngModel
    链接:功能(范围,ELT,ATTRS,ngModel){
      VAR tmpModel = FALSE;
      VAR origHeight = elt.css('高度');
      VAR HEIGHT = elt.css('高度');
      变种heightChangeIndex = 0;
      范围。$腕表('ngModel',函数(){
        如果(elt.css('高度')&GT; origHeight和放大器;&安培;!heightChangeIndex){
          heightChangeIndex = scope.ngModel.length;
          的console.log(heightChangeIndex);
        }
        否则,如果(elt.css('高度')&LT; = origHeight和放大器;&安培; elt.is(':聚焦')){
          heightChangeIndex = 0;
        }
      });
      elt.on(模糊焦点,函数(){
        VAR TMP = elt.css('高度');
        elt.css(高度,身高);
        HEIGHT = tmp目录;
      });
      elt.on('模糊',函数(){
        如果(高度&GT; origHeight){
            tmpModel = angular.copy(scope.ngModel);
            ngModel $ setViewValue(scope.ngModel.substr(0,heightChangeIndex-4)+'...')。
             。ngModel $渲染();
        }
      });
      elt.on('专注',函数(){
       如果(tmpModel.length){
         scope.ngModel = tmpModel;
         ngModel $ setViewValue(scope.ngModel)。
         。ngModel $渲染();
         tmpModel ='';
       }
        });       }
      };
    })

Requirement

  1. I want a textarea that expands or contracts vertically as the user types, alla Facebook comment box.
  2. When the textarea loses focus it contracts to one line (with ellipsis if content overflows) and re-expands to the size of the entered text upon re-focus (this functionality not found on Facebook)

Note: Clicking on the textarea should preserve caret position exactly where user clicked, which precludes any dynamic swapping of div for textarea as the control receives focus

Attempted Solution

I'm already well into an AngularJS implementation, so...

  1. Use Monospaced's Angular Elastic plugin. Nice.
  2. Two attempts...
    • Attempt A: <textarea ng-focus="isFocussed=true" ng-blur="isFocussed=false" ng-class="'msd-elastic': isFocussed"></textarea> Fails because ng-class triggers no re-$compile of the element after adding the class, so Angular Elastic is never invoked
    • Attempt B: create a custom directive that does the needed re-$compile upon class add. I used this solution by hassassin. Fails with the following problems

Attempt B problems

Here's a JSFiddle of Attempt B Note that Angular v1.2.15 is used

I. Disappearing text

  • go to the fiddle
  • type into one textarea
  • blur focus on that textarea (eg click in the other textarea)
  • focus back on the text-containing textarea
  • result: text disappears! (not expected or desired)

II. Increasingly excessive looping and eventual browser meltdown

  • click into one textarea
  • click into the other one
  • repeat the above for as long as you can until the browser stops responding and you get CPU 100% or unresponsive script warnings.
  • you'll notice that it starts out OK, but gets worse the more you click
  • I confirmed this using: XP/Firefox v27, XP/Chrome v33, Win7/Chrome v33

My investigations so far

It seems that traverseScopesLoop in AngularJS starting at line 12012 of v1.2.15, gets out of control, looping hundreds of times. I put a console.log just under the do { // "traverse the scopes" loop line and clocked thousands of loops just clicking.

Curiously, I don't get the same problems in Angular v1.0.4. See this JSFiddle which is identical, except for Angular version

I logged this as an AngularJS bug and it was closed immediately, because I'd not shown it to be a bug in Angular per se.

Questions

  1. Is there another way to solve this to avoid the pattern in Attempt B?
  2. Is there a better way to implement Attempt B? There's no activity on that stackoverflow issue after hassassin offered the solution I used
  3. Are the problems with Attempt B in my code, angular-elastic, hassassin's code, or my implementation of it all? Appreciate tips on how to debug so I can "fish for myself" in future. I've been using Chrome debug and Batarang for a half day already without much success.
  4. Does it seem sensible to make a feature request to the AngularJS team for the pattern in Attempt A? Since you can add directives by class in Angular, and ngClass can add classes dynamically, it seems only natural to solve the problem this way.

解决方案

You are severely overthinking this, and I can't think of any reason you would ever need to dynamically add / remove a directive, you could just as easily, inside the directive, check if it should do anything. All you need to do is

  1. Use the elastic plugin you are using
  2. Use your own directive to reset height / add ellipsis when it doesn't have focus.

So something like this will work (not pretty, but just threw it together): http://jsfiddle.net/ss6Y5/8/

angular.module("App", ['monospaced.elastic']).directive('dynamicClass', function($compile) {
  return {
    scope: { ngModel: '=' },
    require: "?ngModel",
    link: function(scope, elt, attrs, ngModel) {
      var tmpModel = false;
      var origHeight = elt.css('height');
      var height = elt.css('height');
      var heightChangeIndex = 0;
      scope.$watch('ngModel', function() {
        if (elt.css('height') > origHeight && !heightChangeIndex) {
          heightChangeIndex = scope.ngModel.length;
          console.log(heightChangeIndex);
        }
        else if (elt.css('height') <= origHeight && elt.is(':focus')) {
          heightChangeIndex = 0;
        }
      });
      elt.on('blur focus', function() { 
        var tmp = elt.css('height');
        elt.css('height', height);
        height = tmp;
      });
      elt.on('blur', function() {
        if (height > origHeight) {
            tmpModel = angular.copy(scope.ngModel);
            ngModel.$setViewValue(scope.ngModel.substr(0, heightChangeIndex-4) + '...'); 
             ngModel.$render();
        }
      });
      elt.on('focus', function() {
       if (tmpModel.length) {
         scope.ngModel = tmpModel;
         ngModel.$setViewValue(scope.ngModel);
         ngModel.$render();
         tmpModel = '';
       }
        });

       }
      };
    })

这篇关于AngularJS:尝试使用ngClass造成怪异的功能和性能问题,动态地应用指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆