亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Change Detection And Batch Update

陳江龍 / 3506人閱讀

摘要:如果我們不使用提供的事件系統(tǒng)定時(shí)器和,如在事件中進(jìn)行數(shù)據(jù)更新時(shí),我們需要手動(dòng)調(diào)用。

前言

在傳統(tǒng)的WEB開發(fā)中,當(dāng)與用戶或服務(wù)器發(fā)生交互時(shí),需要我們手動(dòng)獲取數(shù)據(jù)并更新DOM,這個(gè)過程是繁瑣的、易錯(cuò)的。
特別是當(dāng)頁面功能過于復(fù)雜時(shí),我們既要關(guān)注數(shù)據(jù)的變化,又要維護(hù)DOM的更新,這樣寫出來的代碼是很難維護(hù)的。
新一代的框架或庫,例如Angular、React、Vue等等讓我們的關(guān)注點(diǎn)只在數(shù)據(jù)上,當(dāng)數(shù)據(jù)更新時(shí),這些框架/庫會(huì)幫我們更新DOM。
那么這里就有兩個(gè)很重要的問題了:當(dāng)數(shù)據(jù)變化時(shí),這些框架/庫是如何感知到的?當(dāng)我們連續(xù)更新數(shù)據(jù)時(shí),這些框架/庫如何避免連續(xù)更新DOM,而是進(jìn)行批量更新?
帶著這兩個(gè)問題,我將簡要分析一下React、Angular1、Angular2及Vue的實(shí)現(xiàn)機(jī)制。

React Virtual DOM

React在更新UI的時(shí)候會(huì)根據(jù)新老state生成兩份虛擬DOM,所謂的虛擬DOM其實(shí)就是JavaScript對(duì)象,然后在根據(jù)特定的diff算法比較這兩個(gè)對(duì)象,找出不同的部分,最后根據(jù)改變的那部分進(jìn)行對(duì)應(yīng)DOM的更新。
那么React是如何知道數(shù)據(jù)變化了呢?我們通過手動(dòng)調(diào)用setState告知React我們需要更新的數(shù)據(jù)。

setState

例如我們這里有一個(gè)很簡單的組件:

class App extends React.Component {
  constructor() {
    super();
    this.handleClick = this.handleClick.bind(this);
    this.state = {
      val: 0,
    };
  }

  handleClick() {
    this.setState({val: 1});
  }

  render() {
    return (
      
{this.state.val}
) } }

當(dāng)我點(diǎn)擊按鈕的時(shí)候調(diào)用this.setState({val: 1});,React就會(huì)將this.state.val更新成1,并且自動(dòng)幫我們更新UI。
如果點(diǎn)擊按鈕的時(shí)候我們連續(xù)調(diào)用setState會(huì)怎么樣?React是連續(xù)更新兩次,還是只更新一次呢?為了更好的觀察出React的更新機(jī)制,我們將點(diǎn)擊按鈕的邏輯換成下面的代碼

this.setState({val: 1});
console.log(this.state.val);

this.setState({val: 2});
console.log(this.state.val);

打開控制臺(tái),點(diǎn)擊按鈕你會(huì)發(fā)現(xiàn)打印了0 0,同時(shí)頁面數(shù)據(jù)也更新成了2。所以我們就得出結(jié)論:React的更新并不是同步的,而是批量更新的。
我們別急著下結(jié)論,我們知道應(yīng)用程序狀態(tài)的改變主要是下面三種情況引起的:

Events - 如點(diǎn)擊按鈕

Timers - 如setTimeout

XHR - 從服務(wù)器獲取數(shù)據(jù)

我們才測試了事件這一種情景,我們試著看看其余兩種情景下state的變化,將點(diǎn)擊按鈕的邏輯換成如下代碼

setTimeout(() => {
  this.setState({val: 1});
  console.log(this.state.val);

  this.setState({val: 2});
  console.log(this.state.val);
});

打開控制臺(tái),點(diǎn)擊按鈕你會(huì)發(fā)現(xiàn)打印了1 2,相信這個(gè)時(shí)候很多人就懵了,為啥和第一種情況的輸出不一致,不是說好的批量更新的么,怎么變成連續(xù)更新了。
我們再試試第三種情景XHR,將點(diǎn)擊按鈕的邏輯換成下面的代碼

fetch("/")
  .then(() => {
    this.setState({val: 1});
    console.log(this.state.val);

    this.setState({val: 2});
    console.log(this.state.val);
  });

打開控制臺(tái),點(diǎn)擊按鈕你會(huì)發(fā)現(xiàn)打印的還是1 2,這究竟是什么情況?如果仔細(xì)觀察的話,你會(huì)發(fā)現(xiàn)上面的輸出符合一個(gè)規(guī)律:在React調(diào)用的方法中連續(xù)setState走的是批量更新,此外走的是連續(xù)更新。
為了驗(yàn)證這個(gè)的猜想,我們試著在React的生命周期方法中連續(xù)調(diào)用setState

componentDidMount() {
  this.setState({val: 1});
  console.log(this.state.val);

  this.setState({val: 2});
  console.log(this.state.val);
}

打開控制臺(tái)你會(huì)發(fā)現(xiàn)打印了0 0 ,更加驗(yàn)證了我們的猜想,因?yàn)樯芷诜椒ㄒ彩荝eact調(diào)用的。到此我們可以得出這樣一個(gè)結(jié)論:

在React調(diào)用的方法中連續(xù)setState走的是批量更新,此外走的是連續(xù)更新

說到這里,有些人可能會(huì)有這樣一個(gè)疑惑

handleClick() {
  setTimeout(() => {
    this.setState({val: 1});
    console.log(this.state.val);

    this.setState({val: 2});
    console.log(this.state.val);
  });
}

setTimeout也是在handleClick當(dāng)中調(diào)用的,為啥不是批量更新呢?
setTimeout確實(shí)是在handleClick當(dāng)中調(diào)用的,但是兩個(gè)setState可不是在handleClick當(dāng)中調(diào)用的,它們是在傳遞給setTimeout的參數(shù)——匿名函數(shù)中執(zhí)行的,走的是事件輪詢,不要弄混了。

綜上,說setState是異步的需要加一個(gè)前提條件,在React調(diào)用的方法中執(zhí)行,這時(shí)我們需要通過回調(diào)獲取到最新的state

this.setState({val: 1}, () => {
  console.log(this.state.val);
});

相信這個(gè)道理大家不難理解,因?yàn)槭录蜕芷诜椒ǘ际荝eact調(diào)用的,它想怎么玩就怎么玩。那么React內(nèi)部是如何實(shí)現(xiàn)批量更新的呢?

事務(wù)

React當(dāng)中事務(wù)最主要的功能就是拿到一個(gè)函數(shù)的執(zhí)行上下文,提供鉤子函數(shù)。啥意思?看個(gè)例子

import Transaction from "react/lib/Transaction";

const transaction = Object.assign({}, Transaction.Mixin, {
  getTransactionWrappers() {
    return [{
      initialize() {
        console.log("initialize");
      },
      close() {
        console.log("close");
      }
    }];
  }
});
transaction.reinitializeTransaction();
const fn = () => {
  console.log("fn");
};
transaction.perform(fn);

執(zhí)行這段代碼,打開控制臺(tái)會(huì)發(fā)現(xiàn)打印如下

initialize
fn
close

事務(wù)最主要的功能就是可以Wrapper一個(gè)函數(shù),通過perform調(diào)用,在執(zhí)行這個(gè)函數(shù)之前會(huì)先調(diào)用initialize方法,等這個(gè)函數(shù)執(zhí)行結(jié)束了在調(diào)用close方法。事務(wù)的核心代碼很短,只有五個(gè)方法,有興趣的可以去看下。
結(jié)合上面setState連續(xù)調(diào)用的情況,我們可以大致猜出React的更新機(jī)制,例如執(zhí)行handleClick的時(shí)候

let updating = false;

setState = function() {
  if(updating){
    // 緩存數(shù)據(jù)
  }else {
    // 更新
  }
}

const transaction = Object.assign({}, Transaction.Mixin, {
  getTransactionWrappers() {
    return [{
      initialize() {
        updating = true;
      },
      close() {
        updating = false;
        // 更新
      }
    }];
  }
});
transaction.reinitializeTransaction();

transaction.perform(instance.handleClick);

我們再來深入一下setState的實(shí)現(xiàn),看看是不是這么回事,下面是setState會(huì)調(diào)用到的方法

function enqueueUpdate(component) {
  ensureInjected();

  if (!batchingStrategy.isBatchingUpdates) {
    batchingStrategy.batchedUpdates(enqueueUpdate, component);
    return;
  }

  dirtyComponents.push(component);
  if (component._updateBatchNumber == null) {
    component._updateBatchNumber = updateBatchNumber + 1;
  }
}

看變量名稱我們也都能猜到大致功能,通過batchingStrategy.isBatchingUpdates來決定是否進(jìn)行batchedUpdates(批量更新),還是dirtyComponents.push(緩存數(shù)據(jù)),結(jié)合事務(wù),React的批量更新策略應(yīng)該是這樣的

const transaction = Object.assign({}, Transaction.Mixin, {
  getTransactionWrappers() {
    return [{
      initialize() {
        batchingStrategy.isBatchingUpdates = true;
      },
      close() {
        batchingStrategy.isBatchingUpdates = false;
      }
    }];
  }
});
transaction.reinitializeTransaction();

transaction.perform(instance.handleClick);
transaction.perform(instance.componentDidMount);
小結(jié)

React通過setState感知到數(shù)據(jù)的變化,通過事務(wù)進(jìn)行批量更新,通過Virtual DOM比較進(jìn)行高效的DOM更新。

Angular1 Dirty Checking

Angular1通過臟值檢測去更新UI,所謂的臟值檢測其實(shí)指Angular1從$rootScope開始遍歷所有scope的$$watchers數(shù)組,通過比較新老值來決定是否更新DOM??磦€(gè)例子

{{val}}
angular.module("myApp", [])
  .controller("MyCtrl", function($scope) {
    $scope.val = 0;
  });

這個(gè)是一個(gè)很簡單的數(shù)據(jù)渲染的例子,我們在控制臺(tái)打印下scope,看下$$watchers的內(nèi)容

因?yàn)橹挥衯al一個(gè)表達(dá)式所以$$watchers長度只有1

eq 是否進(jìn)行數(shù)據(jù)的深度比較

exp 檢測出錯(cuò)時(shí)log所用

fn 更新DOM

get 獲取當(dāng)前數(shù)據(jù)

last 老的數(shù)據(jù)

那么Angular1是如何感知到數(shù)據(jù)變化的呢?

$apply

Angular1通過調(diào)用$scope.$apply()進(jìn)行臟值檢測的,核心代碼如下

遍歷所有scope的$$watchers,通過get獲取到最新值同last比較,值變化了則通過調(diào)用fn更新DOM。有人可能會(huì)疑惑了,我們在編碼的時(shí)候并沒有調(diào)用$apply,那么UI是怎么更新的呢?
實(shí)際上是Angular1幫我們調(diào)用了,我們看下ng事件的源碼實(shí)現(xiàn)

forEach(
  "click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),
  function(eventName) {
    var directiveName = directiveNormalize("ng-" + eventName);
    ngEventDirectives[directiveName] = ["$parse", "$rootScope", function($parse, $rootScope) {
      return {
        restrict: "A",
        compile: function($element, attr) {
          var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true);
          return function ngEventHandler(scope, element) {
            element.on(eventName, function(event) {
              var callback = function() {
                fn(scope, {$event:event});
              };
              if (forceAsyncEvents[eventName] && $rootScope.$$phase) {
                scope.$evalAsync(callback);
              } else {
                scope.$apply(callback);
              }
            });
          };
        }
      };
    }];
  }
);

很明顯調(diào)用了$scope.$apply,我們再看下$timeout的源碼

function timeout(fn, delay, invokeApply) {
  // ...
  
  timeoutId = $browser.defer(function() {
    try {
      deferred.resolve(fn.apply(null, args));
    } catch (e) {
      deferred.reject(e);
      $exceptionHandler(e);
    }
    finally {
      delete deferreds[promise.$$timeoutId];
    }

    if (!skipApply) $rootScope.$apply();
  }, delay);

  // ...
}

最后也調(diào)用了$rootScope.$apply,$http服務(wù)實(shí)際上也做了同樣的處理,說到這,三種引起應(yīng)用程序狀態(tài)變化的情景,Angular1都做了封裝,所以我們寫代碼的時(shí)候不需要手動(dòng)去調(diào)用$apply了。
新手常碰到的一個(gè)問題就是為啥下面的代碼不起作用

$("#btn").on("click", function() {
  $scope.val = 1;
});

因?yàn)槲覀儧]有用Angular1提供的事件系統(tǒng),所以Angular1沒法自動(dòng)幫我們調(diào)用$apply,這里我們只能手動(dòng)調(diào)用$apply進(jìn)行臟值檢測了

$("#btn").on("click", function() {
  $scope.val = 1;
  $scope.$apply();
});
小結(jié)

在Angular1中我們是直接操作數(shù)據(jù)的,這個(gè)過程Angular1是感知不到的,只能在某個(gè)點(diǎn)調(diào)用$apply進(jìn)行臟值檢測,所以默認(rèn)就是批量更新。如果我們不使用Angular1提供的事件系統(tǒng)、定時(shí)器和$http,如在jQuery事件中進(jìn)行數(shù)據(jù)更新時(shí),我們需要手動(dòng)調(diào)用$apply。

Angular2

當(dāng)數(shù)據(jù)變化時(shí),Angular2從根節(jié)點(diǎn)往下遍歷進(jìn)行更新,默認(rèn)Angular2深度遍歷數(shù)據(jù),進(jìn)行新老數(shù)據(jù)的比較來決定是否更新UI,這點(diǎn)和Angular1的臟值檢測有點(diǎn)像,但是Angular2的更新沒有副作用,是單向數(shù)據(jù)流。
同時(shí)大家也不用擔(dān)心性能問題

It can perform hundreds of thousands of checks within a couple of milliseconds. This is mainly due to the fact that Angular generates VM friendly code — by Pascal Precht

Angular2也提供了不同的檢測策略,例如

@Component({
  selector: "child",
  template: `
    
{{data.name}}
`, changeDetection: ChangeDetectionStrategy.OnPush })

設(shè)置了變化檢測策略為OnPush的組件不走深度遍歷,而是直接比較對(duì)象的引用來決定是否更新UI。

Zone.js

Angular2同Angular1一樣都是直接操作數(shù)據(jù)的,框架都無法直接感知數(shù)據(jù)的變化,只能在特定的時(shí)機(jī)去做批量更新。
Angular1是通過封裝自動(dòng)調(diào)用$apply,但是存在手動(dòng)調(diào)用的場景,為了解決這個(gè)問題,Angular2沒有采用1的實(shí)現(xiàn)機(jī)制,轉(zhuǎn)而使用了Zone.js。

Zone.js最主要的功能就是可以獲取到異步方法執(zhí)行的上下文。什么是執(zhí)行上下文?例如

function foo() {
  bar();
}

foo();
baz();

同步的方法我們可以明確的知道bar什么時(shí)候執(zhí)行和結(jié)束,可以在bar結(jié)束的時(shí)候調(diào)用baz。但是對(duì)于異步方法,例如

function foo() {
  bar();
}

setTimeout(foo);
baz();

我們無法知道foo是什么時(shí)候開始執(zhí)行和結(jié)束,因?yàn)樗钱惒降?。如果調(diào)用改成這樣

function foo() {
  bar();
}

setTimeout(function() {
  foo();
  baz();
});

通過添加一層wrapper函數(shù),不就可以保證在foo執(zhí)行完調(diào)用baz了么。Zone.js主要重寫了瀏覽器所有的異步實(shí)現(xiàn),如setTimeout、XMLHttpRequest、addEventListener等等,然后提供鉤子函數(shù),

new Zone().fork({
  beforeTask: function() {
    console.log("beforeTask");
  },
  afterTask: function() {
    console.log("afterTask");
  }
}).run(function mainFn() {
  console.log("main exec");
  setTimeout(function timeoutFn() {
    console.log("timeout exec");
  }, 2000);
});

打開控制臺(tái),你會(huì)發(fā)現(xiàn)打印如下

beforeTask
main exec
afterTask

beforeTask
timeout exec
afterTask

Zone.js捕獲到了mainFn和timeoutFn執(zhí)行的上下文,這樣我們就可以在每個(gè)task執(zhí)行結(jié)束后執(zhí)行更新UI的操作了。Angular2更新機(jī)制大體如下

class ApplicationRef {
  changeDetectorRefs:ChangeDetectorRef[] = [];

  constructor(private zone: NgZone) {
    this.zone.onTurnDone
      .subscribe(() => this.zone.run(() => this.tick());
  }

  tick() {
    this.changeDetectorRefs
      .forEach((ref) => ref.detectChanges());
  }
}

ngZone是對(duì)Zone.js的服務(wù)封裝,Angular2會(huì)在每個(gè)task執(zhí)行結(jié)束后觸發(fā)更新。

小結(jié)

由于Zone.js的存在,我們可以在任何場景下更新數(shù)據(jù)而無需手動(dòng)調(diào)用檢測,Angular2也是批量更新。

Vue

Vue模板中每個(gè)指令/數(shù)據(jù)綁定都有一個(gè)對(duì)應(yīng)的watcher對(duì)象,當(dāng)數(shù)據(jù)變化時(shí),會(huì)觸發(fā)watcher重新計(jì)算并更新相應(yīng)的DOM。

setter

Vue通過Object.defineProperty將data轉(zhuǎn)化為getter/setter,這樣我們直接修改數(shù)據(jù)時(shí),Vue就能夠感知到數(shù)據(jù)的變化了,這個(gè)時(shí)候就可以進(jìn)行UI更新了。
如果我們連續(xù)更新數(shù)據(jù),Vue會(huì)立馬更新DOM還是和React一樣先緩存下來等待狀態(tài)穩(wěn)定進(jìn)行批量更新呢?我們還是從應(yīng)用程序狀態(tài)改變的三種情景來看

var vm = new Vue({
  el: "#app",
  data: {
    val: 0
  },
  methods: {
    onClick: function() {
      vm.val = 1;
      console.log(vm.$el.textContent);

      vm.val = 2;
      console.log(vm.$el.textContent);
    }
  }
});

打開控制臺(tái),點(diǎn)擊按鈕會(huì)發(fā)現(xiàn)打印0 0,說明Vue并不是立馬更新的,走的是批量更新。由于事件系統(tǒng)用的Vue提供的,是可控的,我們再看下定時(shí)器下執(zhí)行的情況

var vm = new Vue({
  el: "#app",
  data: {
    val: 0
  }
});

setTimeout(function() {
  vm.val = 1;
  console.log(vm.$el.textContent);

  vm.val = 2;
  console.log(vm.$el.textContent);
});

打開控制臺(tái),點(diǎn)擊按鈕會(huì)發(fā)現(xiàn)依舊打印了0 0,有人可能就疑惑了Vue是不是跟Angular2一樣也修改了異步方法的原生實(shí)現(xiàn)呢?
Vue并沒有這么干,不用于React、Angular1/2捕獲異步方法上下文去更新,Vue采用了不同的更新策略。

異步更新隊(duì)列

每當(dāng)觀察到數(shù)據(jù)變化時(shí),Vue就開始一個(gè)隊(duì)列,將同一事件循環(huán)內(nèi)所有的數(shù)據(jù)變化緩存起來。如果一個(gè)watcher被多次觸發(fā),只會(huì)推入一次到隊(duì)列中。

等到下一次事件循環(huán),Vue將清空隊(duì)列,只進(jìn)行必要的DOM更新。在內(nèi)部異步隊(duì)列優(yōu)先使用MutationObserver,如果不支持則使用setTimeout(fn, 0) — vuejs.org

這是官方文檔上的說明,抽象成代碼就是這樣的

var waiting = false;
var queue = [];

function setter(val) {
  if(!waiting) {
    waiting = true;
    
    setTimeout(function() {
      queue.forEach(function(item) {
        // 更新DOM
      });
      
      waiting = false;
      queue = [];
    }, 0);
  } else {
    queue.push(val);
  }
}

setter(1);
setter(2);

Vue是通過JavaScript單線程的特性,利用事件隊(duì)列進(jìn)行批量更新的。

config.async

我們可以通過將Vue.config.async設(shè)置為false,關(guān)閉異步更新機(jī)制,讓它變成同步更新,看下面的例子

Vue.config.async = false;

var vm = new Vue({
  el: "#app",
  data: {
    val: 0
  }
});

setTimeout(function() {
  vm.val = 1;
  console.log(vm.$el.textContent);

  vm.val = 2;
  console.log(vm.$el.textContent);
});

打開控制臺(tái)你會(huì)發(fā)現(xiàn)打印了1 2,但是最好別這么干

如果關(guān)閉了異步模式,Vue 在檢測到數(shù)據(jù)變化時(shí)同步更新 DOM。在有些情況下這有助于調(diào)試,但是也可能導(dǎo)致性能下降,并且影響 watcher 回調(diào)的調(diào)用順序。async: false不推薦用在生產(chǎn)環(huán)境中 — vuejs.org

總結(jié)

自此我們分析了React、Angular1/2和Vue的變化檢測以及批量更新的策略。
React和Angular1/2都是通過獲取執(zhí)行上下文來進(jìn)行批量更新,但是React和Angular1支持的并不徹底,都有各自的問題。
Angular2可以適配任意情況,但是是通過篡改了原生方法實(shí)現(xiàn)的。Vue則通過ES5特性和JavaScript單線程的特性進(jìn)行批量更新,無需特殊處理,可以滿足任何情況。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/80450.html

相關(guān)文章

  • TensorFlow Object Detection API Custom Object Hang

    摘要: TensorFlow Object Detection API Hangs On?—?Training and Evaluating using Custom Object Detector *The links to all files updated and the GitHub repo address added. First of All Install TensorF...

    fevin 評(píng)論0 收藏0
  • Change Detection系列一】$digest 在Angular新版本中重生

    摘要:感謝您的閱讀如果喜歡這篇文章請(qǐng)點(diǎn)贊。它對(duì)我意義重大,它能幫助其他人看到這篇文章。對(duì)于更高級(jí)的文章,你可以在或上跟隨我。 I’ve worked with Angular.js for a few years and despite the widespread criticism I think this is a fantastic framework. I’ve started w...

    legendaryedu 評(píng)論0 收藏0
  • 《DeepLearning.ai 深度學(xué)習(xí)筆記》發(fā)布,黃海廣博士整理

    摘要:在這堂課中,學(xué)生將可以學(xué)習(xí)到深度學(xué)習(xí)的基礎(chǔ),學(xué)會(huì)構(gòu)建神經(jīng)網(wǎng)絡(luò),包括和等。課程中也會(huì)有很多實(shí)操項(xiàng)目,幫助學(xué)生更好地應(yīng)用自己學(xué)到的深度學(xué)習(xí)技術(shù),解決真實(shí)世界問題。 深度學(xué)習(xí)入門首推課程就是吳恩達(dá)的深度學(xué)習(xí)專項(xiàng)課程系列的 5 門課。該專項(xiàng)課程最大的特色就是內(nèi)容全面、通俗易懂并配備了豐富的實(shí)戰(zhàn)項(xiàng)目。今天,給大家推薦一份關(guān)于該專項(xiàng)課程的核心筆記!這份筆記只能用兩個(gè)字形容:全面! showImg(...

    wenhai.he 評(píng)論0 收藏0
  • 這5篇文章將使你成為一個(gè)Angular Change Detection專家。

    摘要:編寫工作首先介紹了一個(gè)稱為的內(nèi)部組件表示,并解釋了變更檢測過程在視圖上運(yùn)行。本文主要由兩部分組成第一部分探討錯(cuò)誤產(chǎn)生的原因,第二部分提出可能的修正。它對(duì)我意義重大,它能幫助其他人看到這篇文章。 在過去的8個(gè)月里,我大部分空閑時(shí)間都是reverse-engineering Angular。我最感興趣的話題是變化檢測。我認(rèn)為它是框架中最重要的部分,因?yàn)樗?fù)責(zé)像DOM更新、輸入綁定和查詢列表...

    Coly 評(píng)論0 收藏0
  • [譯] $digest 在 Angular 中重生

    摘要:但如果一個(gè)組件在生命周期鉤子里改變父組件屬性,卻是可以的,因?yàn)檫@個(gè)鉤子函數(shù)是在更新父組件屬性變化之前調(diào)用的注即第步,在第步之前調(diào)用。 原文鏈接:Angular.js’ $digest is reborn in the newer version of Angular showImg(https://segmentfault.com/img/remote/146000001468785...

    incredible 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<