基於Svelte3自定義元件Navbar+Tabbar沉浸式導航條|底部凸起選單欄
Svelte 一種全新的構建使用者介面的框架。當下熱門的 Vue 和 React 在瀏覽器中需要做大量的工作,而 Svelte 將這些工作放到構建應用程式的編譯階段來處理。
svelte編寫的程式具有 更少的程式碼量、無虛擬DOM、內建響應式反應能力 等特性。
◆ 準備
svelte構建的專案,結構簡單清晰。在lib目錄下新建Headerbar和Tabbar元件。
在公共模板 __layout.svelte 頁面或者需要用到元件的頁面引入元件。
import HeaderBar from '$lib/HeaderBar.svelte';
import TabBar from '$lib/TabBar.svelte';
◆ svelte自定義頂部導航欄
<!-- //自定義HeaderBar元件 --> <script> // 是否顯示回退按鈕 export let back = true // 標題 export let title = '' // 顏色 export let color = '#fff' // 背景色 export let bgcolor = '#22d59c' // 是否居中標題 export let center = false // 是否固定 export let fixed = false // 是否鏤空透明 export let transparent = false // 層級 export let zIndex = 2021 function goBack() { console.log('go back') history.go(-1) // history.back(-1) } </script> <div class="header-bar" class:transparent class:fixed={transparent||fixed}> <div class="header-bar__wrap flexbox flex-alignc" style:color style:background={bgcolor} style:z-index={zIndex}> <!-- //返回 --> {#if back && back != 'false'} <div class="action hdbar-action__left" on:click={goBack}> <slot name="backIco" /><slot name="backText" /> </div> {/if} <!-- //標題 --> <div class="hdbar-title" class:center> {#if $$slots.title} <slot name="title" /> {:else} {@html title} {/if} </div> <!-- //搜尋框 --> <div class="action hdbar-action__search"> <slot name="search" /> </div> <!-- //右側 --> <div class="action hdbar-action__right"> <slot name="right" /> </div> </div> </div> <style lang="scss"> @import url('./headerbar.scss'); </style>
和Vue相比,實現相同的功能,Svelte語法更加簡潔隨意。vue通過props自定義屬性欄位,而svelte則是export來定義匯出欄位。
headerbar.svelte 支援自定義背景(漸變色)、文字顏色、標題居中、搜尋框、沉浸式懸浮、是否固定及層疊等功能。
另外還支援自定義插槽豐富元件功能,實現一些城市選擇、按鈕、圓點提示、圖片等功能。
<HeaderBar back="false" title="標題資訊" bgcolor="#ffc107" color="#f00" center fixed zIndex="3030" />
<HeaderBar back="false" bgcolor="linear-gradient(to right, #36f4da, #f889ff)" color="#fff"> <svelte:fragment slot="title">上海 <i class="iconfont icon-arrD"></i></svelte:fragment> <svelte:fragment slot="search"> <div class="seach-box flex-c flex1"> <input class="ipt flex1" placeholder="Search..." /> </div> </svelte:fragment> <svelte:fragment slot="right"> <div class="btn"><i class="iconfont icon-weizhi"></i></div> <div class="btn"><img src="img/logo.png" height="12" alt="" /></div> </svelte:fragment> </HeaderBar>
另外設定transparent屬性,導航條會懸浮在背景或內容之上。可通過控制滾動來動態設定bgcolor屬性。
<HeaderBar back={true} bgcolor={backgroundColor} color="#f00" center transparent> <svelte:fragment slot="backIco"><i class="iconfont icon-close"></i></svelte:fragment> <svelte:fragment slot="title"><img src="img/logo.png" height="20" /><em>Svelte</em></svelte:fragment> <svelte:fragment slot="right"> <i class="iconfont icon-search"></i> <i class="iconfont icon-choose"></i> <button class="vui__btn vui__btn-primary">儲存</button> <img src="img/logo.png" /> </svelte:fragment> </HeaderBar>
在需要滾動的頁面定義一個 <svelte:window bind:scrollY={scrollTop} />
<script> // ... let backgroundColor = 'transparent' let scrollTop $: if(scrollTop) { if(scrollTop > 120) { backgroundColor = 'linear-gradient(to right, #ff0, #17fff4)' scrollTop = 120 }else { backgroundColor = 'transparent' } console.log(scrollTop) } </script>
$: 後面的函式具有響應式能力。
◆ svelte自定義底部Tabbar元件
<div class="tab-bar" class:fixed> <div class="tab-bar__wrap flexbox flex-alignc" style="background: {bgcolor}"> {#each tabs as item,i} <div class="navigator" class:on={currentTabIndex==i} on:click={changeTabs(i, item)}> <div class="ico" class:dock={item.dock}> {#if item.dock}<i class="dock-bg" style:background={item.dockBg ? item.dockBg : activeColor}></i>{/if} {#if item.icon}<i class={'iconfont '+item.icon} style:color={currentTabIndex == i && !item.dock ? activeColor : color} style:font-size={item.iconSize}></i>{/if} {#if item.img}<img class="iconimg" src={currentTabIndex == i && !item.dock ? item.activeImg : item.img} style:font-size={item.iconSize} />{/if} {#if item.badge}<em class="vui__badge">{@html item.badge}</em>{/if} {#if item.dot}<em class="vui__badge-dot"></em>{/if} </div> <div class="txt" style:color={currentTabIndex == i ? activeColor : color}>{@html item.title}</div> </div> {/each} </div> </div>
/** * @Desc Svelte自定義Tabbar元件 * @Time andy by 2022/3/12 * @About Q:282310962 wx:xy190310 */ <script> // tab預設索引 export let current = 0 // 文字顏色 export let color = '#999' // 背景色 export let bgcolor = '#fff' // 啟用顏色 export let activeColor = '#ff3e00' // 是否固定 export let fixed = false // tab選項 export let tabs = [ { path: '/', icon: 'icon-face', title: '訊息', badge: 18, }, { path: '/contact', // icon: 'icon-choose', img: 'https://img.yzcdn.cn/vant/user-inactive.png', activeImg: 'https://img.yzcdn.cn/vant/user-active.png', title: '聯絡人', }, { path: '/me', icon: 'icon-female', title: '我', dot: true, } ] import { page } from '$app/stores' import { goto } from '$app/navigation' import { onMount, createEventDispatcher } from 'svelte' const dispatch = createEventDispatcher() $: currentTabIndex = current onMount(() => { console.log('路由:', $page) console.log('路由地址:', $page.url) const curPath = $page.url.pathname tabs.map((item, index) => { if(item.path == curPath) { currentTabIndex = index } }) }) function changeTabs(index, item) { currentTabIndex = index dispatch('click', index) if(item.path) { goto(item.path) } } </script>
tabbar.svelte 支援自定義背景(漸變背景)、文字顏色|選中顏色、是否固定、中間按鈕dock凸起等功能。
<TabBar bgcolor="#ffc107" color="#fff" activeColor="#fb4e30" on:click={handleTabbar} tabs={ [ { icon: 'icon-face', title: 'Face', dot: true, iconSize: '24px' }, { img: 'https://gw.alicdn.com/tfs/TB1CoEwVrvpK1RjSZFqXXcXUVXa-185-144.png', title: '鹹魚', dock: true, dockBg: '#f00', iconSize: '30px', }, { path: '/me', icon: 'icon-female', title: '我', }, ] } />
點選選項將返回索引值。
<script> // ... // 點選tabbar選項 function handleTabbar(e) { console.log('tabbar索引值:' + e.detail) } </script>
注意:vue向父元件傳遞事件通過this.$emit(),而svelte則需要定義一個事件觸發器createEventDispatcher
import { createEventDispatcher } from 'svelte' const dispatch = createEventDispatcher() dispatch('click', 123)
ok,基於svelte自定義headerbar及tabbar元件的分享就到這裡。後續還會分享一些svelte知識。希望對大家有些幫助~☕️