इसे छोड़कर कंटेंट पर जाएं

Scripts and event handling

यह कंटेंट अभी तक आपकी भाषा में उपलब्ध नहीं है।

You can send JavaScript to the browser and add functionality to your Astro components using <script> tags in the component template.

Scripts add interactivity to your site, such as handling events or updating content dynamically, without the need for a UI framework like React, Svelte, or Vue. This avoids the overhead of shipping framework JavaScript and doesn’t require you to know any additional framework to create a full-featured website or application.

Scripts can be used to add event listeners, send analytics data, play animations, and everything else JavaScript can do on the web.

Astro automatically enhances the HTML standard <script> tag with bundling, TypeScript, and more. See how astro processes scripts for more details.

src/components/ConfettiButton.astro
<button data-confetti-button>Celebrate!</button>
<script>
// Import from npm package.
import confetti from 'canvas-confetti';
// Find our component DOM on the page.
const buttons = document.querySelectorAll('[data-confetti-button]');
// Add event listeners to fire confetti when a button is clicked.
buttons.forEach((button) => {
button.addEventListener('click', () => confetti());
});
</script>
See when your scripts will not be processed to troubleshoot script behavior, or to learn how to opt-out of this processing intentionally.

By default, Astro processes <script> tags that contain no attributes (other than src) in the following ways:

  • TypeScript support: All scripts are TypeScript by default.
  • Import bundling: Import local files or npm modules, which will be bundled together.
  • Type Module: Processed scripts become type="module" automatically.
  • Deduplication: If a component that contains a <script> is used multiple times on a page, the script will only be included once.
  • Automatic inlining: If the script is small enough, Astro will inline it directly into the HTML to reduce the number of requests.
src/components/Example.astro
<script>
// Processed! Bundled! TypeScript!
// Importing local scripts and from npm packages works.
</script>

Astro will not process a <script> tag if it has any attribute other than src.

You can add the is:inline directive to intentionally opt out of processing for a script.

src/components/InlineScript.astro
<script is:inline>
// Will be rendered into the HTML exactly as written!
// Not transformed: no TypeScript and no import resolution by Astro.
// If used inside a component, this code is duplicated for each instance.
</script>

You may want to write your scripts as separate .js/.ts files or need to reference an external script on another server. You can do this by referencing these in a <script> tag’s src attribute.

When to use this: when your script lives inside of src/.

Astro will process these scripts according to the script processing rules.

src/components/LocalScripts.astro
<!-- relative path to script at `src/scripts/local.js` -->
<script src="../scripts/local.js"></script>
<!-- also works for local TypeScript files -->
<script src="./script-with-types.ts"></script>

When to use this: when your JavaScript file lives inside of public/ or on a CDN.

To load scripts outside of your project’s src/ folder, include the is:inline directive. This approach skips the JavaScript processing, bundling, and optimizations that are provided by Astro when you import scripts as described above.

src/components/ExternalScripts.astro
<!-- absolute path to a script at `public/my-script.js` -->
<script is:inline src="/my-script.js"></script>
<!-- full URL to a script on a remote server -->
<script is:inline src="https://my-analytics.com/script.js"></script>

Some UI frameworks use custom syntax for event handling like onClick={...} (React/Preact) or @click="..." (Vue). Astro follows standard HTML more closely and does not use custom syntax for events.

Instead, you can use addEventListener in a <script> tag to handle user interactions.

src/components/AlertButton.astro
<button class="alert">Click me!</button>
<script>
// Find all buttons with the `alert` class on the page.
const buttons = document.querySelectorAll('button.alert');
// Handle clicks on each button.
buttons.forEach((button) => {
button.addEventListener('click', () => {
alert('Button was clicked!');
});
});
</script>

If you have multiple <AlertButton /> components on a page, Astro will not run the script multiple times. Scripts are bundled and only included once per page. Using querySelectorAll ensures that this script attaches the event listener to every button with the alert class found on the page.

You can create your own HTML elements with custom behavior using the Web Components standard. Defining a custom element in a .astro component allows you to build interactive components without needing a UI framework library.

In this example, we define a new <astro-heart> HTML element that tracks how many times you click the heart button and updates the <span> with the latest count.

src/components/AstroHeart.astro
<!-- Wrap the component elements in our custom element “astro-heart”. -->
<astro-heart>
<button aria-label="Heart">💜</button> × <span>0</span>
</astro-heart>
<script>
// Define the behaviour for our new type of HTML element.
class AstroHeart extends HTMLElement {
connectedCallback() {
let count = 0;
const heartButton = this.querySelector('button');
const countSpan = this.querySelector('span');
// Each time the button is clicked, update the count.
heartButton.addEventListener('click', () => {
count++;
countSpan.textContent = count.toString();
});
}
}
// Tell the browser to use our AstroHeart class for <astro-heart> elements.
customElements.define('astro-heart', AstroHeart);
</script>

There are two advantages to using a custom element here:

  1. Instead of searching the whole page using document.querySelector(), you can use this.querySelector(), which only searches within the current custom element instance. This makes it easier to work with only the children of one component instance at a time.

  2. Although a <script> only runs once, the browser will run our custom element’s connectedCallback() method each time it finds <astro-heart> on the page. This means you can safely write code for one component at a time, even if you intend to use this component multiple times on a page.

In Astro components, the code in the frontmatter (between the --- fences) runs on the server and is not available in the browser.

To pass server-side variables to client-side scripts, store them in data-* attributes on HTML elements. Scripts can then access these values using the dataset property.

In this example component, a message prop is stored in a data-message attribute, so the custom element can read this.dataset.message and get the value of the prop in the browser.

src/components/AstroGreet.astro
---
const { message = 'Welcome, world!' } = Astro.props;
---
<!-- Store the message prop as a data attribute. -->
<astro-greet data-message={message}>
<button>Say hi!</button>
</astro-greet>
<script>
class AstroGreet extends HTMLElement {
connectedCallback() {
// Read the message from the data attribute.
const message = this.dataset.message;
const button = this.querySelector('button');
button.addEventListener('click', () => {
alert(message);
});
}
}
customElements.define('astro-greet', AstroGreet);
</script>

Now we can use our component multiple times and be greeted by a different message for each one.

src/pages/example.astro
---
import AstroGreet from '../components/AstroGreet.astro';
---
<!-- Use the default message: “Welcome, world!” -->
<AstroGreet />
<!-- Use custom messages passed as a props. -->
<AstroGreet message="Lovely day to build components!" />
<AstroGreet message="Glad you made it! 👋" />

Elements rendered by a UI framework may not be available yet when a <script> tag executes. If your script also needs to handle UI framework components, using a custom element is recommended.

योगदान करें समुदाय प्रायोजक