从微信小程序到鸿蒙js开发【05】——tabs组件&每日新闻
目录: 1、tabs, tab-bar, tab-content 2、tabs的事件处理 3、tabs实现的每日新闻 1、tabs, tab-bar, tab-content 上章说到,鸿蒙的list组件仅能支持竖向滚动,无法实现横向滚动。如果需要作出可横向滚动的顶部菜单栏,鸿蒙提供了tabs组件。tabs配合两个子元素组件tab-bar和tab-content,即可很轻松地实现顶部菜单+内容切换效果。 tab-bar的子元素为text,tab-content的子元素为div。 hml: <div class="container"> <tabs class="tabs"> <tab-bar> <block for="{{ tabBar }}"> <text> {{ $item.name }} </text> </block> </tab-bar> <tab-content> <block for="{{ tabBar }}"> <div style="background-color: {{ $item.color }}; height: 500px;"> <text style="font-size: 50px;"> {{ $idx }} </text> </div> </block> </tab-content> </tabs> </div> css: .container { width: 100%; height: 1200px; display: flex; flex-direction: column; } .tabs{ width: 100%; height: 100%; } js: export default { data: { tabBar: [{name: '推荐', color: '#1296db'}, {name: '最新', color: '#e20a0b'}, {name: '最热', color: '#cdcdcd'}] } } 由效果可看出,tab-bar组件是顶部的菜单栏,自带了动态样式。tab-content组件是下方的内容部分,会根据点击的菜单切换到对应的内容部分。tab-bar和tab-content是根据索引值一一对应的。这里还发现,哪怕tab-content给了height: 500px的样式,还是会占满整个tabs的高度。 tabs的属性index用于指定默认选中的菜单索引项,vertical指定是否为竖向菜单栏。这里设置为竖向后可以看出,tab-bar变为占满一列,tab-content的height样式起作用,宽度则占满tabs。 <tabs class="tabs" index="1" vertical="true"> 多放几个菜单项,并设置tab-bar的属性mode="fixed",则菜单项无法滑动,均布占满整行。 <tabs class="tabs" index="0" vertical="false"> <tab-bar mode="fixed"> mode="scrollable",就有横向滚动效果了,且点击菜单项后整个菜单栏会有适应移动效果。 <tab-bar mode="scrollable"> tab-content属性scrollable-"true",菜单对应内容就可以竖向滚动了,和list效果类似。 <tab-content scrollable="true"> 2、tabs的事件处理 如想捕获菜单项变化的事件并进行处理,需在tabs标签中通过onchange进行绑定。在传入的事件对象中,index则为选中菜单项的索引值。这里使用prompt模块的showToast()进行调试。 <tabs class="tabs" index="0" vertical="false" onchange="changeTab"> import prompt from '@system.prompt'; export default { data: { tabBar: [ ... ] }, changeTab(event) { prompt.showToast({ message: '你点击了第' + event.index + '项。' }) } } 这个onchange事件捕获的条件比较苛刻,注意: tabs tab-bar text tab-content div 以上组件都必须存在,且tab-bar中text的数量和tab-content中div的数量需一致。 或者也可以在text上通过onclick绑定事件,就没有以上的严苛触发条件。 <div class="container"> <tabs class="tabs" index="0" vertical="false"> <tab-bar mode="scrollable"> <block for="{{ tabBar }}"> <text onclick="clickTab($idx)"> {{ $item.name }} </text> </block> </tab-bar> ...... import prompt from '@system.prompt'; export default { data: { tabBar: [......] }, clickTab(idx) { prompt.showToast({ message: '你点击了第' + idx + '项。' }) } } 当然,弊端也很明显。tab-bar文字下的蓝色线条并没有跟随移动,tab-content也没有随之改变,只是事件可以捕获到。这种用法适用于只希望保留tab-bar的部分,自定义动态样式,可以省略tab-content以及其中的div。哪一种方式更好,还得看需求。 3、tabs实现的每日新闻 这里运用了整套tabs组件,从聚合数据新闻头条接口(https://www.juhe.cn/docs/api/id/235)请求数据,实现了一个简单的每日新闻模块。因为鸿蒙的页面布局如果高度超过手机总高度就会有滑动效果,tab-bar和自定义的底部菜单都是固定的,因此也用不着list组件了。代码如下: hml: <!-- 每日新闻 --> <div> <tabs class="newsTabs" onchange="changeNewsType"> <tab-bar> <block for="{{ newsTitles }}"> <text> <span>{{ $item.name }}</span> </text> </block> </tab-bar> <tab-content> <block for="{{ newsTitles }}"> <div class="newsView"> <block for="{{ newsList }}"> <div class="newsItem"> <image src="{{ $item.thumbnail_pic_s }}" class="newsImg"></image> <div class="newsContent"> <text> {{ $item.title }} </text> <div class="newsDesc"> <text> {{ $item.author_name }} </text> <text> {{ $item.date }} </text> </div> </div> </div> </block> </div> </block> </tab-content> </tabs> </div> <!-- 每日新闻end --> css: /*每日新闻*/ .newsTabs { width: 100%; height: 100%; } .newsView { width: 100%; height: 100%; display: flex; flex-direction: column; } .newsItem { width: 100%; height: 240px; border-bottom: 1px solid #bbbbbb; display: flex; align-items: center; } .newsImg { margin-left: 20px; width: 200px; height: 200px; } .newsContent { display: flex; flex-direction: column; margin-right: 20px; margin-left: 20px; } .newsContent>text { margin-top: 20px; height: 140px; font-size: 34px; color: #333333; } .newsDesc { height: 60px; line-height: 60px; display: flex; justify-content: space-between; } .newsDesc>text { font-size: 28px; color: #777777; } js: data: { newsTitles: [ { name: '头条', value: 'top' }, { name: '社会', value: 'shehui' }, { name: '国内', value: 'guonei' }, { name: '国际', value: 'guoji' }, { name: '娱乐', value: 'yule' }, { name: '体育', value: 'tiyu' }, { name: '军事', value: 'junshi' }, { name: '科技', value: 'keji' }, { name: '财经', value: 'caijing' }, { name: '时尚', value: 'shishang' } ], newsList: [], }, changeNewsType(event) { let type = this.newsTitles[event.index].value; fetch.fetch({ url: 'http://v.juhe.cn/toutiao/index?key=xxxxx&type=' + type, responseType: 'json', success: res => { let data = JSON.parse(res.data); this.newsList = data.result.data; } }) }, 作者:Chris. 想了解更多内容,请访问: 51CTO和华为官方战略合作共建的鸿蒙技术社区https://harmonyos.51cto.com