Svelte 是用于构建应用程序的绝佳框架,Svelte 组件可以独立于具体的应用程序,因此可以在不同的项目和环境中进行重用。你可以将构建好的组件发布到 npm 上,供其他开发人员使用。这种可重用性提高了开发效率,减少了重复编写相似代码的工作。
在这篇文章中,我们将学习如何创建一个 Svelte 组件,将其导出为自定义元素,并使用它。
开发
让我们开始一个新项目来构建我们的组件。
npm create vite@latest
√ Project name: ... webcomponents
√ Select a framework: » Svelte
√ Select a variant: » TypeScript
cd webcomponents
npm install
npm run dev
- 删除
src/App.svelte
文件。 - 修改位于 src 目录下的
main.ts
文件
// src/main.ts
export * from './lib/webcomponents.svelte'
- 在
src/lib
目录下新建一个click.svelte
文件。
注意:要想实现自定义组件需在文件顶部添加以下标签
<svelte:options tag="my-button" />
详细介绍
// src/lib/click.svelte
<!--这一行是添加你的自定义元素标识-->
<svelte:options tag="my-button" />
<button on:click={increment}>
Clicks: {count}
</button>
<script lang="ts">
let count: number = 0
const increment = () => {
count += 1
}
</script>
<style>
button {
font-family: inherit;
font-size: inherit;
padding: 1em 2em;
color: #ff3e00;
background-color: rgba(255, 62, 0, 0.1);
border-radius: 2em;
border: 2px solid rgba(255, 62, 0, 0);
outline: none;
width: 200px;
font-variant-numeric: tabular-nums;
cursor: pointer;
}
button:focus {
border: 2px solid #ff3e00;
}
button:active {
background-color: rgba(255, 62, 0, 0.2);
}
</style>
- 在
index.html
文件内我们可以引入以上自定义的<my-button></my-button>
标签
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Svelte + TS + Vite App</title>
</head>
<body>
<my-button></my-button>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
- 删除
<div id="app">
, 因为我们不会使用它。然后,将自定义元素标签添加到网站正文中。 - 让我们运行我们的应用程序
npm run dev
,您应该能够看到我们的 Web 组件在运行。
转到 vite.config.js
并更新它,如下所示:
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
svelte({
compilerOptions: {
customElement: true,
},
}),
],
});
构建
运行npm run build
打包程序
构建多个自定义组件
在src/lib
目录下创建time.svelte
文件,代码如下
<svelte:options tag="my-time" />
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
let date = new Date().toLocaleTimeString();
let interval;
onMount(() => {
interval = setInterval(() => {
date = new Date().toLocaleTimeString();
}, 1000);
});
onDestroy(() => {
clearInterval(interval);
});
</script>
<span>{date || ''}</span>
<style>
span {
font-family: inherit;
font-size: inherit;
padding: 1em 2em;
color: #ff3e00;
background-color: rgba(255, 62, 0, 0.1);
border-radius: 2em;
border: 2px solid rgba(255, 62, 0, 0);
outline: none;
width: 200px;
font-variant-numeric: tabular-nums;
cursor: pointer;
}
span:active {
background-color: rgba(255, 62, 0, 0.2);
}
</style>
更新 main.ts
文件
export * from './lib/click.svelte'
export * from './lib/time.svelte'
在index.html
里面添加<my-time></my-time>
注意事项
我们的组件需要提供给第三方使用,所以禁用html输出。
使用者可用通过不同的引入方式使用组件
完整代码如下:
// vite.config.ts
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import pkg from './package.json';
const footer = `
if(typeof window !== 'undefined') {
window._Dry_VERSION_ = '${pkg.version}'
}`;
// https://vitejs.dev/config/
export default defineConfig({
base: './',
build: {
outDir: 'components',
assetsDir: 'static',
rollupOptions: {
input: {
main: 'src/main.ts',
},
output: [
{
dir: 'components',
format: 'umd',
name: '...',
entryFileNames: pkg.name + '.mjs',
footer,
},
{
dir: 'components',
format: 'cjs',
name: '...',
entryFileNames: pkg.name + '.js',
footer,
},
],
},
},
plugins: [
svelte({
compilerOptions: {
customElement: true,
},
}),
],
});
组件传参
定义props
在src/lib/click.svelte
文件内定义props 参数如下
<svelte:options
customElement={{
tag: 'my-click',
shadow: 'none',
props: {
name: { reflect: true, type: 'String', attribute: 'element-index' },
},
}}
/>
然后确定需要传递的参数
export let value = { name: 'test' };
html内传参
<body>
<my-click></my-click>
<my-time></my-time>
<!-- <div id="app"></div> -->
<script type="module" src="/src/main.ts"></script>
</body>
<script>
let myClick = document.getElementsByTagName('my-click')
console.log(myClick);
let data = 0
setInterval(() => {
data++;
console.log(data);
myClick[0].value = { name: '测试' + data };
// myClick.setAttribute("value", "234")
}, 1000);
</script>