Nuxt动态引入Script模块
Nuxt在body中增加模块很容易,这里不再多言,仅讨论在<head>
标签中动态增加Script模块的方式。
本文所有结果基于Nuxt版本:“^2.13.0”
head中增加模块
正常情况有两种引入:script外部脚本和页内脚本,静态写法如下:
head () {
return {
title: xxx,
meta: [
// ...
],
script: [
// 所有script模块均在此处添加才可进入<head>标签
]
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
外部脚本
nuxt实现如下:
head () {
return {
// ...
script: [
{ src: 'https://cdn.jsdelivr.net/npm/vue/dist/vue.js', async: true, defer: true }
]
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
效果:
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js" async defer></script>
1
页内脚本
nuxt实现如下:
head () {
return {
// ...
script: [{
hid: 'ldjson-schema',
innerHTML: '{ "@context": "http://schema.org" }',
type: 'application/ld+json'
}],
__dangerouslyDisableSanitizersByTagID: {
'ldjson-schema': ['innerHTML']
},
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
效果:
<script type="application/ld+json">
{ "@context": "http://schema.org" }
</script>
1
2
3
2
3
需注意:
- 官网api文档尚有
vmid
的例子,但当前版本中设置无效,需要改为设置hid
。 - 若
hid
为ldjson-schema
的script模块的innerHTML
属性值不经过__dangerouslyDisableSanitizersByTagID
禁用转义,字符串中的特殊字符均会被转义。 head
的更多配置请参考 官方文档 。
head中动态增加模块
本文中的动态增加则是通过正则表达式将字符串拆分拼接成上述数组实现的。步骤如下:
- 将js字符串根据
<script>....</script>
标签拆分成js数组,即正则:/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/g
。 - 循环js数组,逐个解析js字符串内容。
- 基于
/<script.*?>/
获取js前半部分标签即<script>
的内容。 - 步骤3中的字符串和
indexOf("<\/script>")
结合获取<script>....</script>
中间的内容(如果有)。 - 步骤3中的字符串基于正则
"[\\s]+
替换所有空格为但空格,即replace("[\\s]+"," ")
。 - 拆分步骤3中字符串,获取到
<script>
标签属性配置,逐个变成键值对,作为js对象的属性。 - 最后将js对象放到数组中,并将数组赋值给上述
head
块的script
属性。
完整代码如下:
head () {
let scriptArry = []; // JavaScript对象数组,用于赋值给script
let scripTag = {}; // 待禁止转义的JavaScript内容块ID,用于赋值给 __dangerouslyDisableSanitizersByTagID
// this.windcoder.com.site_head_script_code 待拆分js字符串
if(this.windcoder.com.site_head_script_code) {
// 1. 将字符串拆分为 <script>....</script> 格式字符串的数组
let reg = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/g;
let scriptStrArry = this.siteInfo.site_head_script_code.match(reg);
let reg2 =/<script.*?>/; // 用于获取字符串前半部分
let scnum = 0; // 用于设置script块的ID标签
// 2.循环拆分出的数组,逐个获取数据
for(let str of scriptStrArry) {
// 3. 获取js前半部分标签,即<script>的内容
let preStr = str.match(reg2)[0];
// 4. 获取js标签中间部分的内容(如果有,说明是script块,需要禁用转义)
let mindStr = str.substring(preStr.length,str.indexOf("<\/script>"));
// 5. 格式化js标签前部分内容,方便后续拆分
let preStr2 = preStr.substring(7,preStr.length-1).replace("[\\s]+"," ");
let scriptObj = {}; // 用于存储转化后的js对象
scnum++;
if(preStr2.length>0) {
// 获取scipt标签的属性数组
let preArry = preStr2.split(" ");
for(let apre of preArry) {
// 6. 基于“=”拆分属性,如 src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js" 被拆分为 ["src",'"https://cdn.jsdelivr.net/npm/vue/dist/vue.js"']
let preArr2 = apre.split("=");
if(preArr2.length==2) {
// 说明是键值对形式,这里仅对字符串形式做了处理,数值型,请依据类似做法转化为js对象的属性。
scriptObj[preArr2[0]] = preArr2[1].substring(1,preArr2[1].length-1);
} else {
// 说明属性是默认值,如上面的 async
if(preArr2[0]!='') {
scriptObj[preArr2[0]] = true;
}
}
}
}
// 如果存在中间内容,追加hid,并添加到scripTag用于后续禁用转义
if(mindStr.length>0) {
scriptObj.innerHTML = mindStr;
scriptObj['hid'] = 'script-'+scnum;
scripTag['script-'+scnum] = ['innerHTML'];
}
scriptArry.push(scriptObj);
}
}
return {
title: this.siteInfo.name,
meta: [
{ hid: "keywords", name: "keywords", content: this.siteInfo. site_key},
{ hid: "description", name: "description", content: this.siteInfo. site_description},
],
script: scriptArry, // 7. JavaScript标签组动态赋值
style:[],
__dangerouslyDisableSanitizersByTagID: scripTag,
link: [
// ...
],
}
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
小结
本文主要讲的是如何将JavaScript基于正则表达式动态生成的问题,css相关内容也可以像上面一样动态添加,这里就不再过多说了。这种方式存在一点小问题,就是不支持谷歌广告的js标签。容易出现l类似如下的问题:
adsbygoogle.push() error: Only one AdSense head tag supported per page. The second tag is ignored.
Uncaught TagError: adsbygoogle.push() error: All ins elements in the DOM with class=adsbygoogle already have ads in them.
这些JavaScript最好编译前动手引入。最简单的设置在 nuxt.config.js
文件的head
中,这种方案未作测试,请以实际效果为准。
还有一种文案是通过在项目根目录下创建app.html
,从而修改应用模板,默认如下:
<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
<head {{ HEAD_ATTRS }}>
{{ HEAD }}
</head>
<body {{ BODY_ATTRS }}>
{{ APP }}
</body>
</html>
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
修改之后如下:
<!DOCTYPE html>
<!--[if IE 9]><html class="lt-ie9 ie9" {{ HTML_ATTRS }}><![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--><html {{ HTML_ATTRS }}><!--<![endif]-->
<head {{ HEAD_ATTRS }}>
{{ HEAD }}
<script data-ad-client="ca-pub-xxxxxx" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
</head>
<body {{ BODY_ATTRS }}>
{{ APP }}
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
参考资料:
预览
除特别注明外,本站所有文章均为 windcoder 原创,转载请注明出处来自: nuxtdongtaiyinruscriptmokuai
Loading comments...

预览
暂无数据