【Svelte从入门到精通】实战篇——TodoList之页面布局

搭建环境

首先使用vite搭建项目。

bash 复制代码
npm create vite@latest svelte-todolist -- --template svelte

安装tailwind,这一步读者可自行选择自己喜欢的样式工具。

bash 复制代码
npm install -D tailwindcss postcss autoprefixer
bash 复制代码
npx tailwindcss init -p

删除lib/Counter.svelte,清空App.svelte的内容,清空app.css的内容。

将tailwind的基本内容添加进app.css:

css 复制代码
@tailwind base;
@tailwind components;
@tailwind utilities;

修改tailwind.config.js的内容

javascript 复制代码
/** @type {import('tailwindcss').Config} */
export default {
  content: ["./src/**/*.{html,js,svelte}"],
  theme: {
    extend: {},
  },
  plugins: [],
}

然后我们往App.svelte里添加一行内容

html 复制代码
<div class="text-rose-400">app</div>

如无意外,相信读者朋友们能在页面上看到玫瑰色的app字样。

dribble上获取灵感,挑选了一些好看的颜色。在tailwind.config.js上配置:

javascript 复制代码
/** @type {import('tailwindcss').Config} */
export default {
  content: ["./src/**/*.{html,js,svelte}"],
  theme: {
    extend: {
      colors: {
        'color1': '#FDEEE1',
        'color2': '#E62737',
        'color3': '#FF7171',
        'color4': '#FFADA8',
      }
    },
  },
  plugins: [],
}

数据结构

首先我们需要确定待办列表的一个待办项的数据结构,目前笔者定义如下:

typescript 复制代码
interface Todo {
	id: number,
	text: string,
	done: boolean,
}

布局

我们将页面分成三部分,笔者在这里用不同的颜色进行了标注。分别是输入框、Tab切换以及待办列表展示。 整体使用flex布局。

基本框架

在App.svelte中

html 复制代码
<script>
  let divClass =
    "flex flex-col w-[500px] h-[700px] overflow-hidden rounded-lg mx-auto p-4 bg-black";
</script>

<div class={divClass}></div>

在页面上,看到一个居中的暖色块。

输入框

新建一个Input.svelte文件,内容如下

html 复制代码
<script>
  let inputClass = "flex-1 h-full border rounded-lg mr-4 px-4 caret-color2 focus:outline-color2";
  let buttonClass = "w-[100px] h-full rounded-lg flex items-center justify-center bg-color2 text-white flex-shrink-0 hover:cursor-pointer"
</script>

<div class="flex h-12">
  <input
    type="text"
    class={inputClass}
  />
  <button
    class={buttonClass}>Add</button
  >
</div>```

然后我们在App.svelte中引入该组件
```html
<script>
  import Input from './Input.svelte';

  let divClass =
    "flex flex-col w-[500px] h-[700px] overflow-hidden rounded-lg mx-auto p-4 bg-color1";
</script>

<div class={divClass}>
  <Input />
</div>

此时相信读者们能够看到以下内容:

Tabs

新建Tabs.svelte组件,添加内容:

html 复制代码
<script>
  let tabsClass = "grid grid-cols-3 gap-4 h-12 my-4";
  let tabClass =
    "h-12 flex items-center justify-center hover:cursor-pointer rounded-lg";
</script>

<div class={tabsClass}>
  <button class={tabClass}>Todo</button>
  <button class={tabClass}>Done</button>
  <button class={tabClass}>All</button>
</div>

App.svelte中引入该组件后,页面展示如下:

继续完善Tabs.svelte的内容:

html 复制代码
<script>
  let tabsClass = "grid grid-cols-3 gap-4 h-12 my-4";
  let tabClass =
    "h-12 flex items-center justify-center hover:cursor-pointer rounded-lg";

  let currentTab = 'todo'; // todo | done | all

  const changeTab = (tab) => currentTab = tab;
</script>

<div class={tabsClass}>
  <button class={tabClass} on:click={() => changeTab('todo')}>Todo</button>
  <button class={tabClass} on:click={() => changeTab('done')}>Done</button>
  <button class={tabClass} on:click={() => changeTab('all')}>All</button>
</div>
<div class="flex-1 overflow-auto">
  <slot>{currentTab}</slot>
</div>

笔者设置了currentTab变量,用来记录当前激活的是哪个tab,为三个tab按钮绑定更新tab的事件,然后添加了slot,用于待办列表的展示

列表

首先我们实现Item.svelte内的展示:

html 复制代码
<script>
  export let index = 0;
  export let name = "";
  export let done = false;

  let divClass =
    "flex items-center bg-white rounded-lg h-12 px-4 mb-4";
  let indexClass = "w-12 text-left flex-shrink-0";
  let nameClass = "flex-1 overflow-hidden text-ellipsis";
  let checkboxWrapClass = "w-12 flex-shrink-0 flex justify-end items-center";
</script>

<div class={divClass}>
  <span class={indexClass}>{index}</span>
  <span class={nameClass}>{name}</span>
  <span class={checkboxWrapClass}>
    <input
      type="checkbox"
      checked={done}
    />
  </span>
</div>

<style>
  input[type="checkbox"] {
    appearance: none;
    background-color: #fff;
    margin: 0;
    font: inherit;
    width: 1.15em;
    height: 1.15em;
    border: 0.15em solid currentColor;
    border-radius: 0.15em;
    transform: translateY(-0.075em);
    display: grid;
    place-content: center;
  }

  input[type="checkbox"]::before {
    content: "";
    width: 0.65em;
    height: 0.65em;
    transform: scale(0);
    transition: 120ms transform ease-in-out;
    box-shadow: inset 1em 1em #E62737;
  }

  input[type="checkbox"]:checked::before {
    transform: scale(1);
  }
</style>

待办项Item.svelte接收三个prop:index、name和done。 这里我们用自己的style重写了checkbox的样式,使其看上去更符合我们页面的主题。

接着我们实现List.svelte的内容:

html 复制代码
<script>
  import Item from './Item.svelte';

  let list = [{
    id: 1,
    text: 'hello',
    done: false
  }, {
    id: 2,
    text: 'world',
    done: true
  }];
</script>

{#each list as {text, done}, i}
  <Item index={i} name={text} done={done} />
  {:else}
    No data
{/each}

这里我们mock了两个待办项的假数据,一个状态未完成,另一个状态已完成。 最后,我们在App.svelte中引用List.svelte并使用它。

html 复制代码
<script>
  import Input from './Input.svelte';
  import Tabs from './Tabs.svelte';
  import List from './List.svelte';

  let divClass =
    "flex flex-col w-[500px] h-[700px] overflow-hidden rounded-lg mx-auto p-4 bg-color1";
</script>

<div class={divClass}>
  <Input />
  <Tabs>
    <List />
  </Tabs>
</div>

至此,页面上能够看见我们最开始设计的布局结构。

当然,此时的页面功能仍不完整,比如无法添加待办项、Tab切换没有样式、待办项勾选后没有放置到对应的Tab栏等等。在下一章,我们将完善剩余的功能。

小结

本章我们完成了:

  • TodoList项目环境的搭建
  • TailwindCss的使用
  • 一个待办项基本的数据结构
  • 页面布局的定义和初步实现
相关推荐
学不会•9 分钟前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS1 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
活宝小娜3 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点3 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow3 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o3 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic4 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā4 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年5 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder5 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript