书接上文
Svelte 中的 $
React 中因为机制问题,我们使用 useEffect
和其他钩子,会在重新渲染组件时重新运行钩子的代码。 Svelte 的不同之处在于,默认情况下,您的大部分代码只会运行一次;组件中的 console.log('foo')
行只会在该组件首次呈现时运行。而在 React 中,它会运行很多次。
React 的重新渲染方法有其优点:假设您正在接收大量数据并运行一些函数将其转换为可以渲染的数据。在 React 中,在你的组件中,你可以这样写:
const input = props.inputData
const transformed = input.map((item) => transformItem(item))
return <div>{JSON.stringify(transformed, null, 2)}</div>
—如果用户提供新的 props.inputData
得到的是最新的数据,组件将重新渲染并更新输出。
而在 Svelte 中情况并非如此:
<script>
export let input;
const transformed = input.map((item) => transformItem(item))
</script>
<div>{JSON.stringify(transformed, null, 2)}</div>
这里的输出将在第一次渲染组件时渲染,但之后根本不会更新。
但我们可以通过两种方式解决这个问题,一种是使用 $:
标签语法,将代码标记为反应式,另一种是将我们的转换逻辑移到模板中:
SideTabs
<script>export let input;$: transformed = input.map((item) => transformItem(item))</script><div>{JSON.stringify(transformed, null, 2)}</div>
这是 Svelte 使用 JavaScript 语法并将其用于略有不同含义的另一个示例;它告诉 Svelte 该语句是响应式的,如果任何导入发生变化,应该重新计算。您也可以将其称为“计算属性”。第二种解决方案只是将逻辑移动到模板中,从而确保当组件重新呈现时再次执行逻辑。在我使用 Svelte 的时候,这是我大部分时间采用的方法,通常将逻辑提取到一个函数中:
<div>{calculateOutputForItems(input)}</div>
从 React 到 Svelte,这确实让我困惑了很多次,但对我来说,我现在更喜欢 Svelte 的方法,特别是因为它删除了 useEffect
周围的一些样板。
组件组合
组件组合是决定使用基于组件的框架是否愉快的重要组成部分,这也是 React 和 Svelte 都能很好地解决的问题。 React 的 children
属性使得呈现任何提供的内容变得非常容易:
function Box(props) {
return <div>{props.children}</div>
}
function App() {
return (
<Box>
<p>hello world!</p>
</Box>
)
}
Svelte 使用 slots 做类似的事情:
<!-- Box component -->
<div class="box">
<slot></slot>
</div>
<!-- App component -->
<Box>
<p>hello world!</p>
</Box>
当涉及多个孩子时,他们采取不同的方法,这就是我发现自己更喜欢 Svelte 方法的地方。 React 建议通过多个props:
function Box(props) {
return (
<div>
<div class="left">{props.left}</div>
<div class="right">{props.right}</div>
</div>
)
}
function App() {
return <Box left={<p>hello</p>} right={<p>world!</P>} />
}
我对这种方法的一个抱怨是,您失去了将子级传递到 Box 组件的视觉提示;现在,当您像我们在 HTML 中那样渲染它们时,它们不再嵌套在 Box 中;现在你可以很容易找到提供给子组件的props是哪些。但在真实业务场景中会很难!
Svelte 的方法是定义多个具有显式名称的插槽,让用户提供应该填充这些插槽的元素:
<!-- Box component -->
<div class="box">
<slot name="left"></slot>
<slot name="right"></slot>
</div>
<!-- App component -->
<Box>
<p slot="left">hello</p>
<p slot="right">world!</p>
</Box>
我更喜欢这种方法,因为我可以扫描呈现 Box
组件的代码并轻松发现它需要两个children
。如果 Box
使用任何 props,它们将位于 <Box>
开头标签内,并且它们将与其余的props不同。
我在这里的偏好是因为我每天都在构建 Web 组件,所以 Svelte 的方法对 Web 组件中的插槽感觉非常熟悉。
原文链接:https://juejin.cn/post/7228587400150007845 作者:前端代码王