.data () do jQuery faz algumas coisas, mas não adiciona os dados ao DOM como um atributo. Ao usá-lo para obter um atributo de dados, a primeira coisa que faz é criar um objeto de dados jQuery e define o valor do objeto para o atributo de dados. Depois disso, é essencialmente dissociado do atributo data.
Exemplo:
<div data-foo="bar"></div>
Se você pegasse o valor do atributo usando .data('foo'), ele retornaria "bar" conforme o esperado. Se você alterar o atributo usando .attr('data-foo', 'blah')e depois usar .data('foo')para capturar o valor, ele retornará "bar" mesmo que o DOM indique data-foo="blah". Se você .data()definir o valor, ele mudará o valor no objeto jQuery, mas não no DOM.
Basicamente, .data()é para definir ou verificar o valor dos dados do objeto jQuery. Se você estiver verificando e ele ainda não tiver um, ele cria o valor com base no atributo de dados que está no DOM. .attr()serve para definir ou verificar o valor do atributo do elemento DOM e não tocará no valor dos dados do jQuery. Se você precisar que ambos mudem, use ambos .data()e .attr(). Caso contrário, fique com um ou outro.
.data()menos que você realmente tenha um motivo para usá-lo.attr().