我们在上一章节讲的是消息页开发,重点教大家如何封装组件,然后使用组件,以及父子组件的事件传递,目的是为了让大家对组件的基础知识有更深入的了解,我们在实际开发中,更多的是利用已开发好的组件来提升开发效率,避免重复造轮子,因此,我们既然已经引入了UI框架(uView),那么接下里的页面,我们将更多利用uView的组件,来完成页面开发。
# 一、 好友列表页开发
# 1. 顶部导航栏开发
- 新建好友列表页
pages/friendsList/friendsList.nvue在pages.json中
{
"path" : "pages/friendsList/friendsList",
"style" :
{
"navigationBarTitleText" : "好友列表",
"navigationStyle": "custom"
}
}
- 在页面
pages/friendsList/friendsList.nvue
<template>
<view>
<!-- 导航栏 -->
<chat-navbar title="好友列表" :fixed="true"
:showPlus="false" :showUser="false"
:showBack="true"></chat-navbar>
</view>
</template>
<script>
...
</script>
<style>
/* #ifdef H5 */
@import '/common/css/common.nvue.vue.css';
/* #endif */
</style>
- 优化组件
/components/chat-navbar/chat-navbar.vue导航栏
<template>
<view>
<!-- 导航栏 -->
<view class="bg-light" :class="[fixed ? 'fixed-top' : '']">
<!-- 状态栏 -->
<view :style="'height:' + statusBarHeight + 'px;'"></view>
<!-- 导航 -->
<!-- #ifdef APP || H5 -->
<view class="flex justify-between align-center"
style="height: 90rpx;">
<!-- 左边 -->
<view class="flex align-center">
<!-- 返回箭头 -->
<chat-navbar-icon-button @click="navigateBack" v-if="showBack">
<text class="ml-3 iconfont font-md" ></text>
</chat-navbar-icon-button>
<!-- 标题 -->
...
</view>
<!-- 右边 -->
<view class="flex align-center">
<chat-navbar-icon-button @click="openUser" v-if="showUser">
<text class="iconfont font-lg"></text>
</chat-navbar-icon-button>
<chat-navbar-icon-button @click="openPlus" v-if="showPlus">
<text class="iconfont font-md"></text>
</chat-navbar-icon-button>
</view>
</view>
<!-- #endif -->
<!-- #ifdef MP -->
<view class="flex align-center"
style="height: 90rpx;justify-content: space-between;">
<!-- 左边 -->
<view class="flex align-center flex-1">
<!-- 返回箭头 -->
<chat-navbar-icon-button @click="navigateBack" v-if="showBack">
<text class="ml-3 iconfont font-md" ></text>
</chat-navbar-icon-button>
<chat-navbar-icon-button @click="openPlus" v-if="showPlus">
<text class="iconfont font-md"></text>
</chat-navbar-icon-button>
<chat-navbar-icon-button @click="openUser" v-if="showUser">
<text class="iconfont font-lg"></text>
</chat-navbar-icon-button>
</view>
<!-- 中间 -->
...
<!-- 右边 -->
...
</view>
<!-- #endif -->
</view>
<!-- 占位符:占用 状态栏 + 导航栏的高度 -->
...
<!-- 导航栏点击加号的弹出菜单 -->
...
</view>
</template>
<script>
import toolJS from '@/common/mixins/tool.js';
export default {
name:"chat-navbar",
mixins:[toolJS],
props:{
...,
// 是否显示加号图标
showPlus:{
type:Boolean,
default:true
},
// 是否显示朋友列表图标
showUser:{
type:Boolean,
default:true
},
// 是否显示返回箭头
showBack:{
type:Boolean,
default:false
},
},
...,
methods: {
openUser(){
console.log('点击了通讯录图标');
uni.navigateTo({
url:'/pages/friendsList/friendsList'
})
},
...
},
}
</script>
<style>
...
</style>
- 混入mixins 新建
/common/mixins/tool.js
export default {
methods: {
//页面返回逻辑
// 返回首页逻辑
async redirectToHome() {
try {
// 优先尝试标准跳转
await uni.redirectTo({ url: '/pages/xiaoxi/xiaoxi' })
} catch (e) {
// 处理tab页情况
try {
await uni.switchTab({ url: '/pages/xiaoxi/xiaoxi' })
} catch (e) {
// 终极兜底方案
uni.reLaunch({ url: '/pages/xiaoxi/xiaoxi' })
}
}
},
//页面返回
navigateBack() {
const pages = getCurrentPages()
// 判断是否是分享进入的独立页面
if (pages.length === 1 || pages.length === 0) {
// 尝试多种跳转方式确保可靠性
this.redirectToHome().catch(() => {
uni.showToast({ title: '返回首页失败', icon: 'none' })
})
} else {
uni.navigateBack()
}
},
}
}
# 2. 好友列表开发
- 在UI框架(uView)中,提供了
IndexList 索引列表这个组件:https://uviewui.com/components/indexList.html (opens new window) 帮我们快速开发这个页面。 - 大家可以在uni-app的插件市场:https://ext.dcloud.net.cn/plugin?id=1593 (opens new window)
- 可
使用HBuilderX导入示例项目或者下载示例项目压缩包导入HBuilderX查看示例。- 当前列表样式用到示例项目中的:
pages/componentsC/indexList/indexList.nvue
朋友列表静态页面完整代码: /pages/friendsList/friendsList.nvue
<template>
<view>
<!-- 导航栏 -->
<chat-navbar title="好友列表" :fixed="true"
:showPlus="false" :showUser="false"
:showBack="true"></chat-navbar>
<!-- 好友列表 -->
<u-index-list :indexList="indexList">
<view slot="header" class="list">
<view class="list__item">
<u-avatar shape="square" size="35"
icon="man-add-fill" fontSize="26" randomBgColor></u-avatar>
<text class="list__item__user-name">新的朋友</text>
</view>
<u-line></u-line>
<view class="list__item">
<u-avatar shape="square" size="35"
icon="tags-fill" fontSize="26" randomBgColor></u-avatar>
<text class="list__item__user-name">标签</text>
</view>
<u-line></u-line>
<view class="list__item">
<u-avatar shape="square" size="35"
icon="chrome-circle-fill" fontSize="26" randomBgColor></u-avatar>
<text class="list__item__user-name">朋友圈</text>
</view>
<u-line></u-line>
<view class="list__item">
<u-avatar shape="square" size="35"
icon="qq-fill" fontSize="26" randomBgColor></u-avatar>
<text class="list__item__user-name">QQ</text>
</view>
<u-line></u-line>
</view>
<!-- 列表部分 -->
<template v-for="(item, index) in itemArr">
<!-- #ifdef APP-NVUE -->
<u-index-anchor :text="indexList[index]" :key="index"></u-index-anchor>
<!-- #endif -->
<u-index-item :key="index">
<!-- #ifndef APP-NVUE -->
<u-index-anchor :text="indexList[index]"></u-index-anchor>
<!-- #endif -->
<view class="list" v-for="(item1, index1) in item" :key="index1">
<view class="list__item">
<image class="list__item__avatar" :src="item1.url"></image>
<text class="list__item__user-name">{{item1.name}}</text>
</view>
<u-line></u-line>
</view>
</u-index-item>
</template>
<view slot="footer" class="u-safe-area-inset--bottom">
<text class="list__footer">共305位好友</text>
</view>
</u-index-list>
</view>
</template>
<script>
// 定义列表数据
const indexList = () => {
const indexList = []
const charCodeOfA = 'A'.charCodeAt(0)
indexList.push("↑")
indexList.push("☆")
for (let i = 0; i < 26; i++) {
indexList.push(String.fromCharCode(charCodeOfA + i))
}
console.log('indexList当前数据',indexList);
indexList.push('#')
return indexList
}
export default {
data() {
return {
indexList: indexList(),
urls: [
'https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/avatar-01.png',
'https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/avatar-02.png',
'https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/avatar-03.png',
'https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/avatar-04.png',
'https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/avatar-05.png',
'https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/avatar-06.png',
'https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/avatar-07.png',
'https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/avatar-08.png',
'https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/avatar-09.png',
'https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/avatar-10.png',
],
names: ["晓明哥", "热巴", "GIGI梁咏琪", "古巨基", "古力娜扎", "阿祖",
"力宏哥", "华仔", "黄奕", "刘涛", "林俊杰", "涛涛",
"阿力", "许文强", "周杰伦", "王心凌"
]
}
},
computed: {
itemArr() {
return this.indexList.map(item => {
const arr = []
for (let i = 0; i < 10; i++) {
arr.push({
name: this.names[uni.$u.random(0, this.names.length - 1)],
url: this.urls[uni.$u.random(0, this.urls.length - 1)]
})
}
return arr
})
}
},
methods: {
}
}
</script>
<style>
/* #ifdef H5 */
@import '/common/css/common.nvue.vue.css';
/* #endif */
</style>
<style lang="scss">
.list {
&__item {
@include flex;
padding: 6px 12px;
align-items: center;
&__avatar {
height: 35px;
width: 35px;
border-radius: 3px;
}
&__user-name {
font-size: 16px;
margin-left: 10px;
color: $u-main-color;
}
}
&__footer {
color: $u-tips-color;
font-size: 14px;
text-align: center;
margin: 15px 0;
}
}
</style>
# 二、我的页面开发
- 在
pages.json中
{
"path" : "pages/wode/wode",
"style" :
{
"navigationBarTitleText" : "我的",
"navigationStyle": "custom"
}
},
- 在我的页面
pages/wode/wode.nvue
<template>
<view>
<!-- 头像昵称 -->
<view :style="avatarTopStyle"
class="px-3 pb-5">
<view class="flex align-center justify-between">
<!-- 头像 -->
<view class="ml-1 mr-3">
<u--image
src="https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/avatar-01.png"
mode="widthFix"
width="120rpx" height="120rpx" radius="20rpx"></u--image>
</view>
<!-- 昵称 -->
<view class="flex flex-1 flex-column justify-center">
<text class="font-weight-bold font-lg">小二哥</text>
<view class="flex justify-between mt-2">
<text class="font text-light-muted">账号:xiaoerge001</text>
<text class="font-lg text-light-muted iconfont"></text>
</view>
</view>
</view>
</view>
<!-- 间隔槽 -->
<u-gap height="10" bgColor="#EDEDED"></u-gap>
<!-- Cell 单元格 -->
<u-cell-group>
<u-cell icon="plus-people-fill" title="添加朋友"
:border="false" clickable isLink
:customStyle="customStyles"
:iconStyle="iconStyles"
:titleStyle="titleStyles"></u-cell>
<u-cell icon="chat" title="发起群聊"
:border="false" clickable isLink
:customStyle="customStyles"
:iconStyle="iconStyles"
:titleStyle="titleStyles"></u-cell>
<u-cell icon="scan" title="扫一扫"
:border="false" clickable isLink
:customStyle="customStyles"
:iconStyle="iconStyles"
:titleStyle="titleStyles"></u-cell>
</u-cell-group>
<u-gap height="10" bgColor="#EDEDED"></u-gap>
<u-cell-group>
<u-cell icon="grid" title="我的二维码"
:border="false" clickable isLink
:customStyle="customStyles"
:iconStyle="iconStyles"
:titleStyle="titleStyles"></u-cell>
</u-cell-group>
</view>
</template>
<script>
export default {
data() {
return {
statusBarHeight:0,//状态栏高度动态计算
fixedHeight:0, //占位:状态栏+导航栏
}
},
onLoad() {
this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
this.fixedHeight = this.statusBarHeight + uni.upx2px(90);
},
computed:{
avatarTopStyle(){
return `padding-top:${this.fixedHeight}px;`
},
customStyles(){
return `padding-top:20rpx;padding-bottom:20rpx;`;
},
iconStyles(){
return `font-size:52rpx;margin-right:30rpx;color:#5696DA`;
},
titleStyles(){
return `font-size:32rpx;`;
}
},
methods: {
}
}
</script>
<style>
/* #ifdef H5 */
@import '/common/css/common.nvue.vue.css';
/* #endif */
</style>