Angular Meta Service 详解
本文于921天之前发表,文中内容可能已经过时。
Meta 标签
The
tag provides metadata about the HTML document. Metadata will not be displayed on the page, but will be machine parsable.
Metadata 中文名叫元数据,是用于描述数据的数据。它不会显示在页面上,但是机器却可以识别。meta 常用于定义页面的说明,关键字,最后修改日期,和其它的元数据。这些元数据将服务于浏览器,搜索引擎和其它网络服务。
meta 标签共有两个属性,分别是 name 属性和 http-equiv 属性:
- name:主要用于描述网页,比如网页的关键词,网站描述等。与之对应的属性值为 content,content 中的内容是对 name 填入类型的具体描述,便于搜索引擎抓取。比如我们常见的 viewport:
1 | <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"> |
- http-equiv:相当于文件的头作用,用于向浏览器传递一些有用的信息,以帮助正确地显示网页内容,与之对应的属性为 content。
1 | <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
以上代码告诉 IE 浏览器,IE8/9 及以后的版本都会以最高版本 IE 来渲染页面。关于 HTML meta 标签的相关知识,这里就不再继续展开,感兴趣的同学可以阅读 HTML meta标签总结与属性使用介绍 这篇文章。
Meta Service 简介
为了让开发者能够方便地操作页面中的 Meta 信息,Angular 为我们提供 Meta 服务。该服务支持以下的方法:
首先要使用 Meta 服务,我们需要从 @angular/platform-browser
库导入 Meta 类,然后利用 Angular 依赖注入的机制,通过构造注入的方式注入 Meta 服务:
1 | import { Injectable } from '@angular/core'; |
addTag()
addTag(tag: MetaDefinition, forceCreation: boolean = false): HTMLMetaElement | null
该方法用于在页面上添加一个 HTML Meta 标签,它接收两个参数:
- tag:MetaDefinition 类型的对象
- forceCreation:是否强制创建,默认为 false
tag 参数对应的 MetaDefinition 类型定义如下:
1 | export type MetaDefinition = { |
了解完上述的内容,我们来动手实践一下:
1 | ({ |
上述代码我们通过调用 meta 服务的 addTag()
方法,创建了两个 Meta 标签。如果需要一次添加多个 meta 标签,我们可以调用 addTags() 方法。
addTags()
addTags(tags: MetaDefinition[], forceCreation: boolean = false): HTMLMetaElement[]
该方法用于一次性添加多个 HTML Meta 标签,它接收两个参数:
- tags:MetaDefinition 类型的对象数组
- forceCreation:是否强制创建,默认为 false
1 | addTags() { |
在创建完 HTML meta 标签,我们可以通过 getTag() 方法来获取对应的 HTMLMetaElement 对象。
getTag()
该方法用于获取 attrSelector 属性选择器对应的 HTMLMetaElement 对象,它接收一个参数,即属性选择器,比如我们需要获取 keywords
meta 标签:
1 | getMetaTag(){ |
当 getTag() 方法匹配不了 attrSelector 属性选择器时,会返回 null 对象。与 setTag() 类似,getTag() 方法也存在一个 getTags() 方法。
getTags()
该方法用于获取所有匹配 attrSelector 选择器的所有 HTMLMetaElement 对象:
1 | getMetaTags() { |
这时我们已经介绍完了如何创建和查找 HTMLMetaElement 对象,有时候在创建完 HTMLMetaElement 对象后,我们可能需要修改 HTMLMetaElement 对象,此时我们需要使用 updateTag() 方法。
updateTag()
updateTag(tag: MetaDefinition, selector?: string): HTMLMetaElement | null
该方法用于更新 HTML Meta 标签的信息,它接收两个参数:
- tag:MetaDefinition 类型的对象
- selector(可选):选择器
1 | updateMetaTags() { |
除了更新 HTML Meta 标签之外,我们也可以移除指定的 HTML Meta 标签。
removeTag()
该方法用于移除匹配 attrSelector 属性选择器的 HTML Meta 标签:
1 | removeMetaTags() { |
最后我们来介绍 removeTagElement() 方法。
removeTagElement()
该方法用于移除 meta 参数对应的 HTML Meta 标签:
1 | removeTagElement() { |
感兴趣的同学,可以浏览 Stackblitz 线上示例。下面我们来简单分析一下 Meta Service 的源码。
Meta Service 源码简析
Meta Service 类及构造函数
1 | // packages/platform-browser/src/browser/meta.ts |
通过观察 Injectable 装饰器的 Meta 元信息,我们知道 Meta 服务将被注册在根级注入器中,当首次获取 Meta 服务时,将使用 createMeta() 工厂方法创建对应的实例。
1 | import {Inject, Injectable, inject} from '@angular/core'; |
接下来我们从最简单的 addTag() 方法开始分析。
addTag()
1 | addTag(tag: MetaDefinition, forceCreation: boolean = false): HTMLMetaElement|null { |
这时我们知道其实在 addTag() 方法内部,最终是调用内部的私有方法 _getOrCreateElement()
来执行具体操作。_getOrCreateElement() 方法的具体实现如下:
1 | private _getOrCreateElement(meta: MetaDefinition, forceCreation: boolean = false): |
简单分析完 addTag(),我们再来看一下与它对应的 getTag() 方法。
getTag()
1 | getTag(attrSelector: string): HTMLMetaElement|null { |
该方法内部的实现也很简单,就是通过 DOM 适配器的 querySelector API 来实现元素匹配。对于前面的示例来说:
1 | let metaEl: HTMLMetaElement = this.meta.getTag('name="keywords"'); |
内部会转换为:
1 | return this._dom.querySelector(this._doc, "meta[name='keywords')" || null; |
新增和查询的方法介绍完,我们来继续分析一下 updateTag() 方法。
updateTag()
1 | updateTag(tag: MetaDefinition, selector?: string): HTMLMetaElement|null { |
最后再来看一下 removeTag() 方法,顾名思义就是用来移除指定的 Meta 元素。
removeTag()
1 | removeTag(attrSelector: string): void { |
参考资源
欢迎小伙伴们订阅全栈修仙之路,及时阅读 TypeScript、Node/Deno、Angular 技术栈最新文章。
