Javascript 如何在<;头>;文件的一部分?

Javascript 如何在<;头>;文件的一部分?,javascript,html,angularjs,angularjs-directive,html-head,Javascript,Html,Angularjs,Angularjs Directive,Html Head,我不熟悉angular.js。我试图创建一个指令,在html文档的部分添加一些标题和元标记,但遇到了一些问题 我的index.html文档如下所示: <!DOCTYPE html> <html ng-app="myApp"> <head> <meta charset="UTF-8"> <base href="/"> <seo-title></seo-title> <scrip

我不熟悉
angular.js
。我试图创建一个指令,在html文档的
部分添加一些标题和元标记,但遇到了一些问题

我的
index.html
文档如下所示:

<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <meta charset="UTF-8">
    <base href="/">
    <seo-title></seo-title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.1/angular.min.js"></script>
    <script src="https://code.angularjs.org/1.4.1/angular-route.min.js"></script>
    <script src="/incl/js/myApp.js"></script>
</head>
<body >
    <div ng-view></div>
</body>
</html>

我的javascript是:

var app = angular.module ('myApp', ['ngRoute']);

app.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {

    $routeProvider
        .when('/', { templateUrl: 'routes/home.html'})
        .when('/pageA', { templateUrl: 'routes/pageA.html'})
        .when('/pageB', { templateUrl: 'routes/pageB.html'})
        .otherwise({ redirectTo: '/' });

    $locationProvider.html5Mode({
        enabled: true
    });

}]);

app.directive('seoTitle', function() {
    return {
        restrict: 'E',
        template: '<title>{{seo.title}}</title>'
    };
});
var-app=angular.module('myApp',['ngRoute']);
app.config(['$routeProvider','$locationProvider',函数($routeProvider,$locationProvider){
$routeProvider
.when('/',{templateUrl:'routes/home.html'})
.when('/pageA',{templateUrl:'routes/pageA.html'})
.when('/pageB',{templateUrl:'routes/pageB.html'})
。否则({重定向到:'/'});
$locationProvider.html5模式({
已启用:true
});
}]);
应用指令('seoTitle',函数(){
返回{
限制:'E',
模板:“{seo.title}”
};
});
当我打开inspector时,指令已移动到
,且未替换为模板:

如何在标题中创建指令

p.S.:一个代码示例将非常棒

您的答案是:,在您的代码中实现它可以是:

<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <meta charset="UTF-8">
    <base href="/">
    <title seo-title>doesn't work</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.1/angular.min.js"></script>
    <script src="https://code.angularjs.org/1.4.1/angular-route.min.js"></script>
    <script src="/incl/js/myApp.js"></script>
</head>
<body >
    <div ng-view></div>
</body>
</html>

你只需要添加一个控制器或一些逻辑来设置你想要的标题。首先:我在inspector中查看,是的,不知怎么的,标题标签出现在正文中。但它似乎并不影响它的功能

现在来看解决方案:乍一看,似乎只有
seoTitle
指令的声明中缺少
replace:true
。 添加它可以解决问题,并且
seo title
按计划被替换为
title
标记,但Angular会在创建新范围时将内容包装在一个额外的
span
元素中(即使
seoTag
的范围声明为隔离
范围:{}

我提出了以下解决方案:

app.directive('seoTitle', function() {

    function compile(elem, attrs, transclude) {

        return function ($scope) {
            transclude($scope, function (clone) {
                elem.empty();
                elem.append(clone[0].innerText);
            });
        };
    }

    return {
        restrict: 'E',
        replace: true,
        transclude: true,
        scope: {},
        compile: compile,
        template: '<title ng-transclude></title>',
    };

});
app.directive('seoTitle',function(){
函数编译(elem、attrs、transclude){
返回函数($scope){
转移($范围、功能(克隆){
elem.empty();
元素追加(克隆[0].innerText);
});
};
}
返回{
限制:'E',
替换:正确,
是的,
作用域:{},
编译:编译,
模板:“”,
};
});
用法:

<seo-title>My Title</seo-title>
我的标题
如前所述,使用
replace:true
可以删除包装
seo标题
标签

要删除额外创建的
span
元素, 我提供了
compile
函数,返回
postLink
函数

我真的无法解释,为什么我需要在
postLink
函数中使用
transclude
函数。 这似乎是一个非常常见的问题,在这种情况下,Angular会创建一个额外的
span
元素。
通过一点尝试和错误,我发现摆脱
span
的最简单方法是
emtpy()
元素并只附加
内部文本
您的指令不需要进入
标题来设置标题。只需让您的指令注入
$window
并设置
$window.document.title='your title'

更新这是更新元标记的方法

对于更新元标记,我将使用如下指令:

mmMetaTags.$inject = ['metaTags'];
function mmMetaTags(metaTags) {

    return {
        restrict: 'A',
        link: function(scope, element) {

            metaTags.metaTags.forEach(function(tag) {
                addMetaTag(tag.name, tag.content)
            });

            metaTags.subscribe(addMetaTag);

            function addMetaTag(name, content) {

                var tag = element[0].querySelector('meta[name="' + name + '"]'); 

                if (tag) {

                    tag.setAttribute('content', content);
                } else {

                    element.append('<meta name="' + name + '" content="' + content + '">');
                }
            }
        }
    }

}

directive('mmMetaTags', mmMetaTags);
mmMetaTags.$inject=['metaTags'];
函数mmMetaTags(metaTags){
返回{
限制:“A”,
链接:功能(范围、元素){
metaTags.metaTags.forEach(函数(标记){
addMetaTag(tag.name、tag.content)
});
订阅(addMetaTag);
函数addMetaTag(名称、内容){
var tag=element[0]。querySelector('meta[name=“”+name+””);
如果(标签){
tag.setAttribute('content',content);
}否则{
元素。追加(“”);
}
}
}
}
}
指令(“mmMetaTags”,mmMetaTags);
以及设置元标记的服务:

function MetaTags() {

    // private
    this._tags = [];

    // private
    this._subscriber;

    var self = this;
    Object.defineProperty(this, 'metaTags', { get: function() {
        return self._tags;
     }});
}

MetaTags.prototype.addMetaTag = function(name, content) {
    this._tags.push({ name: name, content: content });
    this._updateSubscriber(name, content);
}

MetaTags.prototype.subscribe = function(callback) {
    if (!this.subscriber) {
        this._subscriber = callback;
    } else {
        throw new Error('Subscriber already attached. Only one subscriber may be added as there can only be one instance of <head>');
    }
}

// private
MetaTags.prototype._updateSubscriber = function(name, content) {
    this.subscriber(name, content);    
}

service('metaTags', MetaTags);
函数元标记(){
//私人的
这个。_标签=[];
//私人的
这是您的订户;
var self=这个;
defineProperty(这是'metaTags',{get:function(){
返回self.\u标签;
}});
}
MetaTags.prototype.addMetaTag=函数(名称、内容){
this.\u tags.push({name:name,content:content});
此._更新订阅程序(名称、内容);
}
MetaTags.prototype.subscribe=函数(回调){
如果(!this.subscriber){
这。_subscriber=callback;
}否则{
抛出新错误('订阅服务器已连接。只能添加一个订阅服务器,因为只能有一个实例');
}
}
//私人的
MetaTags.prototype.\u updateSubscriber=函数(名称、内容){
此。订户(名称、内容);
}
服务(‘元标签’、元标签);
因此,在您的
标记中,您将包含属性
mm元标记
。然后在控制器中注入
metaTags
服务并调用
addMetaTag
更新标记

你可以试试图书馆。除了title之外,它还支持其他元标记(description、author、og:、twitter:,等等)

angular.directive('ngHead',function(){
设strHtml='';
strHtml+='';
strHtml+='';
strHtml+='';
strHtml+='';
strHtml+='';
strHtml+=“标题”;
strHtml+='';
返回{
限制:“A”,
链接:函数(范围、元素、属性){
元素。追加(strHtml);
}
}
});
在您的html

为我工作。

为什么您需要一个指令来添加元标记?从一开始就把它们放进去?标题可以从控制器eas设置
function MetaTags() {

    // private
    this._tags = [];

    // private
    this._subscriber;

    var self = this;
    Object.defineProperty(this, 'metaTags', { get: function() {
        return self._tags;
     }});
}

MetaTags.prototype.addMetaTag = function(name, content) {
    this._tags.push({ name: name, content: content });
    this._updateSubscriber(name, content);
}

MetaTags.prototype.subscribe = function(callback) {
    if (!this.subscriber) {
        this._subscriber = callback;
    } else {
        throw new Error('Subscriber already attached. Only one subscriber may be added as there can only be one instance of <head>');
    }
}

// private
MetaTags.prototype._updateSubscriber = function(name, content) {
    this.subscriber(name, content);    
}

service('metaTags', MetaTags);
    angular.directive('ngHead', function () {
    let strHtml = '';
    strHtml += '<meta charset="utf-8">';
    strHtml += '<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">';
    strHtml += '<meta http-equiv="x-ua-compatible" content="ie=edge">';
    strHtml += '<meta name="google" content="notranslate" />';
    strHtml += '<title>';
    strHtml += '    title';
    strHtml += '</title>';
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.append(strHtml);
        }
    }
});