前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在10分钟内概览Svelte 3的基础知识

在10分钟内概览Svelte 3的基础知识

作者头像
学前端
发布2020-04-07 15:43:01
1.7K0
发布2020-04-07 15:43:01
举报
文章被收录于专栏:前端之巅前端之巅

Svelte在2019年中成为后起之秀,接下来,让我们来简单的了解一下,这个新的框架。

“ Svelte是一种构建用户界面的全新框架。像React和Vue这样的流行框架会在浏览器中完成大部分工作,而Svelte会将这些工作转变为在构建应用程序时发生的编译步骤。”

以上这段话是在他们的官方网站上所描述,但这到底是什么意思?它能够将繁重的工作从运行时转到编译的时候。(例如npm build时或者是yarn build时)

本文将通过以下TODO的项目示例来让大家更加直观的了解这个框架:

项目的功能概览

  • 1.当没有待办事项时,该应用会向我显示一个占位符
  • 2.当我单击添加没有值的待办事项时,该应用程序不会允许我。
  • 3.当我单击以添加带有值的待办事项时,应用程序将添加一个待办事项并重置该值。
  • 4.我可以看到我有多少个待办事项的摘要,以及完成了多少个待办事项
  • 5.我可以通过单击Todos复选框,将其标记为已完成或撤消来删除它们

设置

与其它框架不同的是,Svelte 没有cli脚手架工具来帮助我们快速构建一个项目,但是为了使我们构建项目更加简单,我们将使用一个入门模板并使用degit来获取他 本教程的要求:

  • NodeJS 8及以上
  • npm 5.2及以上 cd到项目的目录,然后在命令行中输入以下内容:
代码语言:javascript
复制
npx degit sveltejs / template svelte-todo
cd svelte-todo

现在,我们已经有了一个适用于小型应用的汇总结构模板,现在,我们可以开始动手了。

结构

看一下我们的结构, main.js 中的内容如下:

代码语言:javascript
复制
import App from './App.svelte';

const app = new App({
	target: document.body,
	props: {
		name: 'world'
	}
});

export default app;

这里需要注意的是,

  • .svelte 如果仔细观察,我们将导入一个.svelte文件,这是svelte的一个组件,在第三行中,我们实例化了该对象。
  • target svelte应用程序将绑定HTML元素。如果你用过react或vue,则就像React中用<div id="root">来给ReactDOM进行渲染或者使用Vue中的el:'body' 来绑定该元素
  • props 有某些组件可以从它的父级接受一些数据或者是属性,从这里,我们可以在svelte上下文之外将它们提供给我们的组件,因为它没有父级对象。

现在,我们来看一下App.svelte 文件:

代码语言:javascript
复制
<script>
// code
</script>
<style>
// css
</style>
<!-- 可以有一个或者多个html/svelte 标签来让你选择-->

<script>标签中通常写普通的JS代码,<style>标签中写样式(如果你想写Scss的话,也可以进行预处理)。除了这两个标签之外的所有内容都将成为我们正在写的组件的模板。

Props

为什么要使用export let name;呢?这就是我们如何定义属性或者Props的方法,还记得在main.js中我们如何给Props赋予值吗?

要查看此操作的实际效果,请在svelte-todo目录中运行cmd的同时运行run build,该服务已被预先配置为热更新。

代码语言:javascript
复制
yarn dev

在这之后,我们打开localhost:5000来查看我们的应用。props是通过export let [PROPNAME]在组件内部声明来定义的。然后我们可以通过几种方式提供给Svelte组件。将其作为值传递给HTML属性,方法如下:

代码语言:javascript
复制
<PersonComponent title = {name} {age} bind:shouldSleep = {sleepy} bind:happy />
  • title= {name} 传递 {name}给 props title
  • {age} 只是age={age} 当父级props与子级props状态公用一个名字时的简写
  • bind:shouldSleep={sleepy} 我们可以在子组件中更改此值
  • bing:happy 变为bind:happy={happy}。提供完这些东西以后,当我们在组件内部访问它们时,我们的props 将保持上面给出的值。例如,我们提供一个 Robot组件,activated={true} ,那当我们进入activated 内部的Robot时,值将为true。

样式

打开 main.js 然后查看结果。现在删除所有的内容。取而代之的是,添加一个<main>标签,并自己在Hello World 中编写,并且这将成为你自己的内容,在这个过程中,还包含了CSS的编译,不信的话你给样式的背景加入一些渐变色吧。Svelte会自动将所有样式的范围调整到每一个组件,因此不需要BEM或者其他的CSS界定方法,但是要到达HTML标签,我们需要进入全局的范围中,幸运的是,我们现在可以使用:global{element}来将样式放在应用的全局范围内,现在,我们的App.svelte文件如下:

代码语言:javascript
复制
<main>
	Hello world!
</main>

<style>
	:global(html) {
		/* this will apply to <html> */
		background: linear-gradient(#FF6F3F, #FFC877);
	}
</style>

组件

上面的内容还不是我们想要的TODO应用,因此,让我们更加进一步:我们要做的第一件事就是进入 src目录中,创建一个新的文件夹components,并且在这里面创建Tode.svelte文件。在这个文件中,添加以下内容:

代码语言:javascript
复制
<script>
  let todos = [];
  let value = "";
  
  $: amount = todos.reduce((sum, todo) => (todo.done ? ++sum : sum), 0);
  
  function addTodo() {
    if (value === "") return alert("please input a todo");
    const newTodo = {
      text: value,
      done: false
    };
    todos = [...todos, newTodo];
    value = "";
  }
</script>

<div class="wrapper">
  <div class="container">
    <div class="todos">
      {#each todos as todo}
        <p> {todo.text} </p>
      {:else}
        <p class="no-todos">Add a new todo!</p>
      {/each}
    </div>
    <div />
    <button on:click={addTodo}>add todo</button>
    <input bind:value placeholder="Your Todo Here" />
    <p>You've done {amount} todos out of {todos.length}</p>
  </div>
</div>

现在,我们首先会看到一个非常奇怪但是有效的JS标签:$:,它实际上表示一个反应性语句。它可以在如图所示的一行中显示,也可以作为块语句显示,并且如果其中包含的任何变量发生更改,它将重新评估或重新运行,因此在这一行中,我们仅计算完成的待办事项数。

如果你以前用过其他的流行框架,你会发现这里实际上直接改变了状态,虽然这通常是一个很大的禁忌,但这是很巧妙的办法,还需要注意的是,我们这里不使用todos.push(newTodo)。而是重新分配待办事项。这是由于svelte决定何时更新。Svelte只会更新待做项。这也意味着:

代码语言:javascript
复制
const family = { father: {name: "Jonathan"}}
const parent = family.father
parent.name = "Nathan"

因为我们没有重新分配家庭,因此不会触发更新。

接下来,我们研究在模板中看到的奇怪模式。那是一个“互相抚摸”的障碍。块有很多种,您应该看一下小型的文档以了解所有知识,您需要了解的所有知识都可以遍历一个数组todos,并为我们提供分别访问每个值的方式,就像todo,并在其中返回模板对于它们中的每一个,如果数组为空,则显示后面的项。如果您熟悉javascript,可以将其与以下内容类似:

代码语言:javascript
复制
if (arr.length < 0) return <Placeholder />
return arr.map(item => <Item {item} />)

最后,我们使用on:[event]bind:[attribute],它们位于最底层,作为回顾,我们来看下面这些内容:

代码语言:javascript
复制
<button on:click={addTodo}>add todo</button>
<input bind:value placeholder="Your Todo Here" />

第一个是我们的事件挂钩,它的简单含义是“在此触发器上执行该操作”。在这种情况下,“ on clickdo addTodo”是我们之前在script标签中定义的功能。第二种方法为给定的值创建双向绑定,这样当您键入时,值会自动更新。如果您输入“洗碗”,value将变成“洗碗”。

现在,我们可以创建TODO并展示出来,但是不能删除它们。所以,在我们的components文件夹中创建一个TodoItem.svelte文件,并且执行以下步骤:

  • 导出一个变量,就像您在App.svelte中看到的todo那样
  • todo.done 添加一个div,该div包含带标签的复选框和一个绑定的选中值
  • 标签包含todo.text。不要忘记将值放在方括号中以表示其js值而不是文本值{thing}。
  • 就像您使用bind一样,在class:done等于的标签上添加**a标签 **todo.done.
  • 添加style标签,并命名为“ done”的Class。
代码语言:javascript
复制
<script>
  export let todo;
</script>

<style>
  .container {
    padding: 12px 24px;
    border-bottom: 1px solid silver;
  }
  label {
    display: block;
    padding-left: 15px;
    text-indent: -15px;
  }
  input {
    width: 13px;
    height: 13px;
    padding: 0;
    margin: 0;
    vertical-align: bottom;
    position: relative;
    top: -1px;
  }
  label.done {
      text-decoration: line-through;
  }
</style>

<div class="container">
  <label class:done={todo.done}>
    <input type="checkbox" bind:checked={todo.done} />
    {todo.text}
  </label>
</div>

我添加了一些样式,但是我鼓励您自己对应用进行设置样式 如果这成功了,那我们成功做了一个自己的组件。我们要做的最后一件事就是将全新的TODOItem放入Todo中:返回Todo.svelte并在script标签中添加一个import语句:import TodoItem from './TodoItem.svelte',转到模板并替换{todo.text}<TodoItem bind:todo />。这会将todo作为名为todo 的道具发送给TodoItem,这就是我们之前在TodoItem中声明的导出todo变量中的内容。代码如下:

代码语言:javascript
复制
<script>
  import TodoItem from "./TodoItem.svelte";
  let todos = [];
  let value = "";
  $: amount = todos.reduce((sum, todo) => (todo.done ? ++sum : sum), 0);
  function addTodo() {
    if (value === "") return alert("please input a todo");
    const newTodo = {
      text: value,
      done: false
    };
    todos = [...todos, newTodo];
    value = "";
  }
</script>

<style>
  .wrapper {
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .container {
    display: grid;
    grid-template-rows: 8fr 1fr 1fr;
    padding: 8px;
    width: 600px;
    max-width: 800px;
    height: 600px;
    background: aliceblue;
    border: 3px solid #f2bb4d;
    border-radius: 5px;
  }
  .no-todos {
    width: 100%;
    height: 40px;
    font-size: 22px;
  }
  .todos {
    height: 100%;
    overflow-y: auto;
    margin-bottom: 24px;
  }
</style>

<div class="wrapper">
  <div class="container">
    <div class="todos">
      {#each todos as todo}
        <TodoItem bind:todo />
      {:else}
        <p class="no-todos">Add a new todo!</p>
      {/each}
    </div>
    <div />
    <button on:click={addTodo}>add todo</button>
    <input bind:value placeholder="Your Todo Here" />
    <p>You've done {amount} todos out of {todos.length}</p>
  </div>
</div>

完成了!小型的项目外观虽然有些怪异,但其核心非常简单。没有花哨的架构,

本文原文来自 Medium,作者:Yuval Datner , 本文仅进行翻译,转载请注明出处!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一起学前端 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 项目的功能概览
  • 设置
  • 结构
  • Props
  • 样式
  • 组件
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档