Like this:
df |>
  @vlplot(:bar,
    x={:Sex, title=nothing},
    y={:Freq, title=nothing}, 
    color={:Eye, title=nothing}, 
    column={:Hair, title=nothing}
  )
The trick is that you now pass a composite value in curly brackets {} to x etc., and then you can configure more details there. All the config options for axis title are described here.
I think you need to configure your scales a bit for that. It might be enough to configure the scale to not try to come up with nice numbers on the axis like this (documented here):
 df |>
  @vlplot(:bar, x=:Sex, y={:Freq, scale={nice=false}}, color=:Eye, column=:Hair)
But you might also have to additionally configure your domain:
 df |>
  @vlplot(:bar,
    x=:Sex,
    y={:Freq, scale={domain=[0,100], nice=false}},
    color=:Eye, column=:haircut_woman
  )
I’m not entirely sure why this doesn’t work automatically. I suspect, that maybe there is a small numerical rounding error that pushes some value just slightly above 100, and then vega-lite thinks it needs to extend the axis or something like that…
You can specify a sort property for the encoding, documented here:
 df |>
  @vlplot(:bar,
    x=:Sex,
    y=:Freq,
    color=:Eye,
    column={:haircut_woman, sort=["Red", "Blond", "Brown", "Black"]}
  )