Oh, surely you can. I have made an engine that actually does this ('Inferno'). But, as you illustrate, this can become rather complex, and I am not sure that for orthodox Chess it would pay off. The engine is for Tenjiku Shogi, though, a game on a 16x16 board where each player starts with 78 pieces. So there it would take massive effort to recalculate the mobility of every piece from scratch, and incremental techniques become extremely competitive, even those that are rather cumbersome.
It is also true that incremental techniques can be highly cooperative, such that when you do everything incrementally, the individual tasks take much less effort, by drawing on each other's results. Inferno keeps track of distances between occupied squares along the orthogonals and diagonals ('view distances'), the captures to each square ('attack map') and the mobility per piece (in the piece list), all updated incrementally. When the occupancy of a square changes, the attack map tells you directly which pieces where attacking it, and thus need a mobility change (which you apply to the total as well). You know how many moves they gain or lose (for sliders) by consulting the view distance in the opposit direction. You can also displace their attack between the given square and the downstream target in the attack map. When a piece gets captured, or moves away, you can subtract its stored mobility from the total, and delete its captures from the attack map. The view-distance table brings you directly to the squares they were attacking (if these were in the move's range), no matter how far away these were. The same for the moves of the moved piece in the new location. So you only have to generate captures for the moved piece from its new location (and calculate its new mobility as a side effect), and for the piece in its old location, and the capture victim (if any), to delete those. On UnMake you have to do that again (to apply the opposit change). So you have to generate moves for only 4 (or 6 on a capture) pieces, rather than for all. (And 'all' can be 156, in Inferno's case!) And the slider captures can be calculated without the intervening non-captures, as the view distance table directly tells you where the capture goes, and how many empty square that skips over (to add to the mobility).
This entire structure is also used for move generation: by generating the captures from the attack map you can generate them in order of victim value, running through the piece list top-down to see where the victims are, looking in the attack map what attacks them, and again in the piece list where that is located. This saves a lot of work on move sorting. As well as on move generation, as when the capture of the most-valuable victim produces a beta cutoff, you never even get to generate captures on any other victim. So there is no need to first generate all captures, and then sort them MVV-wise.