写在开头
- 前段时间看到了svelte和tailwind,想试一下,所以简单用了一下,记录一下感受和过程。
- 内容包括,vite的svelte+ts模板,eslint,tailwind的使用。svelte的路由和store。
正文
使用vite创建svelte+ts及部分修改
npm create vite
选择svelte+ts的项目,生成模板。
遇到了main.ts里引入App.svelte报2307的错,即找不到模块
于是在vite-env.d.ts文件中添加了
// 把原来这里注释掉了
// <reference types="svelte" />
declare module '*.svelte' {
import type { SvelteComponentTyped } from 'svelte';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const component: SvelteComponentTyped<any, any, any>;
export default component;
}
后面发现好像是Svelte for VS Code(用于svelte语法高亮)这个插件的问题,我两个电脑上出现的情况不太一样。 windows情况下是这样就解决了。mac里装了这个提示引入ts配置,然后不需要这么修改就能找到模块了。
引入tailwind
npm i postcss tailwindcss autoprefixer svelte-preprocess -D
npx tailwindcss init -p
总共生成了三个文件app.css,postcss.config.js和tailwind.config.js
这边需要把postcss.config.js和tailwind.config.js改成cjs,不然会报require相关的错
tailwind使用
<main>
<div class="h-screen w-screen bg-slate-400">
<div class="absolute left-1/2 transform -translate-x-1/2 ">
<img class="h-80 w-80" src={logo} alt="Svelte Logo" />
<div
class="button"
on:click="{clickHandle}"
>
{ text }
</div>
<div class="button" on:click="{() => push('/count')}">count</div>
<div class="button" on:click="{() => push('/mixamo')}">mixamo</div>
</div>
</div>
</main>
<style>
.button {
@apply leading-loose
text-6xl
text-center
cursor-pointer
bg-white
rounded-2xl
select-none
hover:text-red-500
hover:shadow-2xl
hover:bg-slate-200
active:bg-slate-700;
}
</style>
简单理解为用类名代替了css语法。
拿h-80举例,他就等于height: 20rem; 如果tailwind里直接用数字是rem单位,如果需要用px则为h-[80px]。
因为刚开始用,不太熟练,用起来基本在对照这文档开发。但是能感受到,如果熟练了,会比写css快。
但是我以后大概率不会去使用tailwind
原因如下
- css和tailwind混用的场景会导致代码可读性下降。比如,团队有人用有人不用;有些情况tailwind可能不支持需要用css写。
- hover,active需要每个属性都加。写着很长
- 属性较多的时候放在class里会很难阅读,放在style里又想着那我为啥不用scss呢。
- 不支持伪元素
PS: 当然这是我浅用下来的感觉,tailwind还有很多东西可以配置去预设,如果很好的去设置,书写文档,应该会有效率的提升。
终于到svelte了
部分语法
响应式语法
<div
class="button"
on:click="{clickHandle}"
>
{ text }
</div>
全都是使用{}去包裹
if,for语法
<main>
{#if loading}
<Loading />
{:else}
<div>
<Navbar />
<div class="h-screen w-screen pt-10">
<img class="h-full w-full" src="{bg}" alt="" />
</div>
<div>
{#each contents as item,i}
<TextImage img="{item.img}" title="{item.title}" content="{item.content}" isRight="{i % 2 === 1}"></TextImage>
{/each}
</div>
</div>
{/if}
</main>
if endif? 哈哈哈。语法上没有什么难理解的,可能一开始用不习惯。
路由
官网上推荐的是svelte-spa-router,但没有内置,所以需要安装
npm i svelte-spa-router
用法和vue比较相似,app.svelte下,用router组件传入路由数组
<script lang="ts">
import routes from './router';
import Router from 'svelte-spa-router';
</script>
<main>
<Router {routes}></Router>
</main>
路由数组,router/index.ts文件如下
import Home from '@/views/home.svelte';
import Test from '@/views/test.svelte';
import Count from '@/views/count.svelte';
import Mixamo from '@/views/mixamo/home/index.svelte';
import Character from '@/views/mixamo/character/index.svelte';
const routes = {
'/': Home,
'/test/:param1/:param2': Test,
'/count': Count,
'/mixamo': Mixamo,
'/character': Character,
};
export default routes;
动态路由功能没有去尝试,这个传参让我有点难受,需要预定义,然后看一下test.svelte下怎么接收的
<script lang="ts">
import type { TestParams } from '@/interfaces/test';
export let params: TestParams = {};
</script>
<main>
Test
<div>{params.param1}</div>
<div>{params.param2}</div>
</main>
支持使用'/test/*'来接收未定义的参数,但只能接收一个
例如, 'test/123/321'相同的路径下,定义接收两个参数的params值为
{
param1: '123',
param2: '321'
}
为定义的,值为
{
wild: '123/321'
}
希望svelte的生态越来越好。
路由跳转的话,引入push方法,然后参数为定义的hash
import { push } from 'svelte-spa-router';
push('/test')
store
svelte内置了store,可以不需要引入额外的依赖
import { writable, readable, derived } from 'svelte/store';
export const count = writable(0);
export const countRead = readable(0);
-----xx.svelte----
import { count, countRead } from './xxx.ts'
let tempCount = 0
const unsubscribe = count.subscribe(value => {
tempCount = value
})
<div>{tempCount}</div>
<div>{$count}</div>
先讲writable和readable,顾名思义。就是可写的和只读的。
- 响应式绑定用法如上,writable和 readable都是这样的,tempCount和$count效果是一致的,可以理解为$是在svelte封装的一层语法糖。
- writable比readable多了两个方法update和set。update传入一个函数,参数为当前值,返回值覆盖当前值。set直接传入一个值,覆盖当前值
count.update(v => v+1)
count.set(0)
- writable和readable都有第二个参数,传入一个函数,参数为set方法。当有组件引用这个store(subscribe或者$)会调用这个方法,返回值也为一个函数,但没有组件引用store时,会调用返回值的方法。readable需要使用这个参数才能改变值。
let i = 0
const countRead = readable(0, set => {
const interval = setInterval(() => {
set(i++)
}, 1000)
return () => clearInterval(interval)
})
derived可以理解为多个store合并成一个新的store,当然可以是单个store生成一个新的store
store = derived([a,b], ([$a,$b]) => $a+$b)
写在最后
- gitee 文章中写的demo地址,里面有一些尝试时候写的demo和mixamo官方的超级丐版(主要是为了测试tailwind和svelte写组件)
- tailwind和svelte都算是初步使用,两个东西内容有很多没讲到的,svelte主要了解了上来就会关心的响应式,路由,store。所以可能会有一些错误和没考虑周全的地方,欢迎指正。
- 整体感受的话,开发一些简单的网站会非常便捷(有考虑用这套技术栈开发一个个人blog。
- 期待svelte的生态越来越好吧。