V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiaoyan2017
V2EX  ›  推广

Nuxt.js 自定义 Navbar+Tabbar 组件|Vue 仿咸鱼 Tab 凸起效果

  •  
  •   xiaoyan2017 · 2020-10-10 17:48:26 +08:00 · 1793 次点击
    这是一个创建于 1534 天前的主题,其中的信息可能已经有所发展或是发生改变。

    说明

    这段时间都忙着开发 Nuxt 项目,鉴于项目中需要用到顶部导航栏 /底部咸鱼效果 Tab,于是就定制了这个功能组件。 Nuxt/Vue 自定义 Navbar|Tabbar 组件

    如下图:项目中实例效果展示

    okey,下面就着重讲解下具体实现过程。

    首先,需要在 components 目录下新建两个 headerBar.vue 和 tabBar.vue 页面。

    再接着,在 plugins 目录下新建 componentsInstall.js 文件并引入即可。

    自定义导航条 headerBar.vue 组件

    <template>
        <div class="header-bar" :class="{'fixed': fixed, 'transparent fixed': transparent}">
            <div class="header-bar__wrap flexbox flex-alignc" :style="{'background': bgcolor, 'color': color, 'z-index': zIndex}">
                <!-- >>返回 -->
                <div class="action hdbar-action__left isback" v-if="back && back!='false'" @click="$router.go(-1)">
                    <slot name="backIco" /><slot name="backText" />
                </div>
     
                <!-- >>标题 -->
                <div class="hdbar-title" :class="{'center': center}">
                    <slot name="title" />
                </div>
     
                <!-- >>搜索框 -->
                <div class="action hdbar-action__search">
                    <slot name="search" />
                </div>
     
                <!-- >>右侧 -->
                <div class="action hdbar-action__right">
                    <slot name="right" />
                </div>
            </div>
        </div>
    </template>
    
    <script>
    /**
     * @Desc     Vue 自定义导航条 headerBar
     * @Time     andy by 2020-10-06
     * @About    Q:282310962  wx:xy190310
     */
        export default {
            props: {
                // 是否返回
                back: { type: [Boolean, String], default: true },
                // 标题
                title: { type: String, default: '' },
                // 标题颜色
                color: { type: String, default: '#fff' },
                // 背景颜色
                bgcolor: { type: String, default: '#22d59c' },
                // 标题是否居中
                center: { type: [Boolean, String], default: false },
                // 搜索框
                search: { type: [Boolean, String], default: false },
                // 是否固定
                fixed: { type: [Boolean, String], default: false },
                // 背景透明
                transparent: { type: [Boolean, String], default: false },
                // 设置层级
                zIndex: { type: [Number, String], default: '2021' },
            },
            data() {
                return {}
            },
            methods: {},
        }
    </script>
    

    <header-bar :back="true" :bgcolor="linear-gradient(to right, #f726ff, #2acfff)" color="#ff0" center transparent>
        <template #backIco><i class="iconfont icon-close"></i></template>
     
        <div slot="title">
        <img src="~/assets/img/logo.png" height="14" /> <em>Nuxt</em>
        </div>
     
        <div slot="right" class="ml-20" @click="$toast('搜索~~')"><i class="iconfont icon-search"></i></div>
        <div slot="right" class="ml-20"><i class="iconfont icon-choose"></i></div>
        <div slot="right" class="ml-20"><van-button type="primary" size="mini" @click="saveData">保存</van-button></div>
    </header-bar>
    

    <header-bar :back="true" bgcolor="linear-gradient(to right, #6126ff, #ff21ee)" color="#ff0" center>
        <div slot="backIco"><i class="iconfont icon-close"></i></div>
        <div slot="search" class="flex-c flex1">
            <input class="ipt flex1" placeholder="搜索关键字..." />
        </div>
        <div slot="right" class="ml-30"> <i class="iconfont icon-shoucang"></i></div>
        <div slot="right" class="ml-30"> <i class="iconfont icon-female"></i></div>
    </header-bar>
    

    自定义 tabBar 组件

    <template>
        <div class="tab-bar" :class="{'fixed': fixed}">
            <div class="tab-bar__wrap flexbox flex-alignc" :style="{'background': bgcolor}">
                <div v-for="(item,index) in tabs" :key="index" class="navigator" :class="currentTabIndex == index ? 'on' : ''" @click="switchTabs(index, item)">
                    <div class="ico" :class="{'dock': item.dock}">
                        <i v-if="item.dock" class="dock-bg" :style="{'background': item.dockBg ? item.dockBg : activeColor}"></i>
                        <i v-if="item.icon" class="iconfont" :class="item.icon" :style="{'color': (currentTabIndex == index && !item.dock ? activeColor : color), 'font-size': item.iconSize}"></i>
                        <img v-if="item.iconImg" class="iconimg" :src="currentTabIndex == index && !item.dock ? item.selectedIconImg : item.iconImg" :style="{'font-size': item.iconSize}" />
                        <em v-if="item.badge" class="nuxt__badge">{{item.badge}}</em>
                        <em v-if="item.dot" class="nuxt__badge-dot"></em>
                    </div>
                    <div class="txt" :style="{'color': (currentTabIndex == index ? activeColor : color)}">{{item.text}}</div>
                </div>
            </div>
        </div>
    </template>
    
    <script>
      export default {
        props: {
            current: { type: [Number, String], default: 0 },
            // 背景颜色
            bgcolor: { type: String, default: '#fff' },
            // 颜色
            color: { type: String, default: '#999' },
            // 点击后颜色
            activeColor: { type: String, default: '#22d59c' },
            // 是否固定
            fixed: { type: [Boolean, String], default: false },
            // tab 选项
            tabs: {
                type: Array,
                default: () => null
            }
        },
        data() {
          return {
              currentTabIndex: this.current
          }
        },
        created() {
            const _pagePath = this.$route.path
            this.tabs.map((val, index) => {
                if(val.pagePath == _pagePath) {
                    this.currentTabIndex = index
                }
            })
        },
        methods: {
            switchTabs(index, item) {
                this.currentTabIndex = index
                this.$emit('click', index)
                if(item.pagePath) {
                    this.$router.push(item.pagePath)
                }
            }
        },
      }
    </script>
    

    <tab-bar bgcolor="#b6ffff" @click="handleTabbar" :tabs="[
        {
            icon: 'icon-tianjia',
            text: 'Home',
        },
        {
            icon: 'icon-shezhi',
            text: 'Manage',
            badge: 1
        },
        {
            icon: 'icon-male',
            text: 'Ucenter',
            dot: true
        },
        ]"
    />
    
    // tabbar 点击事件
    handleTabbar(index) {
        this.$toast('tabbar 索引值:' + index);
    },
    

    另外还支持自定义 tab 数量及配置 dock:true 即可实现凸起 tab 效果。

    <tab-bar bgcolor="#7fa1ff" color="#fff" activeColor="#fb4e30" :tabs="[
        {
            icon: 'icon-face',
            text: 'Face',
            dot: true,
            iconSize: '24px',
        },
        {
            //icon: 'icon-tianjia',
            iconImg: 'https://gw.alicdn.com/tfs/TB1CoEwVrvpK1RjSZFqXXcXUVXa-185-144.png?getAvatar=1',
            text: '咸鱼',
            dock: true,
            dockBg: '#fb4e30',
            iconSize: '.64rem',
        },
        {
            icon: 'icon-search',
            text: '搜索',
        },
        ]"
    />
    

    好了,使用 Nuxt.js 实现自定义 Tabbar+Navbar 组件就分享到这里。希望对大家有所帮助!👊👊

    作者:xiaoyan2017
    链接: https://segmentfault.com/a/1190000037424946
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1742 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:15 · PVG 00:15 · LAX 08:15 · JFK 11:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.