作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.< / div >< / div >
Teimur Gasanov
< / div >

ByTeimur Gasanov

< / div >
验证专家 在工程< / div >< / div >< / div >< / div >

Teimur是一名全栈开发人员,主要使用JavaScript、Go和Python. 他在Docker和Jenkins CI/CD方面也很有经验.

< / div >阅读更多< / div >

专业知识

前端JavaScript< / div >< / div >

以前在

Klarna< / div >< / div >< / div >< / div >< / div >< / div >< / div >< / div >< / div >

这是一个愚蠢风格的组件,我们稍后会让它变得更聪明. 要在我们的站点上看到这个组件,我们应该在根组件- 应用程序中渲染它. 让我们编辑 src /应用程序.苗条的 它看起来是这样的:





如果所有操作都正确且应用程序仍在运行,那么我们的表单将出现在 localhost: 5000. 让我们通过使表单更智能来提升我们的苗条技能.

会有状态

苗条的中的任何组件都可以拥有自己的状态. 状态是一个特殊变量或一组特殊变量,可以在模板内部使用. 为什么我要说"特别"? 每当这样的变量被更改时,模板就会收到通知,并以最新的状态呈现内容. 这使得应用程序能够非常快速地对用户交互做出反应.

我们会申报 电子邮件密码 将存储相应字段的表单值的状态变量. 这意味着我们的 电子邮件密码 变量将始终与表单值保持同步, 因此,我们将随时准备提交这些值,而不必担心提交值与表单中的实际值之间存在任何差异.






👤

{#if isLoading}正在登录...{:其他}登录🔒{/if}

状态变量看起来像普通的JavaScript变量,但要使它们与表单值同步(将它们绑定到表单字段), 这是必须使用的 绑定:价值 指令. 还有一些不熟悉的东西:

  • :提交| preventDefault 是防止默认事件行为的简写吗. 这样比写要舒服得多 e.preventDefault () 每一次.

  • {#if isLoading}正在登录...{:其他}登录🔒{/if} 是苗条的模板语法的一部分. 因为模板块中没有JS,所以有一个特殊的语法来使用if、循环等.

最后,让我们使用可用的选项,通过使用状态向表单添加验证. 它可以通过创建另一个状态变量来实现 错误,当表单以无效值提交时,它将被错误填充.





👤

{#如果对象.键(错误).length > 0}
    {#每个对象.键(错误)作为字段}
  • {field}: {错误[field]}
  • {/每个}
{/if}
登录表单错误
< / div >

表格差不多填好了. 唯一剩下的是在身份验证成功时的成功消息.

让我们创建一个状态变量来跟踪成功的提交 默认情况下. 成功提交表单后,该变量的值应设置为 真正的.

let isSuccess = 假;

处理表单提交的函数也应该按照切换的逻辑进行修改 isSuccess 手术成功后.

const h和leSubmit = () => {
  错误= {};
  如果电子邮件.长度=== 0){
    错误.电子邮件 = "字段不能为空";
  }
  如果密码.长度=== 0){
    错误.密码 = "字段不能为空";
  }
  如果(对象.键(错误).长度=== 0){
    isLoading = 真正的;
    //模拟网络请求
    setTimeout(() => {
      isLoading = 假;
      isSuccess = 真正的;
      //授权用户
    }, 1000);
  }
};

此修改使表单在提交完成后立即进入成功状态.

但是,如果检查开发服务器,则不会发现表单的行为有任何变化. 我们修改了代码,但还没有修改模板. 我们需要向模板添加指令,以便在用户成功登录时显示成功消息. 苗条的的模板语法允许我们轻松实现:

{#如果isSuccess}
🔓
您已成功登录.
{:其他}

👤

{#如果对象.键(错误).length > 0}
    {#每个对象.键(错误)作为字段}
  • {field}: {错误[field]}
  • {/每个}
{/if} {/if}

带有属性的抽象

我们已经整理了关于内部组件状态的所有内容. 现在我们来看看外部依赖项,也就是属性或道具. Props是传递给组件的输入或参数,用于向组件描述应该出现的内容或组件应该如何表现.

属性的声明与状态类似,只是关键字不同 出口.



The answer is {answer}




这都是关于属性的. 声明和传递-所有你需要知道的使用道具.

但是这些属性如何应用于登录表单组件呢? 通过将提交函数提取到属性中,Props可以使我们的登录表单更加通用. 它将允许您将此组件与您需要的任何提交操作(向测试服务器请求)一起使用, 请求到实际的服务器, 等.). 这个道具将被调用 提交 并且将是一个函数,如果提交操作成功,则返回已解决的承诺,如果有错误,则返回已拒绝的承诺. 让我们用上面给出的例子来声明这个道具:

出口让提交;

登录表单中的提交处理程序也应该编辑为使用new 提交 财产.

const h和leSubmit = () => {
  错误= {};
  如果电子邮件.长度=== 0){
    错误.电子邮件 = "字段不能为空";
  }
  如果密码.长度=== 0){
    错误.密码 = "字段不能为空";
  }
  如果(对象.键(错误).长度=== 0){
    isLoading = 真正的;
    提交({电子邮件, 密码})
      .then(() => {
        isSuccess = 真正的;
        isLoading = 假;
      })
      .catch(err => {
        错误.Server = err;
        isLoading = 假;
      });
  }
};

组件似乎准备好了. 然而, 如果您返回表单并尝试提交它, 您会注意到按钮的状态在加载后没有改变. 另外,在控制台中有一个异常: 未捕获的TypeError: 提交不是一个函数. 当然,我们申报了道具,但忘记通过了. 让我们在app组件中声明一个函数,并将其传递给登录表单.

const 提交 = ({ 电子邮件, 密码 }) =>
  new Promise((resolve, reject) => setTimeout(resolve, 1000));

现在表单按预期工作了. 它既可以显示错误,也可以通知用户登录是否成功.

登录表单成功
< / div >

上下文共享

似乎列出了构建应用程序所需的一切. 有了性质和内部状态,我们就可以开始了. 不过,这只是部分正确. 这两点使得设计高复杂性spa成为可能. 然而,如果您尝试在许多不同的组件之间共享数据,您会发现这非常困难.

最简单的例子是拥有全局可访问的 用户 变量. 许多组件应该改变与用户相关的行为, 取决于用户的角色, 年龄, 状态, 等. 然而, 通过使用props将用户传递给应用中的每个组件来重复我们自己并不是DRY.

苗条的对此有一个解决方案 上下文API.

上下文API为组件之间提供了一种“对话”机制,而无需像传递道具一样传递数据和函数或调度大量事件. 这是一个高级功能,但很有用.

让我们将用户上下文添加到正在设计的登录表单中. 创建文件 用户Context.jssrc 载有以下内容的资料夹:

出口 const 关键 = "用户Context";
导出const initialValue = null;

关键 上下文的唯一标识符是否作为应用程序可能具有无限数量的必须保持可访问的不同上下文. initialValue 只是在设置之前上下文的默认值吗.

下一步是将上下文添加到应用程序中. 导航到 应用程序.苗条的 文件和添加2个import语句:

从“苗条的”导入{onMount, setContext};
进口{
  键作为用户ContextKey,
  initialValue为用户ContextInitialValue
} from“./ 用户Context”;

查看上面的代码,您可能想知道我们正在从 苗条的 包. onMount 辅助函数需要回调函数作为参数吗. 这个回调将在当前组件挂载时执行(在加载组件的最开始)。. setContext 是上下文的setter函数吗. 它需要上下文的键和一个新值作为参数.

让我们使用 onMount 为上下文设置默认值的函数:

onMount(() => {
  setContext (用户ContextKey 用户ContextInitialValue);
});

然后修改 提交 设置用户上下文的函数:

const 提交 = ({ 电子邮件, 密码 }) =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      setContext (用户ContextKey, {
        名称:“Foo”,
        姓:“酒吧”,
        电子邮件:“foo@bar.com”
      });
      解决();
    }, 1000);
  });

就是这样. 成功的提交会将用户上下文更改为一个假的用户对象,该对象可以通过上下文getter来访问 getContext:


Summary

苗条的是一个功能强大的工具,具有高性能和灵活的API. 除了本文介绍的基本功能外,苗条的还有以下功能:

  • 响应式声明和语句
  • Await模板块
  • 维绑定
  • 像Redux这样的全球性商店
  • 动画和过渡助手
  • 调试助手

总而言之,苗条的是一个很好的库,可以满足构建spa的所有需求,甚至更多. 它可以与市场上最大的玩家竞争,甚至获胜. 但是,它现在可以使用的是 前端开发人员的 社区.

注意:本文中的所有代码都可以在 teimurjan / 苗条的-login-form GitHub库. 可以使用登录表单的演示 在这里.

< / div >< / div >< / div >< / div >

了解基本知识

  • 苗条的的主要优势是什么?

    苗条的在构建阶段被编译成纯JavaScript, 因此,应用程序不需要依赖项就可以启动.

    < / div >< / div >
  • 苗条的组件是如何构建的?

    一个苗条的组件可能包含三个部分:脚本、样式和模板. 前两个, 哪些修改组件的外观和行为, 是可选的, 模板部分是必需的.

    < / div >< / div >
  • 是苗条的的模板块纯HTML?

    苗条的在模板块中提供了一个增强版的HTML,带有变量等额外特性, 有条件的块, 循环块, async-await块, 和更多的.

    < / div >< / div >
  • 如何跨苗条应用程序共享数据?

    你可以使用苗条的的Context API来共享数据——这是一种组件连接的机制,无需将数据作为属性传递或调度大量事件.

    < / div >< / div >
  • 苗条的是如何实现反应性的?

    苗条组件允许拥有内部状态或接受外部属性. 只要状态或属性的一部分发生了变化,模板就会立即做出反应.

    < / div >< / div >
< / >节< / div >< / div >

标签

< / div >< / div >< / div >< / div >
聘请Toptal这方面的专家.< / div >现在雇佣< / div >< / div >
Teimur Gasanov
< / div >

Teimur Gasanov

验证专家 在工程< / div >< / div >< / div >

比什凯克,Chuy省,吉尔吉斯斯坦

2018年5月1日成为会员

< / div >< / div >< / div >

作者简介

Teimur是一名全栈开发人员,主要使用JavaScript、Go和Python. 他在Docker和Jenkins CI/CD方面也很有经验.

< / div >阅读更多< / div >
作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.< / div >

专业知识

前端JavaScript< / div >< / div >

以前在

Klarna< / div >< / div >
雇佣Teimur< / div >< / div >< / div >< / >节< / div >< / div >
< / div >< / >节< / div >
< / div >< / div >< / div >< / div >< / div >
< / div >< / div >
< / div >

世界级的文章,每周发一次.

< / div >\n\n\n\n

这是一个愚蠢风格的组件,我们稍后会让它变得更聪明. 要在我们的站点上看到这个组件,我们应该在根组件- 应用程序中渲染它. 让我们编辑 src /应用程序.苗条的 它看起来是这样的:

\n\n
\n\n\n\n
\n \n
\n
\n\n

如果所有操作都正确且应用程序仍在运行,那么我们的表单将出现在 localhost: 5000. 让我们通过使表单更智能来提升我们的苗条技能.

\n\n

会有状态

\n\n

苗条的中的任何组件都可以拥有自己的状态. 状态是一个特殊变量或一组特殊变量,可以在模板内部使用. 为什么我要说"特别"? 每当这样的变量被更改时,模板就会收到通知,并以最新的状态呈现内容. 这使得应用程序能够非常快速地对用户交互做出反应.

\n\n

我们会申报 电子邮件密码 将存储相应字段的表单值的状态变量. 这意味着我们的 电子邮件密码 变量将始终与表单值保持同步, 因此,我们将随时准备提交这些值,而不必担心提交值与表单中的实际值之间存在任何差异.

\n\n
\n\n\n\n\n
\n

👤

\n\n \n \n\n \n \n\n {#if isLoading}正在登录...{:其他}登录🔒{/if}\n
\n
\n\n

状态变量看起来像普通的JavaScript变量,但要使它们与表单值同步(将它们绑定到表单字段), 这是必须使用的 绑定:价值 指令. 还有一些不熟悉的东西:

\n\n
    \n
  • \n

    :提交| preventDefault 是防止默认事件行为的简写吗. 这样比写要舒服得多 e.preventDefault () 每一次.

    \n
  • \n
  • \n

    {#if isLoading}正在登录...{:其他}登录🔒{/if} 是苗条的模板语法的一部分. 因为模板块中没有JS,所以有一个特殊的语法来使用if、循环等.

    \n
  • \n
\n\n

最后,让我们使用可用的选项,通过使用状态向表单添加验证. 它可以通过创建另一个状态变量来实现 错误,当表单以无效值提交时,它将被错误填充.

\n\n
\n\n\n\n
\n

👤

\n \n \n \n \n \n \n \n \n \n {#如果对象.键(错误).length > 0}\n
    \n {#每个对象.键(错误)作为字段}\n
  • {field}: {错误[field]}
  • \n {/每个}\n
\n {/if}\n
\n
\n\n
\n \"登录表单错误\"\n
\n\n

表格差不多填好了. 唯一剩下的是在身份验证成功时的成功消息.

\n\n

让我们创建一个状态变量来跟踪成功的提交 默认情况下. 成功提交表单后,该变量的值应设置为 真正的.

\n\n
let isSuccess = 假;\n
\n\n

处理表单提交的函数也应该按照切换的逻辑进行修改 isSuccess 手术成功后.

\n\n
const h和leSubmit = () => {\n  错误= {};\n  如果电子邮件.长度=== 0){\n    错误.电子邮件 = \"Field should not be empty\";\n  }\n  如果密码.长度=== 0){\n    错误.密码 = \"Field should not be empty\";\n  }\n  如果(对象.键(错误).长度=== 0){\n    isLoading = 真正的;\n    //模拟网络请求\n    setTimeout(() => {\n      isLoading = 假;\n      isSuccess = 真正的;\n      //授权用户\n    }, 1000);\n  }\n};\n
\n\n

此修改使表单在提交完成后立即进入成功状态.

\n\n

但是,如果检查开发服务器,则不会发现表单的行为有任何变化. 我们修改了代码,但还没有修改模板. 我们需要向模板添加指令,以便在用户成功登录时显示成功消息. 苗条的的模板语法允许我们轻松实现:

\n\n
\n {#如果isSuccess}\n
\n 🔓\n
\n 您已成功登录.\n
\n {:其他}\n

👤

\n\n \n \n\n \n \n\n \n\n {#如果对象.键(错误).length > 0}\n
    \n {#每个对象.键(错误)作为字段}\n
  • {field}: {错误[field]}
  • \n {/每个}\n
\n {/if}\n {/if}\n
\n
\n\n

带有属性的抽象

\n\n

我们已经整理了关于内部组件状态的所有内容. 现在我们来看看外部依赖项,也就是属性或道具. Props是传递给组件的输入或参数,用于向组件描述应该出现的内容或组件应该如何表现.

\n\n

属性的声明与状态类似,只是关键字不同 出口.

\n\n
\n\n

The answer is {answer}

\n
\n\n
\n\n\n
\n\n

这都是关于属性的. 声明和传递-所有你需要知道的使用道具.

\n\n

但是这些属性如何应用于登录表单组件呢? 通过将提交函数提取到属性中,Props可以使我们的登录表单更加通用. 它将允许您将此组件与您需要的任何提交操作(向测试服务器请求)一起使用, 请求到实际的服务器, 等.). 这个道具将被调用 提交 并且将是一个函数,如果提交操作成功,则返回已解决的承诺,如果有错误,则返回已拒绝的承诺. 让我们用上面给出的例子来声明这个道具:

\n\n
出口让提交;\n
\n\n

登录表单中的提交处理程序也应该编辑为使用new 提交 财产.

\n\n
const h和leSubmit = () => {\n  错误= {};\n  如果电子邮件.长度=== 0){\n    错误.电子邮件 = \"Field should not be empty\";\n  }\n  如果密码.长度=== 0){\n    错误.密码 = \"Field should not be empty\";\n  }\n  如果(对象.键(错误).长度=== 0){\n    isLoading = 真正的;\n    提交({电子邮件, 密码})\n      .then(() => {\n        isSuccess = 真正的;\n        isLoading = 假;\n      })\n      .catch(err => {\n        错误.Server = err;\n        isLoading = 假;\n      });\n  }\n};\n
\n\n

组件似乎准备好了. 然而, 如果您返回表单并尝试提交它, 您会注意到按钮的状态在加载后没有改变. 另外,在控制台中有一个异常: 未捕获的TypeError: 提交不是一个函数. 当然,我们申报了道具,但忘记通过了. 让我们在app组件中声明一个函数,并将其传递给登录表单.

\n\n
const 提交 = ({ 电子邮件, 密码 }) =>\n  new Promise((resolve, reject) => setTimeout(resolve, 1000));\n
\n\n
\n \n
\n
\n\n

现在表单按预期工作了. 它既可以显示错误,也可以通知用户登录是否成功.

\n\n
\n \"登录表单成功\"\n
\n\n

上下文共享

\n\n

似乎列出了构建应用程序所需的一切. 有了性质和内部状态,我们就可以开始了. 不过,这只是部分正确. 这两点使得设计高复杂性spa成为可能. 然而,如果您尝试在许多不同的组件之间共享数据,您会发现这非常困难.

\n\n

最简单的例子是拥有全局可访问的 用户 变量. 许多组件应该改变与用户相关的行为, 取决于用户的角色, 年龄, 状态, 等. 然而, 通过使用props将用户传递给应用中的每个组件来重复我们自己并不是DRY.

\n\n

苗条的对此有一个解决方案 上下文API.

\n\n
\n

上下文API为组件之间提供了一种“对话”机制,而无需像传递道具一样传递数据和函数或调度大量事件. 这是一个高级功能,但很有用.

\n
\n\n

让我们将用户上下文添加到正在设计的登录表单中. 创建文件 用户Context.jssrc 载有以下内容的资料夹:

\n\n
出口 const 关键 = \"用户Context\";\n导出const initialValue = null;\n
\n\n

关键 上下文的唯一标识符是否作为应用程序可能具有无限数量的必须保持可访问的不同上下文. initialValue 只是在设置之前上下文的默认值吗.

\n\n

下一步是将上下文添加到应用程序中. 导航到 应用程序.苗条的 文件和添加2个import语句:

\n\n
进口{ onMount, setContext } from \"苗条的\";\n进口{\n  键作为用户ContextKey,\n  initialValue为用户ContextInitialValue\n} from \"./用户Context\";\n
\n\n

查看上面的代码,您可能想知道我们正在从 苗条的 包. onMount 辅助函数需要回调函数作为参数吗. 这个回调将在当前组件挂载时执行(在加载组件的最开始)。. setContext 是上下文的setter函数吗. 它需要上下文的键和一个新值作为参数.

\n\n

让我们使用 onMount 为上下文设置默认值的函数:

\n\n
onMount(() => {\n  setContext (用户ContextKey 用户ContextInitialValue);\n});\n
\n\n

然后修改 提交 设置用户上下文的函数:

\n\n
const 提交 = ({ 电子邮件, 密码 }) =>\n  new Promise((resolve, reject) => {\n    setTimeout(() => {\n      setContext (用户ContextKey, {\n        name: \"Foo\",\n        lastName: \"Bar\",\n        电子邮件: \"foo@bar.com\"\n      });\n      解决();\n    }, 1000);\n  });\n
\n\n

就是这样. 成功的提交会将用户上下文更改为一个假的用户对象,该对象可以通过上下文getter来访问 getContext:

\n\n
\n
\n\n

Summary

\n\n

苗条的是一个功能强大的工具,具有高性能和灵活的API. 除了本文介绍的基本功能外,苗条的还有以下功能:

\n\n
    \n
  • 响应式声明和语句
  • \n
  • Await模板块
  • \n
  • 维绑定
  • \n
  • 像Redux这样的全球性商店
  • \n
  • 动画和过渡助手
  • \n
  • 调试助手
  • \n
\n\n

总而言之,苗条的是一个很好的库,可以满足构建spa的所有需求,甚至更多. 它可以与市场上最大的玩家竞争,甚至获胜. 但是,它现在可以使用的是 前端开发人员的 社区.

\n\n

注意:本文中的所有代码都可以在 teimurjan / 苗条的-login-form GitHub库. 可以使用登录表单的演示 在这里.

\n","as":"div","isContentFit":真正的,"sharingWidget":{"url":"http://zemw3s2.yutb.net/front-end/Svelte-framework-guide","title":"A Guide to the 苗条的 Framework","text":null,"providers":["linkedin","推特","脸谱网"],"gaCategory":null,"domain":{"name":"developers","title":"工程","vertical":{"name":"developers","title":"开发人员","publicUrl":"http://zemw3s2.yutb.net/developers"},"publicUrl":"http://zemw3s2.yutb.net/developers/blog"},"hash标签s":"JavaScript,苗条的,前端"}}> < /脚本