svelte-ts-tailwind-eslint初步使用

666 阅读4分钟

写在开头

  1. 前段时间看到了svelte和tailwind,想试一下,所以简单用了一下,记录一下感受和过程。
  2. 内容包括,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

原因如下

  1. css和tailwind混用的场景会导致代码可读性下降。比如,团队有人用有人不用;有些情况tailwind可能不支持需要用css写。
  2. hover,active需要每个属性都加。写着很长
  3. 属性较多的时候放在class里会很难阅读,放在style里又想着那我为啥不用scss呢。
  4. 不支持伪元素

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,顾名思义。就是可写的和只读的。

  1. 响应式绑定用法如上,writable和 readable都是这样的,tempCount和$count效果是一致的,可以理解为$是在svelte封装的一层语法糖。
  2. writable比readable多了两个方法update和set。update传入一个函数,参数为当前值,返回值覆盖当前值。set直接传入一个值,覆盖当前值
count.update(v => v+1)
count.set(0)
  1. 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)

写在最后

  1. gitee 文章中写的demo地址,里面有一些尝试时候写的demo和mixamo官方的超级丐版(主要是为了测试tailwind和svelte写组件)
  2. tailwind和svelte都算是初步使用,两个东西内容有很多没讲到的,svelte主要了解了上来就会关心的响应式,路由,store。所以可能会有一些错误和没考虑周全的地方,欢迎指正。
  3. 整体感受的话,开发一些简单的网站会非常便捷(有考虑用这套技术栈开发一个个人blog。
  4. 期待svelte的生态越来越好吧。