Javascript 应用程序组件看不到index.html中声明的条带元素?
我正在尝试创建一个Stripe elements集成的stackblitz演示 我有如下声明的条带元素:Javascript 应用程序组件看不到index.html中声明的条带元素?,javascript,angular,typescript,stripe-payments,Javascript,Angular,Typescript,Stripe Payments,我正在尝试创建一个Stripe elements集成的stackblitz演示 我有如下声明的条带元素: <!DOCTYPE html> <html lang="en"> <body> <script src="https://js.stripe.com/v3/"></script> <script type="text/javascript"> var stripe = Stripe('pk_test_2s
<!DOCTYPE html>
<html lang="en">
<body>
<script src="https://js.stripe.com/v3/"></script>
<script type="text/javascript">
var stripe = Stripe('pk_test_2syov9fTMRwOxYG97ABSFGSDAXbOgt008X6NL46o');t
var elements = stripe.elements();
</script>
<my-app></my-app>
</body>
</html>
变量条带=条带('pk_测试2syov9fTMRwOxYG97ABSFGSDAXbOgt008X6NL46o');T
var elements=stripe.elements();
但是,app.component.ts
文件似乎没有拾取elements
,也没有将其视为全局元素
你知道如何解决这个问题吗?使用类型脚本,你应该使用npm包在组件内部使用它。 在本例中,您所采用的方法只是将其添加到全局窗口DOM元素中,这与Angular框架的工作方式大相径庭。从技术上讲,您可以使用这些变量window.stripe和window.elements来访问它,但我不推荐这样做。最好遵循Stripe文档提供的指南
问题在于Angular可以在加载条带API的同时加载组件。这将导致竞争条件 如果通过脚本标记加载条带API,则组件可以使用它。如果不是,则组件将不会正确呈现,因为调用
stripe.elements()
时出错
要解决这个问题,我们必须先听脚本完成,然后使用StripeAPI
这是一个可以做到这一点的服务。您注入服务,然后调用:
setPublishableKey(key:string, options?:any):Promise<Stripe>{
return this.stripePromise.then( () => {
return this.stripe(key, options)
})
}
setPublishableKey(键:字符串,选项?:任意):承诺{
返回这个.stripePromise.then(()=>{
返回此.stripe(键、选项)
})
}
这就是整个服务:
import { Injectable } from '@angular/core';
import { Stripe, StripeFactory } from './types';
const STRIPE_API_URL = "https://js.stripe.com/v3/";
@Injectable({
providedIn: 'root'
})
/**
* This service has a `stripe` property to that gets
* initialized to `window["Stripe"]`.
*
* The constructor calls `inject()` which will
* inject a script tag with containing the URL that loads
* stripe and return a `Promise<StripeFactory>`.
*
* The script tag will only load stripe if
* c is not available.
*
* If `window["Stripe"]` is available then `inject()` resolves
* the promise with that instance immediately, and does not create and
* wait for the script tag to load.
*
*
*/
export class AngularStripeService{
private _stripe:StripeFactory = window["Stripe"]
private stripePromise:Promise<any>
constructor() {
this.stripePromise = this.inject()
}
get stripe() {
return this._stripe;
}
set stripe(s:StripeFactory) {
this._stripe = s;
}
setPublishableKey(key:string, options?:any):Promise<Stripe>{
return this.stripePromise.then( () => {
return this.stripe(key, options)
})
}
inject():Promise<StripeFactory>{
if( this.stripe ){
return Promise.resolve( this.stripe )
}
return new Promise((res,rej)=>{
const head = this.getHeadElement()
const script = document.createElement("script")
script.setAttribute("type", "text/javascript")
script.setAttribute("src", STRIPE_API_URL)
head.appendChild(script)
script.addEventListener("load",()=>{
this.stripe = window["Stripe"];
res( this.stripe )
})
})
}
/**
* Returns the `head` element.
* @throws Error('Application does not have a head element');
*/
getHeadElement(){
let elm:HTMLElement = document.getElementsByTagName("head")[0]
if(!elm) {
throw new Error('Application does not have a head element');
}
return elm
}
}
从'@angular/core'导入{Injectable};
从“./types”导入{Stripe,StripeFactory};
常量条带\u API\u URL=”https://js.stripe.com/v3/";
@注射的({
providedIn:'根'
})
/**
*此服务的“stripe”属性
*已初始化为“窗口[“条带”]”。
*
*构造函数调用'inject()',这将
*插入包含加载的URL的脚本标记
*条纹并返回“承诺”。
*
*脚本标记仅在以下情况下加载条带:
*c不可用。
*
*如果'window[“Stripe”]`可用,则'inject()`解析
*承诺立即与该实例关联,并且不会创建和
*等待脚本标记加载。
*
*
*/
导出类AngularStripeService{
private _stripe:StripeFactory=window[“stripe”]
私人脱衣舞表演:承诺
以及该服务的演示:
import { Injectable } from '@angular/core';
import { Stripe, StripeFactory } from './types';
const STRIPE_API_URL = "https://js.stripe.com/v3/";
@Injectable({
providedIn: 'root'
})
/**
* This service has a `stripe` property to that gets
* initialized to `window["Stripe"]`.
*
* The constructor calls `inject()` which will
* inject a script tag with containing the URL that loads
* stripe and return a `Promise<StripeFactory>`.
*
* The script tag will only load stripe if
* c is not available.
*
* If `window["Stripe"]` is available then `inject()` resolves
* the promise with that instance immediately, and does not create and
* wait for the script tag to load.
*
*
*/
export class AngularStripeService{
private _stripe:StripeFactory = window["Stripe"]
private stripePromise:Promise<any>
constructor() {
this.stripePromise = this.inject()
}
get stripe() {
return this._stripe;
}
set stripe(s:StripeFactory) {
this._stripe = s;
}
setPublishableKey(key:string, options?:any):Promise<Stripe>{
return this.stripePromise.then( () => {
return this.stripe(key, options)
})
}
inject():Promise<StripeFactory>{
if( this.stripe ){
return Promise.resolve( this.stripe )
}
return new Promise((res,rej)=>{
const head = this.getHeadElement()
const script = document.createElement("script")
script.setAttribute("type", "text/javascript")
script.setAttribute("src", STRIPE_API_URL)
head.appendChild(script)
script.addEventListener("load",()=>{
this.stripe = window["Stripe"];
res( this.stripe )
})
})
}
/**
* Returns the `head` element.
* @throws Error('Application does not have a head element');
*/
getHeadElement(){
let elm:HTMLElement = document.getElementsByTagName("head")[0]
if(!elm) {
throw new Error('Application does not have a head element');
}
return elm
}
}
Hi-我尝试了这种方法,但现在我得到了一个错误,即无法找到http
和https
包。这是更新的stackblitz:我认为这对您不起作用,因为该库是用于节点的。幸运的是,有人已经创建了一个教程,介绍如何按照您以前尝试的方式进行操作,而不导入that库。-创建类型,然后在组件中使用。我在演示中有这个设置-但这也不起作用…这实际上是我遵循的教程:)