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

uni-app 自定义导航栏|支持 H5/小程序/App 端

  •  
  •   xiaoyan2017 · 2019-09-17 14:00:47 +08:00 · 2900 次点击
    这是一个创建于 1927 天前的主题,其中的信息可能已经有所发展或是发生改变。

    基于uniapp 自定义导航栏|仿微信、淘宝顶部导航条,支持背景渐变、标题居左 /居中、搜索条,圆点提示,按钮可自定义传入文字 /字体图标 /图片

    对于如何实现导航栏设置,可通过 uni-app 原生导航配置或自定义导航栏两种方法都行

    uni-app 原生导航条

    uni-app 原生导航栏也能实现一些顶部自定义按钮+搜索框,只需在 page.json 里面做一些配置即可。设置 app-plus,dcloud 平台对 app-plus 做了详细说明:app-plus 配置,不过目前暂支持 H5、App 端,不支持小程序。

    在项目 page.json 里面配置 app-plus

    {
        "path": "pages/ucenter/index",
        "style": {
            "navigationBarTitleText": "我的",
            "app-plus": {
                "titleNView": {
                    "buttons": [
                        {
                            "text": "\ue670",
                            "fontSrc": "/static/iconfont.ttf",
                            "fontSize": "22px",
                            "float": "left"
                        },
                        {
                            "text": "\ue62c",
                            "fontSrc": "/static/iconfont.ttf",
                            "fontSize": "22px"
     
                        }
                    ],
                    "searchInput":{
                        ...
                    }
                }
            }
        }
    },
    

    uni-app 自定义导航条

    那如何实现像微信、京东顶部导航栏,支持背景色渐变、标题居左、居中、搜索条、按钮自定义。。。 将 navigationStyle 设为 custom 或 titleNView 设为 false 时,原生导航栏不显示,这时就能自定义导航栏

    "globalStyle": { "navigationStyle": "custom" }

    具体效果实例如下:

    不过在 H5、小程序、App 端状态栏需重新计算处理,下面为大家提供一种处理方法,在 App.vue 里面设置即可

    onLaunch: function() {
        uni.getSystemInfo({
            success:function(e){
                Vue.prototype.statusBar = e.statusBarHeight
                // #ifndef MP
                if(e.platform == 'android') {
                    Vue.prototype.customBar = e.statusBarHeight + 50
                }else {
                    Vue.prototype.customBar = e.statusBarHeight + 45
                }
                // #endif
                
                // #ifdef MP-WEIXIN
                let custom = wx.getMenuButtonBoundingClientRect()
                Vue.prototype.customBar = custom.bottom + custom.top - e.statusBarHeight
                // #endif
                
                // #ifdef MP-ALIPAY
                Vue.prototype.customBar = e.statusBarHeight + e.titleBarHeight
                // #endif
            }
        })
    },
    

    <header-bar :isBack="false" title="标题信息" titleTintColor="#fff">
        <text slot="back" class="uni_btnIco iconfont icon-arrL"></text>
        <text slot="iconfont" class="uni_btnIco iconfont icon-search" @tap="aaa"></text>
        <text slot="iconfont" class="uni_btnIco iconfont icon-tianjia" @tap="bbb"></text>
        <!-- <text slot="string" class="uni_btnString" @tap="ccc">添加好友</text> -->
        <image slot="image" class="uni_btnImage" src="../../static/logo.png" mode="widthFix" @tap="ddd"></image>
    </header-bar>
    

    <header-bar :isBack="true" titleTintColor="#fff" :bgColor="{'background-image': 'linear-gradient(45deg, #007AFF 10%, #005cbf)'}" search>
        <text slot="back" class="uni_btnIco iconfont icon-arrL"></text>
        <text slot="iconfont" class="uni_btnIco iconfont icon-choose03" @tap="aaa"></text>
        <image slot="image" class="uni_btnImage" src="../../static/logo.png" mode="widthFix" @tap="ddd"></image>
    </header-bar>
    

    <header-bar :isBack="true" title="我的" titleTintColor="#fff" :bgColor="{background: '#353535'}">
    	<text slot="back" class="uni_btnIco iconfont icon-close"></text>
    	<text slot="iconfont" class="uni_btnIco iconfont icon-search"></text>
    	<text slot="string" class="uni_btnString" style="color: #2B9939;">添加好友</text>
    </header-bar>
    

    /**
     * @tpl 顶部导航模板(自定义) by andy  Q:282310962
     */
    <template>
        <view class="uni_topbar" :style="style">
            <view class="inner flexbox flex_alignc" :class="[fixed ? 'fixed' : '']" :style="[{'height': customBarH + 'px', 'padding-top': statusBarH + 'px', 'color': titleTintColor}, bgColor]">
                <!-- 返回 -->
                <!-- <text class="uni_icoBack iconfont icon-arrL" v-if="isBack" @tap="goBack"></text> -->
                <view v-if="isBack" @tap="goBack">
                    <slot name="back"></slot>
                </view>
                <slot name="headerL"></slot>
                <!-- 标题 -->
                <!-- #ifndef MP -->
                <view class="flex1" v-if="!search && center"></view>
                <!-- #endif -->
                <view class="uni_title flex1" :class="[center ? 'uni_titleCenter' : '']" :style="[isBack ? {'font-size': '32upx', 'padding-left': '0'} : '']" v-if="!search && title">
                    {{title}}
                </view>
                <view class="uni_search flex1" :class="[searchRadius ? 'uni_searchRadius' : '']" v-if="search"> />
                    <input class="uni_searchIpt flex1" type="text" placeholder="搜索" placeholder-style="color: rgba(255,255,255,.5);" />
                </view>
                <!-- 右侧 -->
                <view class="uni_headerRight flexbox flex_row flex_alignc">
                    <slot name="iconfont"></slot>
                    <slot name="string"></slot>
                    <slot name="image"></slot>
                </view>
            </view>
        </view>
    </template>
     
    <script>
        export default {
            data() {
                return {
                    statusBarH: this.statusBar,
                    customBarH: this.customBar
                }
            },
            props: {
                isBack: { type: [Boolean, String], default: true },
                title: { type: String, default: '' },
                titleTintColor: { type: String, default: '#fff' },
                bgColor: Object,
                center: { type: [Boolean, String], default: false },
                search: { type: [Boolean, String], default: false },
                searchRadius: { type: [Boolean, String], default: false },
                fixed: { type: [Boolean, String], default: false },
            },
            computed: {
                style() {
                    let _style = `height: ${this.customBarH}px;`
                    return _style
                }
            },
            methods: {
                goBack() {
                    uni.navigateBack()
                }
            }
        }
    </script>
    

    作者:xiaoyan2015
    链接: https://juejin.im/post/5d806bd36fb9a06ad005a2a7
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    6 条回复    2019-09-18 13:29:10 +08:00
    gaigechunfeng
        1
    gaigechunfeng  
       2019-09-17 15:54:41 +08:00
    v 站就是吹水站。
    楼主的干货帖子倒没人顶了,哈哈。
    我支持一把,正在使用 uniapp,make 一下
    aaronlam
        2
    aaronlam  
       2019-09-17 16:17:10 +08:00
    挺不错的干货
    xnode
        3
    xnode  
       2019-09-17 16:20:11 +08:00
    干活 正好最近可能要用 支持一下
    Shook
        4
    Shook  
       2019-09-18 00:49:31 +08:00
    借楼问下,uniapp 里使用自定义组件模式,发现.vue 组件在 html 的表现和用 mpvue 时不一样。
    具体的体现是:
    假设一个名为 list 的组件模板内容:<div>content</div>
    那么在 mpvue 的 html 表现:<div>content</div>
    在 uniapp 的自定义组件模式表现:<div class="list"><div>content</div></div>

    大概是这样,记得不是很清楚,意思就是自定义组件模式会比 mpvue 多一层,所以一些样式就会显示错误…请问这种情况该怎么处理,只能给组件加个对应的样式调整一下么?这样的话整个项目的组件都要检查了。
    pdfgo
        5
    pdfgo  
       2019-09-18 07:55:54 +08:00 via Android
    最近做小程序,用的是 colorui 的自定义导航栏,在 ios 系统上,经常出现不能正确设置导航栏高度的问题,请问 uni-app 把这个问题解决了吗?
    id7368
        6
    id7368  
       2019-09-18 13:29:10 +08:00
    支持下
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2957 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 00:34 · PVG 08:34 · LAX 16:34 · JFK 19:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.