Svelte 根作用域中可见的常见代码

huangapple go评论65阅读模式
英文:

Common code visible at root scope in Svelte

问题

我将以下内容翻译为中文:

我在一个 Svelte 应用程序 v.3.54.0 中集成了 Google 登录按钮(https://developers.google.com/identity/gsi/web/guides/personalized-button)。
该按钮需要一个全局范围内的函数作为回调(data-callback 属性),例如:

<div
    id="g_id_onload"
    data-client_id="<id>.apps.googleusercontent.com"
    data-context="signin"
    data-ux_mode="popup"
    data-callback="handleCredentialResponse"
    data-auto_prompt="false"
></div>

<div
    class="g_id_signin"
    data-type="standard"
    data-shape="rectangular"
    data-theme="filled_blue"
    data-text="signin_with"
    data-size="large"
    data-logo_alignment="left"
></div>

我希望 handleCredentialResponse 函数不在 app.html 中,因为我需要在实现中使用其他导入的模块,例如:

function handleCredentialResponse(response) {
    localStorage.setItem("googleCredentials", JSON.stringify(response));
    let jwt = jwt_decode(JSON.parse(response).credential);
    localStorage.setItem('decodedJwt', JSON.stringify(jwt));
    window.location.reload();
}

在这里,我使用了从 jwt-decode 导入的 jwt_decode
如果我将 handleCredentialResponse 包含在 app.html 中的 script 标签中,我会得到一个错误,因为在这个级别上 jwt_decode 未定义。我将不得不通过另一个 script 标签包含 jwt_decode,这是我想要避免的。
另一方面,如果我在 Svelte 组件中编写函数(即使使用 context="module"),Google 按钮会抱怨回调对它不可见。
目前,我使用了一个解决方法,在 app.html 中的一部分逻辑和 +layout.svelte 中的一部分逻辑在 onMount 中,但我真的不喜欢这种方式。
在 Svelte 应用程序中,有没有一种处理这种需求的方式?或者换句话说,在 Svelte 应用程序中是否有一个可以编写公共代码并且也可见于根范围的地方(可能仅在第一次加载时执行)?

英文:

I integrated the Google Sign In button (https://developers.google.com/identity/gsi/web/guides/personalized-button) in a Svelte application v.3.54.0.
The button requires a function in the global scope as a callback (data-callback attribute), e.g.:

	&lt;div
		id=&quot;g_id_onload&quot;
		data-client_id=&quot;&lt;id&gt;.apps.googleusercontent.com&quot;
		data-context=&quot;signin&quot;
		data-ux_mode=&quot;popup&quot;
		data-callback=&quot;handleCredentialResponse&quot;
		data-auto_prompt=&quot;false&quot;
	/&gt;

	&lt;div
		class=&quot;g_id_signin&quot;
		data-type=&quot;standard&quot;
		data-shape=&quot;rectangular&quot;
		data-theme=&quot;filled_blue&quot;
		data-text=&quot;signin_with&quot;
		data-size=&quot;large&quot;
		data-logo_alignment=&quot;left&quot;
	/&gt;

I would like the handleCredentialResponse function to reside in a source file other than app.html, because I need to use other imported modules in the implementation, e.g.:

	function handleCredentialResponse(response) {
		
		localStorage.setItem(&quot;googleCredentials&quot;, JSON.stringify(response));
		let jwt = jwt_decode(JSON.parse(response).credential);
		localStorage.setItem(&#39;decodedJwt&#39;, JSON.stringify(jwt));
		window.location.reload();
	} 

Here I use jwt_decode which is imported from jwt-decode.
If I include handleCredentialResponse in a script tag in app.html, I get an error because jwt_decode is not defined at this level. I would have to include jwt_decode via another script tag, which I rather avoid.
On the other hand, if I write the function in a Svelte component (even with context=&quot;module&quot;), the Google Button complains because the callback is not visible to it.
Currently I use a workaroud where I have part of the logic in app.html and part in the +layout.svelte onMount, but I really do not like it.
What is the Svelte way to deal with this need? Or, in other words, is there a place in a svelte application where I can write common code that is also visible at the root scope (and, possibly, that gets executed only once at the first loading)?

答案1

得分: 1

事后看来,从一开始就应该很容易。我只需在HTML中省略data-callback属性,并将其推迟到<script>部分,像这样:

<script>
    import { onMount } from 'svelte';
    import jwt_decode from 'jwt-decode';

    function handleCredentialResponse(response) {
        localStorage.setItem('googleCredentials', JSON.stringify(response));

        let jwt = jwt_decode(response.credential);
        localStorage.setItem('decodedJwt', JSON.stringify(jwt));
        window.location.reload();
    }

    onMount(() => {
        google.accounts.id.initialize({
            client_id: '<id>.apps.googleusercontent.com',
            callback: handleCredentialResponse
        });
        const parent = document.getElementById('g_id_onload');
        google.accounts.id.renderButton(parent, { theme: 'filled_blue' });
    });
</script>

它正常工作。

英文:

In hindsight it should have been very easy from the start. I can just omit the data-callback attribute in the HTML and defer it to the &lt;script&gt; section like this:

&lt;script&gt;
	import { onMount } from &#39;svelte&#39;;
	import jwt_decode from &#39;jwt-decode&#39;;

	function handleCredentialResponse(response) {
		localStorage.setItem(&#39;googleCredentials&#39;, JSON.stringify(response));

		let jwt = jwt_decode(response.credential);
		localStorage.setItem(&#39;decodedJwt&#39;, JSON.stringify(jwt));
		window.location.reload();
	}

	onMount(() =&gt; {
		google.accounts.id.initialize({
			client_id: &#39;&lt;id&gt;.apps.googleusercontent.com&#39;,
			callback: handleCredentialResponse
		});
		const parent = document.getElementById(&#39;g_id_onload&#39;);
		google.accounts.id.renderButton(parent, { theme: &#39;filled_blue&#39; });
	});
&lt;/script&gt;	

It works fine.

答案2

得分: 0

我不认为有一种"Svelte方式"来处理这个问题,因为通常应该避免这样做。如果没有其他方法,我只会通过将该函数设置在window上,使其在全局范围内可用:

onMount(() => {
  window.handleCredentialResponse = ...
})

(使用onMount是因为在服务器端进行SSR时,这将无法工作。)

英文:

I don't think there is a "Svelte way" for this, as that should generally be avoided. If there is no other way, I would just make the function globally available by setting it on the window:

onMount(() =&gt; {
  window.handleCredentialResponse = ...
})

(onMount is used because this will not work on the server during SSR.)

答案3

得分: -1

只需创建一个次要的“main”脚本,引入必要的功能并创建HTML的Google按钮。这样应该可以正常工作。这样,按钮在相应的功能加载之前是不存在的。

英文:

Just create a secondary "main" script that brings the necessary function and creates the HTML Google button. That should work ok. This way, the button doesn't exist until the corresponding function has been loaded.

huangapple
  • 本文由 发表于 2023年6月19日 22:01:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76507385.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定