Bootstrap

2.13 页面链接:如何自定义一个导航栏?

视频链接:

2.13 页面链接:如何自定义一个导航栏?

片 1

 

上节课我们学习了滚动选择器,以及如何在 wxs 脚本里自定义实现一个竖向的 slider 组件。这节课我们开始学习导航组件,以及如何在小程序里面实现一个自定义的导航栏。

 

1,functional-page-navigator

2,navigator

片 2

 

小程序的导航组件不多,一共有两个(见上面列表)。第一个导航组件,functional-page-navigator 是在插件中使用,仅能跳转到插件的功能页。

 

小程序插件是对一些 js 接口、自定义组件或页面的封装,可以嵌入到小程序中去使用。插件不能独立运行,它必须嵌入在其他小程序中才能被用户使用。而使用第三方插件时,我们也无法看到插件的源码。插件适合用来封装功能或者是服务,提供给第三方小程序使用。

 

第二个导航组件,navigator 是小程序标准的导航组件。虽然是一个组件,便是通过设置不同的跳转方式 open-type 这个属性,可以实现不同的跳转功能。

 

navigate

redirect

switchTab

reLaunch

navigateBack

exit

片 3

 

我们看一下这个列表,open-type 一共有六个合法值。第一个类型 navigate,相当于接口 wx.navigateTo 或 wx.navigateToMiniProgram 的功能,代表页面跳转或小程序跳转。

 

当是页面跳转的时候,需要同时设置 url 这个属性,url 是目标页面的地址,和我们在 app.json 中设置的 page url 是一样的。

 

当是小程序跳转时,要将 target 属性设置为 miniProgram,同时提供一个 app-id 属性,app-id 是要跳转的目标小程序的 appId,这个信息呢,我们在前面注册小程序的时候讲过,它是在微信公众平台的后台查看的。如果跳转别的小程序的时候,还需要带上额外的参数,要在 extra-data 这个属性中去设置。

 

第二个类型 redirect,相当于接口 wx.redirectTo 的功能。使用这个类型,需要同时设置 url 属性。需要注意的是,使用这个类型时,设置的 url 不能是 tab 页面,否则跳转是无效的。

 

第三个类型 switchTab,相当于接口 wx.switchTab 的功能,这个类型仍然同时需要一个 url 属性,并且这个 url 和 navigate 或 redirect 类型的 url 并没有什么不同,在使用的时候要特别注意一下,如果是 tab 页跳转,只有使用这个类型才是有效的。

 

第四个类型 reLaunch,相当于接口 wx.reLaunch 重启小程序的功能。

 

第五个类型 navigateBack,对应接口 wx.navigateBack 的功能,使用这个类型时,同时可以设置 delta 这个属性,它表示回退的层数。这个层数是大于等于 1 的,1 表示回到上一页,2 表示回到上上页。如果 delta 大于现有的页面数,就返回到首页。

 

第六个类型 exit,表示退出小程序,使用这个类型,同时要将 target 设置为 miniProgram。

 

从以上 6 个类型来看,navigator 这个组件,更像是一个复合组件,将多个接口的功能复合在一起了。

 

在小程序的导航中,导航栏非常重要,默认导航栏中没有回到首页,及返回到上一页的按钮。但是大多数小程序都需要这样的导航设置。有的小程序还可以实现透明的导航栏,不但导航栏透明,而且系统状态栏也透明,这是怎么实现的呢?我们看一个示例。

 

片 4

 

这个是微信圈子的截图。最上面有电池图标的区域,是系统状态栏,下面有小程序胶囊按钮的区域,是导航栏。其中标题在导航中显示。从效果中可以看到,微信圈子的状态栏、导航栏默认都是透明的,而当内容向上滚动到一定程度时,状态栏、导航栏区域背景变白,同时标题也显示出来了(见上面效果图)。

 

这个功能呢,大家可以去微信里面,搜索微信圈子就可以看到这个效果了,那上面这个是我自己创建的一个微信圈子的运行截图。

 

这个微信圈子的导航栏功能,就是通过导航栏自定义实现的。

 

{

"navigationStyle": "custom"

}

片 5

 

在每个小程序页面的 json 配置页面中,都可以通过设置 navigationStyle 为 custom,开启页面导航栏的自定义。在开启以后,系统状态栏也会透明,但状态栏上面有许多信息,例如电池啊,时间啊,WiFi 信号啊等等,也不适合放置组件,所以一般情况下,都只是将状态栏同时透明化处理。

 

片 6

 

我们看一下,这是我们自定义实现的效果,默认情况下,状态栏和导航栏都是透明的,下面有一个背景图。当页面向上滚动到一定程度时,背景完全看不到了,导航栏和状态栏变白,同时返回按钮、主页按钮由白色变成黑色,页面标题由不显示变成显示。

 

这个效果很常见,在很多品牌小程序中都使用过了,有的小程序还在中间放置了一个搜索框,也是通过这种自定义的方式实现的。接下来我们看看具体的代码是怎么写的。

 

<navigation-bar

ext-class="page-navigator-bar"

active="{{active}}"

loading="{{loading}}">

<view class="left" slot="left">

<icon bindtap="goBack" class="iconfont icon-back">icon>

<icon bindtap="goHome" class="iconfont icon-home">icon>

view>

<view slot="center">

<view>自定义导航标题view>

view>

navigation-bar>

片 7

 

在调用自定义组件的地方,代码很简单,主要定义了两个 slot 插槽的内容。一个是 left 插槽,一个是 center 插槽。

 

在 left 插槽中,我们放置了两个 icon 图标,一个是返回,一个是主页。把这个内容放在每个页面里面,方便我们对按钮进行控制。如果不需要显示主页按钮,例如当前就是主页上,就可以把这个主页按钮隐藏或直接去掉。另外,直接通过插槽的方式,把内容放在调用的地方声明,也方便监听和处理事件,例如 goBack、goHome 这两个 js 函数,我们都可以在外面定义。

 

icon-back 和 icon-hom 是两个图标,关于图标的自定义实现,前面我们讲过了。这两个图标也是基于 iconfont 网站实现的。

 

在 center 插槽中,我们目前仅仅是放置了一个标题,如果需要的话,这里还可以放置广告条,或者搜索框,都是可以的。

 

关于滚动到一定程度,状态自动切换了,这是怎么实现的呢?

 

miniprogram/pages/2.13/index.js:

onPageScroll(res) {

if (res.scrollTop > 400) {

if (!this.data.active) {

this.setData({

active: true

})

}

} else {

if (this.data.active) {

this.setData({

active: false

})

}

}

}

miniprogram/components/navigation-bar/index.wxml:

<view class="{{active ? 'navigator-active' : 'navigator-normal'}} ...>

片 8

 

我们看一下这段代码,onPageScroll 是一个在调用页面里的页面函数,是不需要监听的,当页面滚动的时候,这个函数会自动触发执行。这个很方便。

 

有时候有人觉得小程序是一门很简单的技术,可能就是因为微信团队做的这种很贴心开发者的工作做得太多了,让他们误以为小程序很简单。其实把小程序的体验做得好,又独立赚到钱的并不多。

 

在 onPageScroll 这个函数中,我们查看了页面的 scrollTop 属性,如果大于 400 时,就将控制自定义导航组件状态的 active 变量反转过来(见上面代码)。

 

那么在这里,为什么是 400 呢?

 

这跟我们的页面有关系,在我们的页面中,上方有一块透明显示背景的区域,这块区域的高度就是 400px。

 

active 是自定义组件 navigation-bar 的一个属性,在它的 wxml 代码中,通过这个属性控制了组件在 navigator-active 和 navigator-normal 两个类样式之间切换。通过这种方式实现了导航栏 UI 效果的切换。

 

但是返回按钮和主页按钮,它们是在外面定义的,它们是怎么切换的呢?

 

是通过 ext-class 这个扩展样式属性实现的。设置这个属性,是为了在外面可以控制内部组件的样式,只要自定义组件使用插槽,基本这个机制就是需要的。weui 组件库所有的组件都实现了这种机制。

 

properties: {

'ext-class': {

type: String,

value: ''

},

...

}

<view class="weui-navigation-bar {{ext-class}}" bindtouchstart="doubleClick">

miniprogram/components/navigation-bar/index.json:

{

"styleIsolation": "apply-shared"

}

片 9

 

我们看一下这段代码,实现这种机制首先需要在自定义组件中声明一个 ext-class 属性,并且将这个属性绑定到组件的 wxml 代码上。但做完这一步还不够,我们还需要在自定义组件的 json 配置文件中,开启样式穿透,充许页面上的样式可以影响组件内的样式,开启方法就是在自定义组件的 json 配置文件中,将 styleIsolation 设置为 apply-shared。

 

1,isolated

2,apply-shared 

3,shared

片 10

 

我们看一下这个列表,组件配置页的 styleIsolation 这个配置字段,一共有三个值(见上面列表)。

 

第一个值 isolated,表示启用样式隔离,两者都不会相互影响。

 

第二个值 apply-shared,是我们在自定义组件中选择的值,它表示单向影响,页面的样式可以影响组件,但组件中的样式不能影响页面。

 

第三个值 shared,它表示相互影响,页面的样式既能影响组件,组件中的样式也能影响页面。

 

miniprogram/pages/2.13/index.wxml:

<navigation-bar

ext-class="page-navigator-bar".../>

miniprogram/pages/2.13/index.wxss:

.page-navigator-bar .navigator-normal .icon-back{

color: white;

}

.page-navigator-bar .navigator-active .icon-back{

color: black;

}

片 11

 

我们看一下这段代码,在使用的时候,我们在组件中将 ext-class 属性设置为 page-navigator-bar,这个名称是自定义的,也可以设置为别的名字。然后我们在 wxss 样式文件中,重写.icon-back 样式。由于我们知道组件内部在激活态与常态下不同的类样式名称,所以我们可以根据不现状态分别进行样式的重写。

 

上面就是关于 ext-class 属性实现的机制。接一来我们再看另外一个值得关注问题:样式变量。

 

miniprogram/components/navigation-bar/index.wxss

page {

--height: 44px;

--right: 190rpx;

}

.weui-navigation-bar .android {

--height: 48px;

--right: 222rpx

}

.weui-navigation-bar__inner {

height: var(--height);

padding-right: var(--right);

width: calc(100% - var(--right))

}

片 12

 

我们看一下这个代码,在 wxss 文件中,可以使用两个连字符加一个标识符,作为名称,声明一个样式变量。声明以后,便可以在其它地方,使用样式函数 var 进行使用。

 

page{

--base-size-200: 200px;

--base-size-10: 10rpx;

}

div{

inline-size: calc(var(--base-size-200) + 10px);

inline-size: calc(var(--base-size-200) - var(--base-size-10));

inline-size: calc(var(--base-size-200) * 2);

inline-size: calc(var(--base-size-200) / 2);

}

片 13

 

对于 var 变量,还可以使用 calc 这个样式函数进行四则运算,加减乘除都可以应用。并且 px 与 rpx,还有 100%,都可以放在 clac 函数里一起计算,小程序会自动处理单位之间的差异。

 

现在,请你想一想,我们为什么要使用样式变量呢?

 

attached: function attached() {

wx.getSystemInfo({

success: function success(res) {

var ios = !!(res.system.toLowerCase().search('ios') + 1);

var statusBarHeight=res.statusBarHeight;

var topBarHeight=ios ? (44 + statusBarHeight) : (48 + statusBarHeight);

...

}

})

<view class="weui-navigation-bar__inner {{ios ? 'ios' : 'android'}}" ...>

片 14

 

主要是为了方便实现不同平台之间的兼容,有两个作用。

 

第一,可以控制样式中的同样的数值,在修改的时候,只需要修改变量的值,所有地方都修改了。

 

第二,在我们这个自定义组件中,需要处理 iOS、Android 两种机型。iOS 的导航栏高度是 44px 高度,而 Android 则是 48px 高度。

 

在自定义组件的 js 代码中,有一个 attached 函数,这个函数,在组件被加载进页面结点树之后,会自动执行。在这个函数里面,通过查询系统信息,决定了 ios 变量是否为真(见上面 js 代码),从而决定了在 wxml 代码中使用哪个类样式(见上面 wxml 代码)。

 

(可以从本课视频查看示例效果)

 

好,这节课我们就讲到这里。这节课我们主要讲了页面导航组件 navigator,以及如何自定义实现一个常见的透明的页面导航栏效果。下节课我们学习 image 组件,这是一个非常常用的媒体组件,如果图片过大将会影响小程序页面的加载速度,我们将学习如何实现图片的懒加载机制。

 

2020 年 5 月 29 日