RE:痛苦和眼泪在Svelte 3

而不是前言


这篇文章是对昨天文章“ Svelte 3中的疼痛和眼泪”的回应,它是由于对原始文章的评论非常“胖”而出现的,我决定将其设计为文章。 在下文中,我将使用“ 作者 ”一词指代原始文章的作者,并允许我自己对所有观点进行一些说明。 走吧



谁是斯维尔特?


当我看到原始文章的标题时,起初我很高兴。 我想现在,我会读到一些深刻而建设性的批评。 最重要的是,有陷阱的有趣案例不是来自“沙发专家”,而是来自“谁可能”。 阅读后,热情降低了,但是非常感谢vds64_max的文章。

尽管并非所有事情都能解决,但我认为我需要更多文章来描述Svelte中的实际问题及其解决方案。 至少他没有落后于React和Vue等知名同志。 毕竟,最终读者可能会觉得Svelte太完美了,但事实并非如此。

讲解


我不明白作者在这方面的想法。 教程行之有效,效果很好。 我想作者只是由于他的项目的截止日期才表面上与他相识并且不了解工作原理。 在某些情况下,人们没有立即理解分步教程的含义,而为了使该示例生效,必须采取一些措施。 自己尝试!

UI套件和样式



为Svelte寻找UI套件对我们所有人来说都是一个单独的痛苦。 我想大声疾呼:“至少是材料,引导程序……至少是某些东西……”。

首先,原则上,UI鲸不是所有项目都适用。 其次,并非所有用于其他框架的UI套件都能很好地工作。

主要问题始于该项目具有非常混乱和自定义的设计,而鲸鱼通常仍具有有限的自定义方式。 如果我们在谈论管理面板,我同意拥有UI工具包是有用的,但是并不是每个人都写管理面板,而且从Svelte的后台获得的收益将不会那么明显。

该链接也可以在Svelte的其他UI鲸中找到。

由于Svelte以“不同的方式”与DOM一起工作,MaterialUI开始弄清与显示如何通过js添加到dom的UI组件有关的各种讨厌的事情。 例如,每隔一段时间显示一次简单的微调器:

我不明白句子开头的含义以及Svelte如何以“不同的方式”准确地与DOM协同工作,但总的来说,整个论文听起来至少是不认真的。 如果您尝试将与DOM一起使用的第三方库集成到管理DOM的任何框架(React / Vue / Angular / Ember)中,您都会遇到完全相同的问题。 立刻有一种感觉,作者从未这样做过。

此外,Svelte有一个很棒的机制,称为action ,通过这种机制,与任何第三方DOM的集成都减少了,可以编写一个小的函数。 似乎作者直到这一刻都没有读过基座。 好吧,它发生了。

例如,在2分钟内实现MDCSlider: REPL


请告诉我,在哪里更容易?

程式化


使用样式,一切都非常清晰,我们将所有样式都填充到Vue中。 您编写了样式,一切都很好,然后编写了一个UI组件(因为没有UIKit),该组件应带有props参数,例如width和height,并在逻辑上这样做:
...
而且...不,在这种风格下,您无法插入变量。

据我所知,在Vue中,状态也不能在组件样式内使用,在React中,根本没有使用样式的工作。

虽然,我可以理解在样式中使用动态的愿望,但是有很多原因不建议这样做:

  • 样式中出现一部分组件状态后,必须为每个组件实例复制这些样式。 立即提出具有复杂设计的1000个项目的清单。 我们需要吗?
  • 在CSS中使用动力学会导致大量不必要的重绘,并且效率极低。

在Svelte中使用动态样式的替代方法:

  • 使用class指令更改类
  • 将内联样式与样式属性一起使用
  • 使用CSS自定义属性(变量)
  • 使用Emotion之类的CSS-in-js解决方案( 本文

既然提到了Vue,让我们比较一下动态内联样式的用法:

<button v-on:click="fontSize++">Increase font size</button> <button v-on:click="fontSize--">Decrease font size</button> <p v-bind:style="{ fontSize: fontSize + 'px' }">Font size is: {{ fontSize }}</p> 

 <button on:click={e => fontSize++}>Increase font size</button> <button on:click={e => fontSize--}>Decrease font size</button> <p style="font-size: {fontSize + 'px'}">Font size is: {fontSize}</p> 

替换

总的来说,我看不出有什么特别的区别,但是由于某种原因,作者认为Vue的一切都很好,但Svelte却没有。 真奇怪

顺便说一下,借助反应式声明,将所有动态样式集中在一个地方非常方便:

 <div {style}>....</div> <script> let fontSize = 10; let color = 'red'; let width = 50; $: style = ` font-size: ${fontSize}px; color: ${color}; width: ${width}px; `; </script> 

通常,这对于99%的情况就足够了,其余的可以使用主题和/或CSS自定义属性解决

路由和路由器


通常,Svelte是一个UI框架,与路由器无关。 此外,外部Svelte api使得只需几分钟和几行代码即可轻松集成任何独立的路由器。 例如, page.js

 import page from 'page'; import App from './App.svelte'; const app = new App({ target: document.body }); page('/posts', ctx => { //     dynamic import & code-splitting app.$set({ ctx, page: import('./Posts.svelte') }); }); page('/', ctx => { app.$set({ ctx, page: import('./Home.svelte') }); }); page.start(); export default app; 

 <nav> <a href="/">Home</a> <a href="/posts">Posts</a> </nav> <main> {#await page} <p>Loading...</p> {:then comp} <svelte:component this={comp.default || comp} {...ctx} /> {/await} </main> <script> export let page = null, ctx = null; </script> 

难吗 作者仅在特定实现,特定路由器上遇到问题。 另外,温和地说,这并不是Svelte最好的,因为它复制了所有问题的React Router。 您可以在这里找到许多其他路由器。

失误


与React不同,React根本不允许您创建捆绑包,并且会对错误大声尖叫,Svelte会完美地收集所有包含错误的内容。 同时,如果您忘记了一些东西,请安装npm install或export,一切都会好起来,并且只显示白屏(顺便说一句,在React的第一个版本中就是这种情况)。

React不会为您收集任何东西。 收集器收集。 在这种情况下,我很希望作者与Rollup合作,并且很可能是第一次这样做。 在我看来,要么研究您将要使用的工具,要么不使用它是有意义的。 我要补充一点,作者写的东西在斯维尔特中没有得到遵守。 至少在其他框架中出现的问题很少出现。 对于其他框架,作者很可能已经设置好一切并开始工作,但是在这里他懒得这么做。

有一个假设,即作者也意味着要使用道具,这在Svelte中是通过组件的导出来进行的,但是即使在这里,如果您尝试抛出组件未定义的道具,则始终会显示警告:


Svelte只需要命名约定


在没有命名约定的情况下,您会经常遇到此问题。

我真的很喜欢这个短语,因为从本质上讲它可以用于任何项目/库/编程语言。 这里的狡猾之处在于,您将以同样的方式到处遇到这种情况。 例如,在同一React中:

 class MyComponent extends React.Component { constructor(props) { super(props); this.dialog = null; this.loading = false; this.pins = []; this.stitch = null; } render() { return <dialog ref={el=> this.dialog = el} class="mdl-dialog» />; } } 

通常,所有内容都是相同的,您将需要以某种方式“理解”元素上的refk,以及使用后端或download标志的对象是什么。 看来,如果您的团队昨天没有开会,那么所有这些问题都应该早就解决。

通常,当然,如果您的项目和团队没有命名约定,那么Svelte将不会为您提供帮助。 我在项目中使用的一些东西:

 <!--  ,      --> <Modal {open}> <!--      --> <!--  ,     ,      --> <form on:submit|preventDefault={save}> <!--  ,   --> <input bind:value={firstName} placeholder="First name"> <input bind:value={lastName} placeholder="Last name"> <input bind:value={birthDay} use:asDatepicker placeholder="Birthday"> <button bind:this={btnEl}>Save</button> </form> </Modal> <button on:click={e => open = true}>Open</button> <!--   --> <script> //     //  -  ,     import Modal from '~/components/Modal'; //     `as`,   `use:as<something>` import asDatepicker from '~/actions/datepicker'; //    -  observerable,    cycle/rx import user$ from '~/stores/user'; import { saveUser } from '/api'; //     let firstName = '', lastName = '', birthDay = ''; let open = false; let btnEl; //           let refs = {}; //       async function save() { const patch = { firstName, lastName, birthDay }; await saveUser(patch); $user$ = { ...$user$, ...patch }; } //          export { open, save }; </script> <!--   --> <style> /* ... */ </style> 

另外,通常我的组件的“预算”包括样式的200行代码。 如果多一点-不可怕。 如果更大,我为组件创建一个文件夹,然后开始使用svelte-preprocess从样式开始将零件移动到单独的文件中。 在这种情况下,对收集器进行了配置,以使导入不会更改。

发生了什么变化,何处发生了变化?




结果,您可以很快地编写组件,但是几天后,当他已经忘记了(有时甚至是他的名字)时,很难理解大三在这个“ Venegret”中写的内容。 因此,如果没有在项目或团队中清楚地组织代码,就不可能理解其中的内容。

一个有趣的论点,最重要的是,它再次普遍适用于任何框架和项目。 而且,现代React中的钩子语法受到Vue的创建者的喜爱,以至于他甚至决定在Vue 3中紧急实现它,它将具有相同的冲突:

 import React, { useState, useCallback } from 'react'; function MyComponent() { const [ loading, setLoading ] = useState(false); const [ status, setStatus ] = useState(0); const [ pins, setPins ] = useState([]); const ReloadPins = useCallback(async () => { setLoading(true); setPins(await getAllPins()); setStatus(0); }); return (<div></div>); } 



 <div></div> <script> let loading = false; let status = 0; let pins = []; async function ReloadPins() { loading = true; pins = await getAllPins(); status = 0; } </script> 

如您所见,所有内容都是一样的,只有2倍的涂鸦。

当然,只是开玩笑,还不清楚。 此外,状态甚至不明确,还是只是一个辅助变量。 在React中,这是由状态决定的,这至少在某种程度上带来了清晰度。

实际上,“了解”模板中使用了哪个组件状态变量,以及仅对于脚本起作用才是必需的。 在Svelte中,根本没有这种分离,变量通常存在于JS中-它们存在于自己的作用域中,有些具有整个组件作用域,另一些则存在于单个函数或另一个代码块中。 没有什么新鲜的或意外的。 仅了解一件事很重要-仅在状态的相关部分更改时才重新计算DOM。

例如,在同一React中,如果您这样做:

 this.setState({ foo: 1 }) 

并且在模板中未使用foo时 ,VDOM机制将无法以任何方式理解这一点,并将产生重新渲染/协调。 你知道吗 因此,了解React中使用的模板和未使用的模板在React中可能很重要。 在斯维尔特,我们没有这种动荡。

因此,在这里,我只能向作者表示赞同-如果您的项目和团队没有清晰的组织,则任何项目的任何工具都将出现问题。 实际上,作者项目的一个例子就是对此的直接证明。

装订针


当然,这是由于收藏家的缘故。 作者不应该对新工具如此轻描淡写。 默认情况下,Svelte附带Rollup,即装即用的功能比Webpack少得多,但是它收集了更多优化和更多本机包。 可以使用插件来自定义任何其他功能。 如果您不想洗个澡,则可以使用Webpack社区中其他任何人官方模板 ,因为其中有很多。

为什么需要斯维尔特?


在这一段中,我将更简短-对于React或Vue足够的任何新项目。 与Angular或Ember进行比较没有任何意义,因为它们是不同规模的框架。

基于后者,我真的不明白为什么Svelte维护者会提供TypeScript支持? 我们喜欢Svelte只是为了“投足”,而我认为TypeScript就像Svelte跑车的全地形赛道。 您知道,与Svelte一起工作后,我意识到JS近年来发生了很大变化,并且不再是JS。

Svelte提供了使用相同的旧版JS工作的机会,而无需PropTypes,Flow和TypeScript。

我不能不同意这个说法。 实际上,Svelte并不需要TS。 尽管借助预处理器 (没有taypechek模板)对它有部分支持,但是总的来说,它更多地是一个附件,否则,您将无法编写好的组件。

为什么不值得使用Svelte?


  1. 如果您的项目已经编写在另一个框架上并且运行良好。 无需运行并重写它。
  2. 即使在第1点中也有机会之窗-您可以在Svelte上重写一些“繁重的”组件。 该项目将变得更加容易,并且组件将运行得更快。 您不必重写所有内容。
  3. 如果您正在编写企业,则Angular或Ember可能是最佳选择。 像React和Vue一样,Svelte并非总是一个好的选择。
  4. 如果需要一流的 Typescript支持。
  5. 如果您专门开发标准解决方案,并且习惯于从现成的组件组装项目。
  6. 仍然比有经验的同志更弱。 如果这很关键,那么值得等待,或者加入我们的社区并一起开发调优。)))

***

通常,不幸的是,原始文章的大多数结论都是基于错误的假设,并且会误导读者。 鉴于我在Telegram @sveltejs的俄语Svelte社区中没有看到作者( 超过 1K位参与者),因此我得出结论,作者和他的团队没有花足够的精力来掌握一个未知的新工具。 我认为,如果这些人只是添加到聊天室中,大多数问题都可以避免。 目前,这些家伙似乎得出了仓促的结论,但这是他们的个人问题。

Source: https://habr.com/ru/post/zh-CN469411/


All Articles