【问题标题】:Executing a <script> tag on append after the DOM has loaded在 DOM 加载后执行 <script> 标记
【发布时间】:2018-09-20 12:32:17
【问题描述】:

我正在尝试以模式观看 onClick 视频,而无需访问视频页面本身。

我正在使用 Vue.js,并且通过一系列 Ajax 调用,我能够完成大部分工作。

密码笔:https://codepen.io/nolaandy/pen/BrbBzO

如果您点击顶部的“vs Suns”,您会看到所有视频帖子的列表。然后点击任意一张图片,弹出模态组件,动态获取文章标题。

我也想在那里播放视频,所以我尝试运行这个脚本标签:

 < script class="_nbaVideoPlayerScout" data-team="warriors" data-videoId="/video/{{unique videoId from post ajax call}}" data-width="768" data-height="732" src="https://www.nba.com/scout/team/cvp/videoPlayerScout.js"></script>

当模式弹出时,我看到了我点击的帖子/图像的正确标题,并且我看到了与检查器中应有的完全一样的脚本标签,但脚本标签永远不会运行。

我应该以其他方式注入此脚本吗? (这是在axios响应调用里面)

let theVideoId = response.data.content[0].videoID


let s = document.createElement('script')
s.setAttribute('class', '_nbaVideoPlayerScout')
s.setAttribute('data-team', 'warriors') 
s.setAttribute('data-videoId', '/video/' + theVideoId) 
s.setAttribute('data-width', '768') 
s.setAttribute('data-height', '732') 
s.setAttribute('src', 'https://www.nba.com/scout/team/cvp/videoPlayerScout.js')
document.getElementById('popupVideo').appendChild(s);

MODAL COMPONENT -- 在点击其中一个帖子缩略图时触发

const videoModal = Vue.component('VideoModal', {
props: {
    id: {
    type: String,
    required: true
    }
},
data: function () {
  return {
    post: [],
  }
},
mounted() {
  const singleApi = 'https://cors-anywhere.herokuapp.com/www.nba.com/warriors/api/1.1/json?textformat=html&nid='
  axios.get(singleApi + this.id).then((response) => {
    this.post = response.data.content[0]
    console.log('THE RESPONSE', response)

    let theVideoId = response.data.content[0].videoID


let s = document.createElement('script')
s.setAttribute('class', '_nbaVideoPlayerScout')
s.setAttribute('data-team', 'warriors') 
s.setAttribute('data-videoId', '/video/' + theVideoId) 
s.setAttribute('data-width', '768') 
s.setAttribute('data-height', '732') 
s.setAttribute('src', 'https://www.nba.com/scout/team/cvp/videoPlayerScout.js')
document.getElementById('popupVideo').appendChild(s);
  }).catch((error) => {
    console.log(error)
  })

},
methods: {
  goBack: function () {
    router.go(-1)
  }
},
template:`<div>
<div id="video-popup">
  <button class="close-video-popup" @click="goBack">close me</button>
  <div class="video-popup-wrapper">
    <div class="video-popup--title">{{post.title}}</div>
    <div class="video-popup--video" id="popupVideo"></div>
  <div class="video-popup--share"></div>
</div>
</div>
</div>`
})

【问题讨论】:

  • 这个答案可能对你有帮助stackoverflow.com/a/8578840/1309377
  • 我希望这能奏效,但我得到了同样的结果。添加了脚本,但没有运行任何内容。
  • 这太疯狂了,因为如果我添加一个带有警报的脚本,我会收到警报弹出窗口: var s = document.createElement('script') s.type = 'text/javascript' var code = 'alert("'+theVideoId+'");'尝试 { s.appendChild(document.createTextNode(code)); document.getElementById('scriptMe').appendChild(s); } 捕捉 (e) { s.text = 代码; document.getElementById('scriptMe').appendChild(s); }
  • 开发控制台有错误吗?当您加载此脚本时,您预计会发生什么?
  • 我正在尝试显示视频。此时没有错误。如果将此脚本标签添加到代码笔中,您将看到视频弹出窗口:

标签: javascript vue.js append


【解决方案1】:

一时兴起,我做了这个改变:

// document.getElementById('scriptMe').appendChild(s);
document.body.appendChild(s);

然后繁荣,脚本运行和视频加载。

哪个超级有趣,因为“为什么”,对吧?

编辑: 另外,尝试其他脚本注入方法discussed here.

document.write 方法

document.write(s.outerHTML) // s is a script node

也可以。事实上,您可以将该脚本节点嵌入到 div 中,它也可以正常工作。

createContextualFragment 方法

// var $container = document.getElementById('scriptMe'); // does not work
var $container = document.body
var range = document.createRange()
$container.appendChild(range.createContextualFragment(script_str))

有效,其中 script_str 是一个 html 字符串文字。这将作为"&lt;script&gt;....&lt;/script&gt;""&lt;div id="myDiv"&gt;&lt;script&gt;...&lt;/script&gt;&lt;/div&gt;" 工作

但我测试的所有方法最终都需要在body 中完成注入。

codepen

【讨论】:

  • 哇,这很烦人。你能弄清楚这一点真是太棒了!您知道如何将其加载到指定的 div 中吗?
  • 有,有点。但它可能不符合您的标准。首先,tip o the hat to this article。这是a forked pen with the working example。使用createContextualFragment,但注意片段必须如何包含div 容器!在我尝试的所有方法中,我必须附加到 body 才能让脚本运行。很有意思。链接的文章还有另一种可以测试的方法。
  • 感谢您的详细解答!看来您只能附加到 document.body 是正确的。我能够使用以下代码移动视频(设置超时 3 秒并使用片段)。我看到了很多潜在的问题,第一个是如果视频加载时间超过 3 秒会发生什么? setTimeout(function(){ var fragment = document.createDocumentFragment(); fragment.appendChild(document.getElementById('container')); document.getElementById('scriptMe').appendChild(fragment); }, 3000);跨度>
  • 是的,我对为什么一无所知,但我怀疑它与 nba 视频播放器库有关。经过一番测试,我意识到播放器脚本确实加载并运行,没有问题,正如我们预期的那样!但是当它执行时,播放器脚本中的某些条件检查或其他内容会导致init() 函数无法运行。所以现在,我只会怪他们哈哈
猜你喜欢
  • 2019-12-02
  • 2015-10-29
  • 2014-05-02
  • 2014-09-25
  • 2021-06-25
  • 2018-09-06
  • 2019-06-01
  • 2014-05-21
  • 1970-01-01
相关资源
最近更新 更多