AngularJS и метатеги в режиме SPA?

Кто-нибудь из вас уже выяснил элегантный способ работы с мета-тегами с AngularJS в режиме SPA?

В базовом шаблоне у меня есть метатеги по умолчанию. Для каждого маршрута каждый контроллер загружает другое представление с различным содержимым. Очень нормально. Но как я могу изменить метатеги для каждой из этих страниц?

Кроме того, некоторые страницы должны иметь больше метатегов, а другие - меньше. Например, страницы с содержимым должны иметь дополнительные метатеги для обмена социальными сетями. Другие чувствительные страницы должны иметь мета-теги, не требующие отслеживания, чтобы запретить индексирование страницы роботами.

Любопытно, как опытные справляются с этим?

Ответ 1

Образец, который я использовал, исходит из проекта ngBoilerplate. В этом шаблоне есть общий контроллер приложений, который имеет дело с "глобальной" областью, включая метатеги.

Контроллеры отдельных страниц могут генерировать событие, когда они перемещаются, $locationChangeSuccess, если вы используете маршрутизатор по умолчанию.

Контроллер приложения прослушивает это событие и использует его для обновления заголовка страницы в случае ngBoilerplate: https://github.com/ngbp/ngbp/blob/v0.3.2-release/src/app/app.js#L17-L21

Тем не менее, вам нечего мешать вам испускать объект с любой метатекой, которую вам нравится, а затем иметь прослушиватель для этого события.

// on your individual app pages goes something like this
function SomePageController($scope) {
   // the event gets fired when the page is loaded and the controller is called.
   $scope.$emit('newPageLoaded', { 'title': 'Some Page', 'description': 'blah' });
}

// your overall app controller
function AppController($scope) {
    $scope.metadata = {
        'title': 'default title',
        'description': 'default description',
    };

    // whenever a controller emits the newPageLoaded event, we update the app metadata
    $scope.$on('newPageLoaded', function(event, metadata) {
        $scope.metadata = metadata
    });
}

Затем в вашем заголовке вы можете сделать что-то вроде этого:

<html ng-app="myApp" ng-controller="AppController">
<head>
    <meta title="{{ metadata.title }}" ng-if="metadata.title" />
    <meta description="{{ metadata.description}}" ng-if="metadata.description" />
    <meta whatever="{{ metadata.whatever}}" ng-if="metadata.whatever" />
</head>

Я не тестировал этот код, поэтому могут быть ошибки, но я думаю, что общий принцип звучит.

Примечание: обмен социальными медиа

В вашем вопросе вы упомянете пример использования тегов для обмена социальными сетями. Я предполагаю, что вы имеете в виду что-то вроде открытого графика или твиттера и т.д.

В этом случае важно знать, что в настоящее время сканеры, которые используют эти сайты (facebook, twitter, pinterest и т.д.), не будут выполнять ваш JavaScript и, таким образом, не смогут читать любые метатеги, которые вы динамически заполняете с помощью Angularjs.

Я написал сообщение в блоге об этой проблеме с предлагаемым решением: http://www.michaelbromley.co.uk/blog/171/enable-rich-social-sharing-in-your-angularjs-app/