Angular 模型变量在 DOM 更新之前更新得太早,导致 UI 成为 "behind"?

Angular model variable updating too early before DOM updates, causing UI to be "behind"?

我正在尝试构建一个 Angular 标签指令,其功能与 Stack Overflow 的标签输入表单不太相似。它使用带边框的 div 来创建表单的错觉,然后 div 在输入字段的左侧包含标签列表,您可以在其中键入:

<div class="wrapper">
    <div class="tag-wrapper">
        <div class="tags" ng-repeat="tag in selectedTags">
            <div>
                [[ tag.name ]]
                <span class="remove" ng-click="removeTag(tag)"></span>
            </div>
        </div>
    </div>
    <input type="text" class="tag-input"
           ng-model="tagInput"
           ng-style="{ width: inputLength + 'px'}"
           ng-keypress="tagInputKeyPress($event)"
           ng-keyup="updateSuggestionList()"
           ng-focus="toggleSuggestionVisibility()"
           ng-blur="toggleSuggestionVisibility()" />
</div>

请注意,我使用 [[]] 作为 Angular 的插值提供程序,因为我有另一个模板引擎已经在使用 {{}}.

当在输入中按下一个键时,它会运行一个函数来检查该键是返回space还是回车或space到create/remove标签:

$scope.tagInputKeyPress = function(event) {
    // Currently using jQuery.event.which to detect keypresses, keyCode is deprecated, use KeyboardEvent.key eventually:
    // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key

    // event.key == ' ' || event.key == 'Enter'
    if (event.which == 32 || event.which == 13) {
        event.preventDefault();

        // Remove any rulebreaking chars
        var tag = $scope.tagInput;
        tag = tag.replace(/["']/g, "");
        // Remove whitespace if present
        tag = tag.trim();

        $scope.createTag(tag);

    // event.key == 'Backspace'
    } else if (event.which == 8 && $scope.tagInput == "") {
        event.preventDefault();

        // grab the last tag to be inserted (if any) and put it back in the input
        if ($scope.selectedTags.length > 0) {
            $scope.tagInput = $scope.selectedTags.pop().name;
        }
    }
    $scope.inputLength = $(element).find('input.tag-input').parent().innerWidth() - $(element).find('.tag-wrapper').outerWidth() - 1;

    return true;
};

我遇到的问题是 return 语句之前的最后一行。 这样做的目的 是重新计算 .tag-wrapper 元素的宽度并通过 ng-style ng-style [调整 input 元素的宽度以适应=71=]:

ng-style="{ width: inputLength + 'px'}"

但是,按照目前的情况,输入长度总是比UI落后一步,导致输入溢出。这是因为:

  1. 它首先在 selectedTags 列表中添加一个新标签。
  2. 计算.tag-wrapper的宽度。
  3. 让原按键事件通过return是真的
  4. Angular 的摘要循环运行并将新标签附加到 DOM。 现在.tag-wrapper的宽度变大了,input溢出了

这是一个例子:

现在,第 4 步在第 2 步之后发生。我需要第 2 步在第 4 步之后发生

我怎样才能做到这一点?

您将 createTag 方法修改为具有回调,并在回调中设置 inputLength。

替代方法:将 inputLength 的设置包装在 $timeout 内,以强制在接下来的摘要调用中执行该行。