svelte組件:Svelte3自定義Navbar+Tabbr組件|svelte自定義插件


基於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知識。希望對大家有些幫助~☕️

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM