Angular 2 - bypassSecurityTrustHtml 和 bypassSecurityTrustScript
Angular 2 - bypassSecurityTrustHtml along with bypassSecurityTrustScript
我有一个按钮(在左侧导航侧),单击它,我想在右侧(内容部分)显示一个模板 (.html)。模板 (.html) 路径将从 Web 服务中获取,并且每次都会不同(因此没有硬编码值)。
该模板 (.html) 可以有自己的脚本标签。直到 Angular 1.x 使用 ng-include 标签很容易,但似乎 Angular 2 不再支持它了。
我可以使用以下解决方法显示 HTML 的内容(以及 CSS)-
this.sanitizer.bypassSecurityTrustHtml(url);
但是脚本没有被加载或执行。
在此先感谢您的帮助。
official document 说 bypassSecurityTrustHtml()
应该适用于您的情况。
我还假设您必须使用 [innerHTML]
属性来填充目标容器中的内容。
我有类似的需求,我需要单个 HTML 标签和单个脚本标签。我为此使用了 bypassSecurityTrustResourceUrl()
。
return this.sanitizer.bypassSecurityTrustResourceUrl(url)
我很确定它也适用于您的情况,因为您正在获取可执行源。
您也可以尝试组合 bypassSecurityTrustScript()
和 bypassSecurityTrustHtml()
。
当您的 HTML 内容中只有一个脚本标签时,[innerHTML] 选项可能对您有用。但是,如果您有多个脚本标签要加载 HTML 内容,那么这不是一个可行的选择,因为它不能保证脚本将被加载和执行的顺序。为此,您必须在任何元素中附加 HTML 并按顺序逐一加载脚本。
下面的解决方案在这里得到了正确的解释 -
https://ghinda.net/article/script-tags/
你的 HTML 应该看起来像 -
<div id="scripts"></div>
<div id="content"></div>
首先 div,您的所有脚本都将被附加,其次,您的所有 HTML 内容都将被附加。
首先将您的 HTML 转换为字符串并将所有脚本标签推送到 scriptArr[]。
// run the scripts inside the dom node
if (scriptArr.length > 0) {
var $container = document.getElementById('scripts')
$container.innerHTML = scriptArr
runScripts($container)
}
/* helpers */
// runs an array of async functions in sequential order
function seq(arr, callback, index) {
// first call, without an index
if (typeof index === 'undefined') {
index = 0
}
arr[index](function () {
index++
if (index === arr.length) {
callback()
} else {
seq(arr, callback, index)
}
})
}
// trigger DOMContentLoaded
function scriptsDone() {
var DOMContentLoadedEvent = document.createEvent('Event')
DOMContentLoadedEvent.initEvent('DOMContentLoaded', true, true)
document.dispatchEvent(DOMContentLoadedEvent)
}
/* script runner */
function insertScript($script, callback) {
var s = document.createElement('script')
if (!s.type) {
s.type = 'text/javascript'
}
if ($script.src) {
s.onload = callback
s.onerror = callback
s.src = $script.src
} else {
s.textContent = $script.innerText
}
// re-insert the script tag so it executes.
document.head.appendChild(s)
// clean-up
$script.parentNode.removeChild($script)
// run the callback immediately for inline scripts
if (!$script.src) {
callback()
}
}
// https://html.spec.whatwg.org/multipage/scripting.html
var runScriptTypes = [
'application/javascript',
'application/ecmascript',
'application/x-ecmascript',
'application/x-javascript',
'text/ecmascript',
'text/javascript',
'text/javascript1.0',
'text/javascript1.1',
'text/javascript1.2',
'text/javascript1.3',
'text/javascript1.4',
'text/javascript1.5',
'text/jscript',
'text/livescript',
'text/x-ecmascript',
'text/x-javascript'
]
function runScripts($container) {
// get scripts tags from a node
var $scripts = $container.querySelectorAll('script')
var runList = []
var typeAttr
[].forEach.call($scripts, function ($script) {
typeAttr = $script.getAttribute('type')
// only run script tags without the type attribute
// or with a javascript mime attribute value
if (!typeAttr || (runScriptTypes ? runScriptTypes.indexOf(typeAttr) !== -1 : 'text/javascript')) {
runList.push(function (callback) {
insertScript($script, callback)
})
}
})
// insert the script tags sequentially
// to preserve execution order
seq(runList, scriptsDone)
}
let fragment = document.createRange()
.createContextualFragment(html);
// fragment.baseURI = 'http://toolsqaplp/publish/Dev_Testing/n1d/DS_MAC/en/CATMMGSkillets_en.edu/CATMMGEdc0020_en.doc/src/';
document.getElementById('content')
.appendChild(fragment);
我有一个按钮(在左侧导航侧),单击它,我想在右侧(内容部分)显示一个模板 (.html)。模板 (.html) 路径将从 Web 服务中获取,并且每次都会不同(因此没有硬编码值)。
该模板 (.html) 可以有自己的脚本标签。直到 Angular 1.x 使用 ng-include 标签很容易,但似乎 Angular 2 不再支持它了。
我可以使用以下解决方法显示 HTML 的内容(以及 CSS)-
this.sanitizer.bypassSecurityTrustHtml(url);
但是脚本没有被加载或执行。
在此先感谢您的帮助。
official document 说 bypassSecurityTrustHtml()
应该适用于您的情况。
我还假设您必须使用 [innerHTML]
属性来填充目标容器中的内容。
我有类似的需求,我需要单个 HTML 标签和单个脚本标签。我为此使用了 bypassSecurityTrustResourceUrl()
。
return this.sanitizer.bypassSecurityTrustResourceUrl(url)
我很确定它也适用于您的情况,因为您正在获取可执行源。
您也可以尝试组合 bypassSecurityTrustScript()
和 bypassSecurityTrustHtml()
。
[innerHTML] 选项可能对您有用。但是,如果您有多个脚本标签要加载 HTML 内容,那么这不是一个可行的选择,因为它不能保证脚本将被加载和执行的顺序。为此,您必须在任何元素中附加 HTML 并按顺序逐一加载脚本。
下面的解决方案在这里得到了正确的解释 - https://ghinda.net/article/script-tags/
你的 HTML 应该看起来像 -
<div id="scripts"></div>
<div id="content"></div>
首先 div,您的所有脚本都将被附加,其次,您的所有 HTML 内容都将被附加。
首先将您的 HTML 转换为字符串并将所有脚本标签推送到 scriptArr[]。
// run the scripts inside the dom node
if (scriptArr.length > 0) {
var $container = document.getElementById('scripts')
$container.innerHTML = scriptArr
runScripts($container)
}
/* helpers */
// runs an array of async functions in sequential order
function seq(arr, callback, index) {
// first call, without an index
if (typeof index === 'undefined') {
index = 0
}
arr[index](function () {
index++
if (index === arr.length) {
callback()
} else {
seq(arr, callback, index)
}
})
}
// trigger DOMContentLoaded
function scriptsDone() {
var DOMContentLoadedEvent = document.createEvent('Event')
DOMContentLoadedEvent.initEvent('DOMContentLoaded', true, true)
document.dispatchEvent(DOMContentLoadedEvent)
}
/* script runner */
function insertScript($script, callback) {
var s = document.createElement('script')
if (!s.type) {
s.type = 'text/javascript'
}
if ($script.src) {
s.onload = callback
s.onerror = callback
s.src = $script.src
} else {
s.textContent = $script.innerText
}
// re-insert the script tag so it executes.
document.head.appendChild(s)
// clean-up
$script.parentNode.removeChild($script)
// run the callback immediately for inline scripts
if (!$script.src) {
callback()
}
}
// https://html.spec.whatwg.org/multipage/scripting.html
var runScriptTypes = [
'application/javascript',
'application/ecmascript',
'application/x-ecmascript',
'application/x-javascript',
'text/ecmascript',
'text/javascript',
'text/javascript1.0',
'text/javascript1.1',
'text/javascript1.2',
'text/javascript1.3',
'text/javascript1.4',
'text/javascript1.5',
'text/jscript',
'text/livescript',
'text/x-ecmascript',
'text/x-javascript'
]
function runScripts($container) {
// get scripts tags from a node
var $scripts = $container.querySelectorAll('script')
var runList = []
var typeAttr
[].forEach.call($scripts, function ($script) {
typeAttr = $script.getAttribute('type')
// only run script tags without the type attribute
// or with a javascript mime attribute value
if (!typeAttr || (runScriptTypes ? runScriptTypes.indexOf(typeAttr) !== -1 : 'text/javascript')) {
runList.push(function (callback) {
insertScript($script, callback)
})
}
})
// insert the script tags sequentially
// to preserve execution order
seq(runList, scriptsDone)
}
let fragment = document.createRange()
.createContextualFragment(html);
// fragment.baseURI = 'http://toolsqaplp/publish/Dev_Testing/n1d/DS_MAC/en/CATMMGSkillets_en.edu/CATMMGEdc0020_en.doc/src/';
document.getElementById('content')
.appendChild(fragment);