我必须为支付网关使用两个外部脚本。
现在两者都放在index.html文件中。
但是,我不想在开头本身就加载这些文件。
只有在用户打开特定组件(使用路由器视图)时才需要支付网关。
有办法实现这个目标吗?
谢谢。
我必须为支付网关使用两个外部脚本。
现在两者都放在index.html文件中。
但是,我不想在开头本身就加载这些文件。
只有在用户打开特定组件(使用路由器视图)时才需要支付网关。
有办法实现这个目标吗?
谢谢。
当前回答
解决这个问题的一个简单而有效的方法是将外部脚本添加到组件的vue mounted()中。我将用谷歌Recaptcha脚本为您演示:
<template>
.... your HTML
</template>
<script>
export default {
data: () => ({
......data of your component
}),
mounted() {
let recaptchaScript = document.createElement('script')
recaptchaScript.setAttribute('src', 'https://www.google.com/recaptcha/api.js')
document.head.appendChild(recaptchaScript)
},
methods: {
......methods of your component
}
}
</script>
来源:https://medium.com/@lassiuosukainen how-to-include-a-script-tag-on-a-vue-component-fe10940af9e8
其他回答
来自mejiamanuel57的答案很好,但我想添加几个适合我的技巧(我花了几个小时在上面)。首先,我需要使用“窗口”范围。此外,如果您需要访问“onload”函数内的任何Vue元素,则需要为“this”实例创建一个新变量。
<script>
import { mapActions } from "vuex";
export default {
name: "Payment",
methods: {
...mapActions(["aVueAction"])
},
created() {
let paywayScript = document.createElement("script");
let self = this;
paywayScript.onload = () => {
// call to Vuex action.
self.aVueAction();
// call to script function
window.payway.aScriptFunction();
};
// paywayScript.async = true;
paywayScript.setAttribute(
"src",
"https://api.payway.com.au/rest/v1/payway.js"
);
document.body.appendChild(paywayScript);
}
};
</script>
我在Vue 2.6上使用它。这里有一个关于“let self = this;”在Javascript中如何工作的技巧的解释:
var that = this;在JavaScript中是什么意思?
好吧,这是我在qiokian(一个live2d动画人物vuejs组件)中的实践:
(以下来自src/qiokian.vue文件)
<script>
export default {
data() {
return {
live2d_path:
'https://cdn.jsdelivr.net/gh/knowscount/live2d-widget@latest/',
cdnPath: 'https://cdn.jsdelivr.net/gh/fghrsh/live2d_api/',
}
},
<!-- ... -->
loadAssets() {
// load waifu.css live2d.min.js waifu-tips.js
if (screen.width >= 768) {
Promise.all([
this.loadExternalResource(
this.live2d_path + 'waifu.css',
'css'
),
<!-- ... -->
loadExternalResource(url, type) {
// note: live2d_path parameter should be an absolute path
// const live2d_path =
// "https://cdn.jsdelivr.net/gh/knowscount/live2d-widget@latest/";
//const live2d_path = "/live2d-widget/";
return new Promise((resolve, reject) => {
let tag
if (type === 'css') {
tag = document.createElement('link')
tag.rel = 'stylesheet'
tag.href = url
} else if (type === 'js') {
tag = document.createElement('script')
tag.src = url
}
if (tag) {
tag.onload = () => resolve(url)
tag.onerror = () => reject(url)
document.head.appendChild(tag)
}
})
},
},
}
顶部的创建标签的答案是好的,但它有一些问题:如果你改变你的链接多次,它会重复创建标签一遍又一遍。
所以我创建了一个脚本来解决这个问题,如果你愿意,你可以删除标签。
它非常简单,但可以节省你自己创建的时间。
// PROJECT/src/assets/external.js
function head_script(src) {
if(document.querySelector("script[src='" + src + "']")){ return; }
let script = document.createElement('script');
script.setAttribute('src', src);
script.setAttribute('type', 'text/javascript');
document.head.appendChild(script)
}
function body_script(src) {
if(document.querySelector("script[src='" + src + "']")){ return; }
let script = document.createElement('script');
script.setAttribute('src', src);
script.setAttribute('type', 'text/javascript');
document.body.appendChild(script)
}
function del_script(src) {
let el = document.querySelector("script[src='" + src + "']");
if(el){ el.remove(); }
}
function head_link(href) {
if(document.querySelector("link[href='" + href + "']")){ return; }
let link = document.createElement('link');
link.setAttribute('href', href);
link.setAttribute('rel', "stylesheet");
link.setAttribute('type', "text/css");
document.head.appendChild(link)
}
function body_link(href) {
if(document.querySelector("link[href='" + href + "']")){ return; }
let link = document.createElement('link');
link.setAttribute('href', href);
link.setAttribute('rel', "stylesheet");
link.setAttribute('type', "text/css");
document.body.appendChild(link)
}
function del_link(href) {
let el = document.querySelector("link[href='" + href + "']");
if(el){ el.remove(); }
}
export {
head_script,
body_script,
del_script,
head_link,
body_link,
del_link,
}
你可以这样使用它:
// PROJECT/src/views/xxxxxxxxx.vue
......
<script>
import * as external from '@/assets/external.js'
export default {
name: "xxxxxxxxx",
mounted(){
external.head_script('/assets/script1.js');
external.body_script('/assets/script2.js');
external.head_link('/assets/style1.css');
external.body_link('/assets/style2.css');
},
destroyed(){
external.del_script('/assets/script1.js');
external.del_script('/assets/script2.js');
external.del_link('/assets/style1.css');
external.del_link('/assets/style2.css');
},
}
</script>
......
你可以加载你需要的基于承诺的解决方案的脚本:
export default {
data () {
return { is_script_loading: false }
},
created () {
// If another component is already loading the script
this.$root.$on('loading_script', e => { this.is_script_loading = true })
},
methods: {
load_script () {
let self = this
return new Promise((resolve, reject) => {
// if script is already loading via another component
if ( self.is_script_loading ){
// Resolve when the other component has loaded the script
this.$root.$on('script_loaded', resolve)
return
}
let script = document.createElement('script')
script.setAttribute('src', 'https://www.google.com/recaptcha/api.js')
script.async = true
this.$root.$emit('loading_script')
script.onload = () => {
/* emit to global event bus to inform other components
* we are already loading the script */
this.$root.$emit('script_loaded')
resolve()
}
document.head.appendChild(script)
})
},
async use_script () {
try {
await this.load_script()
// .. do what you want after script has loaded
} catch (err) { console.log(err) }
}
}
}
请注意这一点。$root有点粗糙,对于全局事件,您应该使用vuex或甚至enthub解决方案。
你可以把上面的内容变成一个组件,并在任何需要的地方使用它,它只会在使用时加载脚本。
注意:这是一台Vue 2。基于X的解。Vue 3已停止支持$on。
使用webpack和vue加载器,你可以这样做
在创建组件之前,它会等待外部脚本加载,因此在组件中可以使用globar vars等
components: {
SomeComponent: () => {
return new Promise((resolve, reject) => {
let script = document.createElement('script')
script.onload = () => {
resolve(import(someComponent))
}
script.async = true
script.src = 'https://maps.googleapis.com/maps/api/js?key=APIKEY&libraries=places'
document.head.appendChild(script)
})
}
},