我必须为支付网关使用两个外部脚本。
现在两者都放在index.html文件中。
但是,我不想在开头本身就加载这些文件。
只有在用户打开特定组件(使用路由器视图)时才需要支付网关。
有办法实现这个目标吗?
谢谢。
我必须为支付网关使用两个外部脚本。
现在两者都放在index.html文件中。
但是,我不想在开头本身就加载这些文件。
只有在用户打开特定组件(使用路由器视图)时才需要支付网关。
有办法实现这个目标吗?
谢谢。
当前回答
如果你正在使用Vue 3和Composition API(我强烈推荐),并且你经常使用<script>标记,你可以为它写一个“composable”函数:
import { onMounted } from "vue";
export const useScript = (src, async = false, defer = false) => {
onMounted(() => {
// check if script already exists
if (document.querySelector(`head script[src="${src}"`)) return;
// add tag to head
const tag = document.createElement("script");
tag.setAttribute("src", src);
if (async) tag.setAttribute("async", "");
if (defer) tag.setAttribute("defer", "");
tag.setAttribute("type", "text/javascript");
document.head.append(tag);
});
};
或者,如果你正在使用VueUse(我也强烈推荐),你可以使用他们现有的useScriptTag函数。
其他回答
这个用例有一个vue组件
https://github.com/TheDynomike/vue-script-component#usage
<template>
<div>
<VueScriptComponent script='<script type="text/javascript"> alert("Peekaboo!"); </script>'/>
<div>
</template>
<script>
import VueScriptComponent from 'vue-script-component'
export default {
...
components: {
...
VueScriptComponent
}
...
}
</script>
使用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)
})
}
},
为了保持组件的干净,你可以使用mixin。
在组件上导入外部mixin文件。
Profile.vue
import externalJs from '@client/mixins/externalJs';
export default{
mounted(){
this.externalJsFiles();
}
}
externalJs.js
import('@JSassets/js/file-upload.js').then(mod => {
// your JS elements
})
babelrc(我包括这个,如果任何导入卡住)
{
"presets":["@babel/preset-env"],
"plugins":[
[
"module-resolver", {
"root": ["./"],
alias : {
"@client": "./client",
"@JSassets": "./server/public",
}
}
]
}
您可以使用vue-loader并在它们自己的文件中编写组件(单文件组件)。这将允许您在组件的基础上包含脚本和css。
你可以加载你需要的基于承诺的解决方案的脚本:
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。