苗条的生成树
In this tutorial, we will implement a Svelte component that serves as a structure for our project’s pages. It comes in handy when our pages have similar layouts and we want to react to content scroll.
在本教程中,我们将实现一个Svelte组件,该组件用作项目页面的结构。 当我们的页面具有相似的布局并且我们希望对内容滚动做出React时,它会派上用场。
The structure we will build here is composed by:
我们将在此处构建的结构由以下组成:
main content: scrollable
主要内容:可滚动
header: fixed on top of the page
标头:固定在页面顶部
footer: fixed on bottom of the page
页脚: 固定在页面底部
We can obviously adapt the component to our needs. You can skip to the end if you only want the complete component code.
显然,我们可以使组件适应我们的需求。 如果只需要完整的组件代码,则可以跳到最后。
We start adding the main content layout. This is composed by a “main” element and a slot:
我们开始添加主要内容布局。 这由一个“主要”元素和一个插槽组成:
<main bind:this={main} class:header class:footer> <slot/></main>Next to it, we add the containers for the header and footer. We kept the main slot for the content so we now need to add two named slots (“header” and “footer”):
在它旁边,我们添加页眉和页脚的容器。 我们保留了内容的主插槽,因此现在需要添加两个命名的插槽(“页眉”和“页脚”):
<div class="slotHeader"> <slot name="header"/></div><div class="slotFooter"> <slot name="footer"/></div>In the “script” tag, we now declare the “main” variable which will be binded to the “main” element, the necessary attributes “header” and “footer” which indicate if they are present, and their height, default to 64:
现在,在“ script”标签中,声明“ main”变量,该变量将绑定到“ main”元素,必要的属性“ header”和“ footer”指示它们是否存在以及它们的高度,默认为64 :
<script> let main; export let header = false; export let headerHeight = 64; export let footer = false; export let footerHeight = 64;</script>We also react to attribute changes to set the correct CSS variables for heights:
我们还对属性更改做出React,以为高度设置正确CSS变量:
$: if(main) { main.style.setProperty('--header-height', headerHeight + 'px'); main.style.setProperty('--footer-height', footerHeight + 'px');}Now, in “style” tag, we pad the content according to the attributes and fix header and footer in page:
现在,在“样式”标签中,我们根据属性填充内容并修复页面中的页眉和页脚:
<style> main { height: 100%; overflow-y: auto; } main.header { padding-top: var(--header-height, 0px); } main.footer { padding-bottom: var(--footer-height, 0px); } .slotHeader { position: fixed; top: 0px; left: 0px; width: 100%; } .slotFooter { position: fixed; bottom: 0px; left: 0px; width: 100%; }</style>Complete code
完整的代码
<main bind:this={main} class:header class:footer> <slot/></main><div class="slotHeader"> <slot name="header"/></div><div class="slotFooter"> <slot name="footer"/></div><script> let main; export let header = false; export let headerHeight = 64; export let footer = false; export let footerHeight = 64; $: if(main) { main.style.setProperty('--header-height', headerHeight + 'px'); main.style.setProperty('--footer-height', footerHeight + 'px'); }</script><style> main { height: 100%; overflow-y: auto; } main.header { padding-top: var(--header-height, 0px); } main.footer { padding-bottom: var(--footer-height, 0px); } .slotHeader { position: fixed; top: 0px; left: 0px; width: 100%; } .slotFooter { position: fixed; bottom: 0px; left: 0px; width: 100%; }</style>Let’s say that we want the header to hide and show as the user scrolls the content, as in Material Design’s App Bars. To implement this, we have to listen to main content scroll event and calculate if and when the header will hide. The same is valid for footer.
假设我们希望标题在用户滚动内容时隐藏和显示,如Material Design的App Bars中所示。 为了实现这一点,我们必须侦听主要内容滚动事件并计算是否以及何时隐藏标题。 页脚同样适用。
In layout, edit the “main” element:
在布局中,编辑“主要”元素:
<main bind:this={main} class:header class:footer on:scroll={Scroll}>And the header and footer containers:
以及页眉和页脚容器:
<div class="slotHeader" class:hide={hideHeader && scroller.hide}> <slot name="header"/></div><div class="slotFooter" class:hide={hideFooter && scroller.hide}> <slot name="footer"/></div>In “script” tag, we must declare a few new variables to keep the scrolling data, the threshold after which to hide header and footer, and if header and footer can hide on scroll:
在“ script”标签中,我们必须声明一些新变量来保留滚动数据,阈值,在此阈值之后可以隐藏页眉和页脚,以及页眉和页脚是否可以在滚动中隐藏:
let scroller = { scroll: 0, direction: true, // true: scroll down; false: scroll up delta: 0, hide: false, initialScroll: 0};export let threshold = 64;export let hideHeader = false;export let hideFooter = false;Then, we add the “Scroll” function used to calculate the current values:
然后,我们添加用于计算当前值的“滚动”功能:
const Scroll = e => { const scroll = e.target.scrollTop; scroller = { scroll, direction: scroll > scroller.scroll, delta: scroll - scroller.initialScroll, hide: scroll > threshold && scroller.hide ? scroll - scroller.initialScroll > -threshold : scroll - scroller.initialScroll > threshold, initialScroll: (scroll > scroller.scroll) != scroller.direction ? scroll : scroller.initialScroll };};To conclude, we edit the “style” tag to animate the header and footer on hide:
总而言之,我们编辑“ style”标签以在hide上设置页眉和页脚的动画:
.slotHeader { // previous code transition: all .2s ease-in-out;}.slotHeader.hide { transform: translateY(-100%);}.slotFooter { // previous code transition: all .2s ease-in-out;}.slotFooter.hide { transform: translateY(100%);}Three ways: attribute, let directive, event dispatch
三种方式:属性,let指令,事件分配
We can also expose the scroller object to the parent. It may be used for example to add a shadow to the header on scroll, or to make other page elements to show or hide reactively.
我们还可以将滚动对象公开给父对象。 例如,它可用于在滚动条的标题上添加阴影,或使其他页面元素显示或隐藏。
We can do it in three ways, I suggest to implement all of them:
我们可以通过三种方式做到这一点,我建议实施所有这些方式:
In this way you can bind:scroller on your parent
这样,您可以在父母上绑定:scroller
In this way, you can let:scroller in your parent and use it inside the Layout component
这样,您可以让:scroller进入父级并在Layout组件内使用
In this way, you can add on:scroller event to parent and maybe set to a variable
这样,您可以将on:scroller事件添加到父对象,也可以将其设置为变量
Feel free to write a comment if you have any question or suggestion
如有任何问题或建议,请随时发表评论
Thank you all, and follow me for more articles!
谢谢大家,关注我以获取更多文章!
Here are some of my other articles:
这是我的其他一些文章:
翻译自: https://medium.com/javascript-in-plain-english/create-reusable-svelte-components-for-your-page-layouts-9593b1a60b08
苗条的生成树
