Lists in Haskell are lazy. They're being calculated as they're being used, but not further.
The function fib1 indeed calculates the whole list, but only does it once, and only up to the index you're asking for.
The function fib2 does a lot of extra work: it potentially calculates elements many, many times over.
Just try to do it with pen and paper. For example, in the case of fib2 !! 5, the list needs to be expanded up to index 5. Calculating fib2 !! 0 and fib2 !! 1 takes little time, as they are constants. The next element, fib2 !! 2 is calculated by adding fib2 !! 0 and fib2 !! 1, and then fib2 !! 3 = fib2 !! 1 + fib2 !! 2, and so on.
BUT.
The most important thing to note here, is that the compiler and/or runtime does not memoize the fib2 function, meaning: it does not remembers previous calculations. So every time the code hits a fib2 !! n
it starts calculating it all over again, it doesn't matter how many time this has been done before, even if this happened in the very same (recursive) function call.
Regarding computational efficiency, your fib2 implementation is equivalent to this:
fib3' :: Integer -> Integer
fib3' 0 = 0
fib3' 1 = 1
fib3' n = fib3' (n - 2) + fib3' (n - 1)
fib3 :: [Integer]
fib3 = [fib3' n | n <- [0..]]
which suffers from the same inefficiency, I merely factored out the list part.
On the other hand, fib1 takes advantage of the previous calculations, by using them to avoid re-calculating them. And that's the core idea behind dynamic programming: use a data structure that can be used to store and retrieve results of previous calculations to exchange a potentially expensive recursive function call to a - hpefully - much cheap lookup.