UNPKG

2.21 kBJavaScriptView Raw
1// 当前 meta 标签
2let currentMetaTags
3// meta 标签区域结尾的 HTML 注释代码
4let nodeCommentEnd
5
6/**
7 * (浏览器环境) 更新页面信息
8 * @param {String} title
9 * @param {Object[]} metas
10 */
11export default (title, metas = []) => {
12 if (__SERVER__) return
13
14 // 替换页面标题
15 document.title = title
16
17 // 替换 metas
18 const head = document.getElementsByTagName('head')[0]
19 if (!Array.isArray(currentMetaTags)) {
20 currentMetaTags = []
21 // 移除所有在 KOOT_METAS 里的 meta 标签
22 // 采用 DOM 操作的初衷:如果使用 innerHTML 的字符串替换方法,浏览器可能会全局重新渲染一次,造成“闪屏”
23 const childNodes = head.childNodes
24 const nodesToRemove = []
25 let meetStart = false
26 let meetEnd = false
27 let i = 0
28 while (!meetEnd && childNodes[i] instanceof Node) {
29 const node = childNodes[i]
30 if (node.nodeType === Node.COMMENT_NODE) {
31 if (node.nodeValue === __KOOT_INJECT_METAS_START__)
32 meetStart = true
33 if (node.nodeValue === __KOOT_INJECT_METAS_END__) {
34 meetEnd = true
35 nodeCommentEnd = node
36 }
37 } else if (meetStart && node.nodeType === Node.ELEMENT_NODE && node.tagName === 'META') {
38 nodesToRemove.push(node)
39 }
40 i++
41 }
42 nodesToRemove.forEach(el => head.removeChild(el))
43 }
44
45 currentMetaTags.forEach(el => {
46 if (el && el.parentNode)
47 el.parentNode.removeChild(el)
48 })
49 currentMetaTags = metas
50 .filter(meta => typeof meta === 'object')
51 .map(meta => {
52 const el = document.createElement('meta')
53 for (var key in meta) {
54 el.setAttribute(key, meta[key])
55 }
56 // el.setAttribute(__KOOT_INJECT_ATTRIBUTE_NAME__, '')
57 if (nodeCommentEnd) {
58 head.insertBefore(el, nodeCommentEnd)
59 } else {
60 head.appendChild(el)
61 }
62 return el
63 })
64}