Home  >  Article  >  Web Front-end  >  angular1 study notes, which contain the view model synchronization process in angularjs

angular1 study notes, which contain the view model synchronization process in angularjs

寻∝梦
寻∝梦Original
2018-09-07 17:28:251361browse

This is a personal understanding note of angularjs. Here is the synchronization process of the view model. Let me write it for everyone to see. Now let us enter this article together

The thing originated from a small problem encountered in the project: the project requires an input box to enter the quantity of products sold, and the handling fee is calculated based on the input data after the user inputs. Naturally I used ng-model and ng-change, and generally there is no problem. The problem is: there is a button under the input box to sell all. Clicking this button will automatically set the selling amount. But in fact, the program does not calculate the handling fee at this time.
After troubleshooting and consulting the documentation, I found that it was a problem with ng-change. Angular's official document about ng-change prompts:
The expression is not evaluated when the value change is coming from the model.
The source code of ng-change is also very simple:

  var ngChangeDirective = valueFn({
      restrict: 'A',
      require: 'ngModel',
      link: function(scope, element, attr, ctrl) {
        ctrl.$viewChangeListeners.push(function() {
          scope.$eval(attr.ngChange);
        });
      }
    });

From We can also see that ng-change only monitors the view to the model. So when we modify the variables of ng-model directly in js, ng-change will not be triggered.
The problem is found, and the solution is not difficult. Just abandon ng-change and use $watch instead.
But is this the end? What exactly does a variable go through from the view change to the synchronous update to the model? The other way around, is it the same?
So I took a look at the source code of ng-model again, and found nothing. However, I unexpectedly learned this:
ng-change is executed before the model value changes. There is such a function in the ng-model source code:

function setupModelWatcher(ctrl) {
  // model -> value
  // !!!Note: we cannot use a normal scope.$watch as we want to detect the following:
  // !!!1. scope value is 'a'
  // !!! 2. user enters 'b'
  // !!!3. ng-change kicks in and reverts scope value to 'a'
  //    -> scope value did not change since the last digest as
  //       ng-change executes in apply phase
  // !!!4. view should be changed back to 'a'
  ctrl.$$scope.$watch(function ngModelWatch(scope) {
    var modelValue = ctrl.$$ngModelGet(scope);

    // if scope model value and ngModel value are out of sync
    // This cannot be moved to the action function, because it would not catch the
    // case where the model is changed in the ngChange function or the model setter
    if (modelValue !== ctrl.$modelValue &&
      // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator
      // eslint-disable-next-line no-self-compare
      (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)
    ) {
      ctrl.$$setModelValue(modelValue);
    }

    return modelValue;
  });
}

The comments inside explain why the variable model value must be modified after ng-change, because the variable value is likely to be modified back in ng-change. , so that the variable value does not actually change (you really have to take all situations into consideration when writing an api!!). Regarding this and the previous questions, here is a demo code: http://php.cn/course/47.html

Since there is nothing to gain from looking at the source code, then go search for articles online. I found a good article during this process. This article introduces

$formatters,$parsers,$render and$setViewValue. I won’t introduce it here anymore. If you need to learn, the original text is here: http://php.cn/course/47.html

I also found one that is very easy when learning $setViewValue The pitfall: When calling $setViewValue, if the parameter is a reference variable, then if the reference variable address has not changed, the variable is considered unchanged, such as var map = ['er', 'tr '];Then $setViewValue does not think that the map value has changed after map.pop();. For details on this, please see my answer to this question. (If you want to know more, go to the PHP Chinese website AngularJS Development Manual to learn)

ng-model also has this problem, which can be seen in the ng-model source code comments:

However, custom controls might also pass objects to this method. In
this case, we should make a copy of the object before passing it to
$setViewValue. This is because ngModel does not perform a deep
watch of objects, it only looks for a change of identity.

If you only change the property of the object then ngModel will not
realize that the object has changed and will not invoke the $parsers
and $validators pipelines.

You can also see from the above that there is actually a variable There are more than $formatters and $parsers pipelines for updating from view to model and model to view, so what others are there?

After checking a lot of information, I found a very clear explanation: https://stackoverflow.com/que... In fact, you only need to read the answer to the question. The question is too long. . .
There is a demo link in this answer. I copied it and made small modifications and put it at this address: http://php.cn/course/47.html. This demo clearly shows the variable updates. The process will not be repeated in detail. Here we only summarize the results as follows:
From model to view:
Model value modification----> $formattersPipeline--- -> $renderfunction----> $validators ----> $watchfunction

From view to model:
view value modification----> $setViewValuefunction----> $parserspipeline----> $validators ----> $viewChangeListenerFunction----> $watchFunction
We can also directly call the $setViewValue function Directly change the value of $viewValue, the process will be the same as above.
Note that when using $setViewValue, you must be wary of parameters that refer to variables. This pitfall has also been mentioned above.

This article does not specifically introduce the $formatters and $parsers pipelines. For this part, you can refer to the link given in the article

Okay, this article ends here (if you want to see more, go to the PHP Chinese website AngularJS User Manual to learn). If you have any questions, you can leave a message below.

The above is the detailed content of angular1 study notes, which contain the view model synchronization process in angularjs. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn