Yes, you can!
FirstThe first thing you need to do is to add the entire cached content into a single variable:
{% set navigation %}
{% cache globally for 3 years %}
{# YOUR CACHED CONTENT #}
{% endcache %}
{% endset %}
Then you need to add some dummy placeholder tags on your <li>
tag and your <a>
tag which thethen can be used by |replace
filter then can run it'sto make the replacement on.
For <li>
<li class="{{ entry.hasDescendants() ? 'has-dropdown' : "" }} data-class-{{entry.slug}}">
For <a>
(You need to modify this for each different entry type)
<a href="{{ entry.url}}" data-url="{{ entry.url }}">{{ entry.title }}</a>
After all this you'll have special "tags" in your cached content that you can run some replacement on, like this:
{{ navigation|replace({('data-url="' ~ craft.request.getUrl() ~ '"'): 'class="active"'})|replace({('data-class-' ~ craft.request.segment(1)'"'): 'active'})|raw %}}
I'm unsure if youYou can run two |replace|replace
filters after each other, but I think you can. If you can'tcould just split them up into two variablessteps. Also, this code is untested - I just wrote it from my head so please be aware there might be some typos etc..