使用uniapp开发社区交友网站的项目教程
uniapp社区交友开发前端模块开发
源码可以提供下载,详情访问末尾码云地址
环境搭建和创建项目
开发环境搭建
- 使用HubilderX
- 安装对应插件
创建uniapp项目
- 创建项目(名称:社区交友)
- 真机调试或微信开发者工具调试
App.vue引入全局公共样式
引入官方css样式库
新建模板项目hello uniapp
复制模板common下的css
在本项目的app.vue进行引入css文件 @import “./common/uni.css ” (还要引入uni.tff文件,否则报错)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xizHMjdI-1649380676444)(uniapp社区交友开发.assets/image-20220322164136184-16479384973031.png)]
引入自定义图标
阿里巴巴矢量图标库 https://www.iconfont.cn/
下载所选图标至项目打包 得到压缩文件
修改icon.css文件去掉url,引入文件 测试图标使用
<view><text class="iconfont icon-smile" style="font-size: 100rpx; color: red;"></text> </view>
引入css动画库
下载animate.css
引入animate.css
测试css动画库的使用
<view style="display: flex;justify-content: center;padding: 50rpx;"> <view class="" hover-class=" animated rubberBand" style="border: 1rpx solid black; padding: 20rpx;">点击效果</view></view>
设置全局属性globalStyle
解析page.json文件 看官方文档
设置导航栏的样式
"globalStyle": {"navigationBarTextStyle": "black", //导航栏字体颜色"navigationBarTitleText": "社区交友",//导航栏文字"navigationBarBackgroundColor": "#FFF",//背景颜色"backgroundColor": "#FFF"}
底部导航开发
设置图标(图片为png,81*81)用矢量图标库下载
配置tabBar前提要配置pages数组页面
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages{"path": "pages/index/index","style": {}},{"path" : "pages/news/news","style" : {"navigationBarTitleText": "","enablePullDownRefresh": false}},{"path" : "pages/msg/msg","style" : {"navigationBarTitleText": "","enablePullDownRefresh": false}},{"path" : "pages/my/my","style" : {"navigationBarTitleText": "","enablePullDownRefresh": false}}],"tabBar": {"color": "#323232","selectedColor": "#FC5C82","backgroundColor": "#FFF","borderStyle": "black","list": [{"pagePath": "pages/index/index","text": "首页","iconPath": "static/tabbar/index.png","selectedIconPath": "static/tabbar/indexed.png"},{"pagePath": "pages/news/news","text": "动态","iconPath": "static/tabbar/news.png","selectedIconPath": "static/tabbar/newsed.png"},{"pagePath": "pages/msg/msg","text": "消息","iconPath": "static/tabbar/paper.png","selectedIconPath": "static/tabbar/papered.png"},{"pagePath": "pages/my/my","text": "我的","iconPath": "static/tabbar/home.png","selectedIconPath": "static/tabbar/homeed.png"}]}
uni-app和vuejs基础快速上手
view和text组件和动画的使用
- hover-class的测试使用
- text的测试使用
- 两个内置组件的使用可参考官方文档
uniapp的css3选择器
普通的选择器 id就用#,class就用.,什么都不加默认全部
父级下的子级菜单的选择器
.box>view:first-of-type{background-color: red; } .box>view:last-of-type{background-color: pink; } .box>view:nth-child(2){background-color: yellow; }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SvOmDgZ5-1649380676446)(uniapp社区交友开发.assets/image-20220323110150462-16480045116861.png)]
奇偶选择器
//奇数选择器 .box>view:nth-of-type(odd){background-color: red; } //偶数选择器 .box>view:nth-of-type(even){background-color: green; } //偶数选择器 .box:nth-of-type(even){background-color: green; }
flex布局快速入手
- display:flex 外层使用,块内元素挤在一行内
- justify-content:常用center,水平居中
- align-items:常用center,垂直居中
- felx-direction:改变排序方式,从行转换成列
- felx-shirink:0 不被压缩
- flex:1占一份 2占两份
数据渲染
- {{}}获取data中的数据渲染
- @tap触发点击事件
class和style的绑定
- 绑定class用冒号:class
- :class={‘class1’:isActive}
- s:tyle=" {‘color’: Color,‘font-size’:num+‘px’}"
条件渲染
- v-if的使用
- v-show是会渲染只是不显示
- 一般在template里面用v-if
列表渲染
- v-for
- 官方文档建议v-for写在
事件处理器
- @tap点击事件
- @tap.stop点里面不会触发外面的事件
监听属性
watch
测试
<template><view><view>{{num}}</view><button @tap="changNum()">按钮</button></view> </template><script>export default {data() {return {num:0}},watch:{num(val){console.log(val);}},methods: {changNum(){this.num++;}}} </script><style> button{background: blue;display: flex;justify-content: center;align-items: center;font-size: 15px;color: white; } </style>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gyz1MrF9-1649380676447)(uniapp社区交友开发.assets/image-20220323154220758-16480213421241.png)]
计算属性
常用于数据的格式化
computed
测试运用
<template><view>{{formatWeight}}</view> </template><script>export default {data() {return {weight:2100}},computed:{formatWeight(){return (this.weight>1000)?this.weight/1000+'kg':this.weight+'g';}}} </script><style></style>
首页开发
page.json配置
导航栏配置根据官方文档配置
{"path": "pages/index/index","style": {"app-plus": {// 导航栏配置"titleNView":{// 搜索框配置"searchInput":{"align":"center","backgroundColor":"#F5F4F2","borderRadius":"4px","disabled":true,"placeholder":"搜索帖子","placeholderColor":"#6D6C67"},"buttons":[{"color":"#333333","colorPressed":"#FD597C","float":"right","fontSize":"20px","fontSrc":"/static/iconfont.ttf","text":"\ue668"}]}}}}
用真机调试成功,微信开发者工具旁边无显示
图文列表样式
封装free.css把常用样式封装 如==flex:display;justify-content:center;algin-items:center、
引入自定义css库
列表开发
<view style="padding: 20rpx;"><view class="flex;justify-between;align-center"><!-- 头像,昵称 --><view class="flex;align-center"><!-- 头像 --><image src="/static/common//nothing.png" class="mr-1; rounded" style="width:65rpx;height:65rpx"></image><view><view style="font-size: 30rpx;">昵称</view><view style="color: #9d9589;font-size: 20rpx;">2022-3-15</view></view></view ><!-- 按钮 --><view class="flex;align-center; justify-center" style="background: #FF4A6A; width:90rpx; height:50rpx;color: white;" >关注</view></view><!-- 文章内容 --><view>哈哈哈</view><!-- 图片 --><view class="mt-1" ><image src="/static/demo/datapic/45.jpg" style="width: 100%; height: 350rpx;" lazy-load="true"></image></view><!-- 按钮 --><view class="flex" ><view class="flex;align-center; justify-center flex-1"><view class="iconfont icon-dianzan2 "></view><view>赞</view></view><view class="flex;align-center; justify-center flex-1"><view class="iconfont icon-cai; mr-2" ></view><view>踩</view></view><view class="flex;align-center; justify-center flex-1"><view class="iconfont icon-pinglun2; mr-2" ></view><view>评论</view></view><view class="flex;align-center; justify-center flex-1"><view class="iconfont icon-zhuanfa1; mr-2" ></view><view>转发</view></view></view></view>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-daoAQo1N-1649380676447)(uniapp社区交友开发.assets/image-20220323193232107.png)]
封装列表样式
继续使用free.css封装代码
<view><view class="p-2"><view class="flex;justify-between;align-center"><!-- 头像,昵称 --><view class="flex;align-center"><!-- 头像 --><image src="/static/common//nothing.png" class="mr-1; rounded-circle" style="width:65rpx;height:65rpx"></image><view><view class="font" style="line-height: 1.5;">昵称</view><view style=" ine-height: 1.5;" class="font-small; text-light-muted">2022-3-15</view></view></view ><!-- 按钮 --><view class="flex;align-center; justify-center; rounded; text-white; bg-main" style=" width:90rpx; height:50rpx;" >关注</view></view><!-- 文章内容 --><view class="font-md; my-1">我是标题</view><!-- 图片 --><view class="mt-1" ><image src="/static/demo/datapic/45.jpg" class="rounded" style="width: 100%; height: 350rpx;" lazy-load="true"></image></view><!-- 按钮 --><view class="flex" ><view class="flex;align-center; justify-center flex-1"><view class="iconfont icon-dianzan2 "></view><view>赞</view></view><view class="flex;align-center; justify-center flex-1"><view class="iconfont icon-cai; mr-2" ></view><view>踩</view></view><view class="flex;align-center; justify-center flex-1"><view class="iconfont icon-pinglun2; mr-2" ></view><view>评论</view></view><view class="flex;align-center; justify-center flex-1"><view class="iconfont icon-zhuanfa1; mr-2" ></view><view>转发</view></view></view></view></view>
封装本项目公共css(common.css 记得引入)
.bg-main{background: #FF4A6A; }
封装成组件动态渲染
<block v-for="(item,index) in list" :key="index"><commonList :item="item" :index="index" ></commonList></block>import commonList from '@/components/common/common-list';components:{commonList},<view class="p-2"><view class="flex;justify-between;align-center"><!-- 头像,昵称 --><view class="flex;align-center"><!-- 头像 --><image :src="item.userPic" class="mr-1; rounded-circle" style="width:65rpx;height:65rpx"></image><view><view class="font" style="line-height: 1.5;">{{item.username}}</view><view style=" ine-height: 1.5;" class="font-small; text-light-muted">{{item.newstime}}</view></view></view ><!-- 按钮 --><view class="flex;align-center; justify-center; rounded; text-white; bg-main" style=" width:90rpx; height:50rpx;" >关注</view></view><!-- 文章内容 --><view class="font-md; my-1">{{item.title}}</view><!-- 图片 --><view class="mt-1" ><image :src="item.titlePic" class="rounded" style="width: 100%; height: 350rpx;" lazy-load="true"></image></view><!-- 按钮 --><view class="flex" ><view class="flex;align-center; justify-center flex-1"><view class="iconfont icon-dianzan2; mr-2"></view><view>{{item.support.support_count}}</view></view><view class="flex;align-center; justify-center flex-1"><view class="iconfont icon-cai; mr-2" ></view><view>{{item.support.unsupport_count}}</view></view><view class="flex;align-center; justify-center flex-1"><view class="iconfont icon-pinglun2; mr-2" ></view><view>{{item.comment_count}}</view></view><view class="flex;align-center; justify-center flex-1"><view class="iconfont icon-zhuanfa1; mr-2" ></view><view>{{item.share_num}}</view></view></view></view>export default{props:{item:Object,key:Number}}
全局分割线开发
封装组件divider.vue
<!-- 分割线样式 --><view style="height: 15rpx; background-color: #F5F5F4;"></view>
引入全局组件(分割线常用)
import divider from '@/components/common/divider.vue'; Vue.component('divider',divider);<block v-for="(item,index) in list" :key="index"><commonList :item="item" :index="index"></commonList><divider></divider> </block>
优化列表组件-动画特效
- 图片显示优化
- 关注、图标的点击动画特效(jello)
- 图标主色调变化 加字体颜色
- 为各元素添加click事件 (头像、关注、标题、图片、点赞、踩)
<template><view><view class="p-2"><view class="flex;justify-between;align-center"><!-- 头像,昵称 --><view class="flex;align-center"><!-- 头像 --><image :src="item.userPic" class="mr-1; rounded-circle" style="width:65rpx;height:65rpx" @click="openSapce()"></image><view><view class="font" style="line-height: 1.5;">{{item.username}}</view><view style=" ine-height: 1.5;" class="font-small; text-light-muted">{{item.newstime}}</view></view></view><!-- 按钮 --><view class="flex;align-center; justify-center; rounded; text-white; bg-main; animated faster "style=" width:90rpx; height:50rpx;" hover-class="rubberBand" @click="follow()">关注</view></view><!-- 文章内容 --><view class="font-md; my-1" @click="openDetail()" >{{item.title}}</view><!-- 图片 --><view class="mt-1" v-if="item.titlePic" @click="openDetail()"><image :src="item.titlePic" class="rounded" style="width: 100%; height: 350rpx;" lazy-load="true"></image></view><!-- 按钮 --><view class="flex"><view class="flex;align-center; justify-center flex-1 animated faster" hover-class="jello text-main" @click="doSupport('support')"><view class="iconfont icon-dianzan2; mr-2;"></view><view>{{item.support.support_count}}</view></view><view class="flex;align-center; justify-center flex-1 animated faster" hover-class="jello text-main" @click="doSupport('unsupport')"><view class="iconfont icon-cai; mr-2 "></view><view>{{item.support.unsupport_count}}</view></view><view class="flex;align-center; justify-center flex-1 animated faster" hover-class="jello text-main" @click="openDetail()"><view class="iconfont icon-pinglun2; mr-2"></view><view>{{item.comment_count}}</view></view><view class="flex;align-center; justify-center flex-1 animated faster" hover-class="jello text-main" @click="openDetail()"><view class="iconfont icon-zhuanfa1; mr-2"></view><view>{{item.share_num}}</view></view></view></view></view>
</template><script>export default {props: {item: Object,index: Number},methods:{openSapce(){console.log("打开个人空间");},follow(){console.log("关注");},openDetail(){console.log("打开详情页");},doSupport(type){console.log(type);}}}
</script><style>
</style>
优化列表组件-关注功能
- 关注按钮的显示
- 子组件触发父组件方法更新isFollowz
<view class="flex;align-center; justify-center; rounded; text-white; bg-main; animated faster "style=" width:90rpx; height:50rpx;" hover-class="rubberBand" @click="follow()" v-if="!item.isFollow">关注</view>follow(){// 触发父级follow方法this.$emit('follow',this.index);},<commonList :item="item" :index="index" @follow="follow(index)"></commonList>methods: {follow(index){this.list[index].isFollow=true;uni.showToast({title:'关注成功'})}}
优化列表组件-顶踩功能
- 绑定class渲染
- 方法参数传递
- 父方法实现
<view class="flex;align-center; justify-center flex-1 animated faster" hover-class="jello text-main" @click="doSupport('support')":class="item.support.type==='support'?'support-active':''"><view class="iconfont icon-dianzan2; mr-2;"></view><view>{{item.support.support_count>0?item.support.support_count:'支持'}}</view></view>doSupport(type){this.$emit('doSupport',{type:type,index:this.index})}<commonList :item="item" :index="index" @follow="follow" @doSupport="doSupport"></commonList>doSupport(e) {let obj=this.newList[this.tabIndex].list[e.index]console.log(obj);if (obj.support.type === '') {//无操作obj.support[e.type + '_count']++;} else if (obj.support.type === 'support' && e.type === 'unsupport') {//之前是顶,顶减一,踩加一obj.support.support_count--;obj.support.unsupport_count++;} else if (obj.support.type === 'unsupport' && e.type === 'support') {//之前是踩,顶加一,踩减一obj.support.support_count++;obj.support.unsupport_count--;}obj.support.type = e.type;let msg = e.type === 'support' ? '顶' : '踩';uni.showToast({title: msg + '成功'})},
滚动tab导航开发
顶部导航选项卡
<scroll-view class="scroll-row border-bottom" scroll-x="true" :scroll-into-view="scrollInto" scroll-with-animation="true"><view v-for="(item,index) in tabBars" :key="index" class="scroll-row-item px-3 py-2 font-md " :id="'tab'+index":class="tabIndex===index?'text-main font-lg font-weight-bold':''" @click="doTab(index)">{{item.name}}</view></scroll-view>tabIndex:0,scrollInto:'',tabBars:[{name:'首页'},{name:'体育'},{name:'军事'},{name:'热点'},{name:'新闻'},{name:'娱乐'},{name:'电竞'},{name:'国际'},{name:'国家'}],doTab(index){this.tabIndex=index;this.scrollInto='tab'+index;}
下面容器能做到切换与导航栏一样,容器也能拉取
<swiper duration=150 @change="onChange" :current="tabIndex" :style="'height:'+scrollH+'px'"><swiper-item v-for="(item,index) in tabBars" :key="index" ><scroll-view scroll-y="true" :style="'height:'+scrollH+'px'"><view v-for="i in 100">{{i}}</view></scroll-view></swiper-item></swiper>doTab(index){this.tabIndex=index;this.scrollInto='tab'+index;},onChange(e){this.doTab(e.detail.current);}onLoad() {const res = uni.getSystemInfoSync();this.scrollH=res.windowHeight-uni.upx2px(101);console.log(this.scrollH);},
列表显示
<swiper duration=150 @change="onChange" :current="tabIndex" :style="'height:'+scrollH+'px'"><swiper-item v-for="(item,index) in newList" :key="index" ><scroll-view scroll-y="true" :style="'height:'+scrollH+'px'"><block v-for="(item2,index2) in item.list" :key="index"><commonList :item="item2" :index="index2" @follow="follow()" @doSupport="doSupport()"></commonList><divider></divider></block></scroll-view></swiper-item></swiper>getData(){let arr=[];for (var i = 0; i < this.tabBars.length; i++) {arr.push({list: [{userPic: '/static/common//nothing.png',username: '',newstime: '',isFollow: false,title: '我是标题',titlePic: '/static/demo/datapic/45.jpg',support: {type: 'support',support_count: 1,unsupport_count: 2},comment_count: 1,share_num: 0},{userPic: '/static/common//nothing.png',username: '',newstime: '',isFollow: false,title: '我是标题',titlePic: '',support: {type: 'unsupport',support_count: 2,unsupport_count: 2},comment_count: 1,share_num: 1},{userPic: '/static/common//nothing.png',username: '',newstime: '',isFollow: false,title: '我是标题',titlePic: '',support: {type: '',support_count: 2,unsupport_count: 2},comment_count: 1,share_num: 1}]})};this.newList=arr;},
上拉加载组件开发
静态的开发
<scroll-view scroll-y="true" :style="'height:'+scrollH+'px'" @scrolltolower="loadMore(index)"><block v-for="(item2,index2) in item.list" :key="index"><commonList :item="item2" :index="index2" @follow="follow()" @doSupport="doSupport()"></commonList><divider></divider></block><view class="py-2 flex justify-center align-center"><view class="text-light-muted">{{item.loading}}</view></view></scroll-view>
触底函数的开发
loadMore(index){let item=this.newList[index];item.loading='加载中.';setTimeout(()=>{//复制文本item.list=[...item.list,...item.list];},2000)}
封装上拉加载组件
优化加载判断
loadMore(index){let item=this.newList[index];if(!item==='上拉加载更多'){return;}item.loading='加载中...';setTimeout(()=>{item.list=[...item.list,...item.list];item.loading='上拉加载更多';},10000)}
封装load-more.vue 并引入
<template><view class="py-2 flex justify-center align-center"><view class="text-light-muted">{{loading}}</view></view> </template><script>export default{props:{loading:String}} </script>import loadMore from '@/components/common/load-more';export default {components: {commonList,loadMore}, }
封装无数据默认组件
无数据环境测试
const demo=[{userPic: '/static/common//nothing.png',username: '',newstime: '',isFollow: false,title: '我是标题',titlePic: '/static/demo/datapic/45.jpg',support: {type: 'support',support_count: 1,unsupport_count: 2},comment_count: 1,share_num: 0},{userPic: '/static/common//nothing.png',username: '',newstime: '',isFollow: false,title: '我是标题',titlePic: '/static/demo/datapic/45.jpg',support: {type: 'unsupport',support_count: 2,unsupport_count: 2},comment_count: 1,share_num: 1},{userPic: '/static/common//nothing.png',username: '',newstime: '',isFollow: false,title: '我是标题',titlePic: '',support: {type: '',support_count: 2,unsupport_count: 2},comment_count: 1,share_num: 1}]getData() {let arr = [];for (var i = 0; i < this.tabBars.length; i++) {let obj = {loading:'上拉加载更多',list: []}if(i<2){obj.list=demo;}arr.push(obj)};this.newList = arr;},
封装nothing.vue组件 全局引入
<template v-if="item.list.length>0"><scroll-view scroll-y="true" :style="'height:'+scrollH+'px'" @scrolltolower="loadMore(index)"><block v-for="(item2,index2) in item.list" :key="index"><commonList :item="item2" :index="index2" @follow="follow()" @doSupport="doSupport()"></commonList><divider></divider></block><loadMore :loading="item.loading"></loadMore></scroll-view></template><template v-else><no-thing></no-thing></template>import noThing from '@/components/common/no-thing.vue'; Vue.component('no-thing',noThing);
搜索页开发
创建页面search,配置pages.json
{"path": "pages/index/index","style": {"app-plus": {// 导航栏配置"titleNView":{// 搜索框配置"searchInput":{"align":"center","backgroundColor":"#F5F4F2","borderRadius":"4px","disabled":true,"placeholder":"搜索帖子","placeholderColor":"#6D6C67"},"buttons":[{"color":"#333333","colorPressed":"#FD597C","float":"right","fontSize":"20px","fontSrc":"/static/iconfont.ttf","text":"\ue668"}]}}}},{"path" : "pages/news/news","style" : {"navigationBarTitleText": "","enablePullDownRefresh": false}},{"path" : "pages/msg/msg","style" : {"navigationBarTitleText": "","enablePullDownRefresh": false}},{"path" : "pages/my/my","style" : {"navigationBarTitleText": "","enablePullDownRefresh": false}},{"path" : "pages/search/search","style": {"app-plus": {// 导航栏配置"titleNView":{// 搜索框配置"searchInput":{"align":"center","backgroundColor":"#F5F4F2","borderRadius":"4px","placeholder":"搜索帖子","placeholderColor":"#6D6C67"},"buttons":[{"color":"#333333","colorPressed":"#FD597C","float":"right","fontSize":"14px","text":"搜索"}]}}}}
监听点击导航栏搜索框事件, 实现跳转,用官方api
onNavigationBarSearchInputClicked() {uni.navigateTo({url: '../search/search'})},
搜索历史开发
<view><view class="py-2 font-md px-2">搜索历史</view><view class="flex flex-wrap"><view class="border rounded font mx-2 my-1 px-2 " v-for="(item,index) in list" :key="index"hover-class="bg-light">{{item}}</view></view></view>
监听导航输入
onNavigationBarSearchInputChanged(e) {this.searchText=e.text;}
监听导航搜索按钮
onNavigationBarButtonTap(e) {if(e.index===0){this.searchEvent();}},
搜索事件, 收起键盘,处于loading状态, 展示搜索结果,隐藏loading提示框
searchEvent(){uni.hideKeyboard();uni.showLoading({title:'加载中'})setTimeout(()=>{this.serachList=demo;uni.hideLoading();},3000)}
搜索结果列表 引入commonlist,遍历,优化搜索历史与列表存在问题
<view><template v-if="this.serachList.length===0"><view class="py-2 font-md px-2">搜索历史</view><view class="flex flex-wrap"><view class="border rounded font mx-2 my-1 px-2 " v-for="(item,index) in list" :key="index"hover-class="bg-light">{{item}}</view></view></template><template v-else><block v-for="(item,index) in serachList" :key="index" ><commonList :item="item" :index="index"></commonList></block></template></view>import commonList from '@/components/common/common-list.vue';export default {components:{commonList}, }
点击搜索历史的事件
<view class="flex flex-wrap"><view class="border rounded font mx-2 my-1 px-2 " v-for="(item,index) in list" :key="index"hover-class="bg-light" @click="historyEvent(item)">{{item}}</view></view>historyEvent(item){console.log(item);this.searchText=item;this.searchEvent();}
发布表单页面开发
自定义导航栏开发
新建发布页面add-input,取消原生导航
{"path" : "pages/add-input/add-input","style" : {"app-plus": {"titleNView": false}}}
首页导航按钮跳转页面
onNavigationBarButtonTap() {uni.navigateTo({url:'../add-input/add-input'})},
自定义导航栏,添加uni-nav-bar依赖, 根据官方文档调用
<uni-nav-bar left-icon="back" statusBar><view class="flex justify-center align-center w-100">所有人可见<text class="iconfont icon-shezhi ml-1"></text></view></uni-nav-bar>
textarea组件使用
utextarea, 动态绑定
<textarea v-model="content" placeholder="说一句话吧~" class="px-2 uni-textarea" />
底部操作条组件开发
<view style="height: 85rpx" class="fixed-bottom bg-white flex align-center"><view class="iconfont icon-caidan footer-btn"></view><view class="iconfont icon-huati footer-btn"></view><view class="iconfont icon-tupian footer-btn"></view><view class="bg-main text-white justify-center align-center ml-auto flex mr-2" style="width: 140rpx; height: 60rpx;">发送</view></view><style>
.footer-btn{width: 86rpx;height: 86rpx;justify-content: center;display: flex;align-items: center;font-size: 50rpx;
}
</style>
上传多图功能开发
upload-image组件开发, 引官方组件,对应引入也需要引入
对官方组件的修改 添加mode压缩,修改内边距, 修改圆角
<view class="px-2"><view class="uni-uploader"><view class="uni-uploader-head"><view class="uni-uploader-title">点击可预览选好的图片</view><view class="uni-uploader-info">{{imageList.length}}/9</view></view><view class="uni-uploader-body"><view class="uni-uploader__files"><block v-for="(image,index) in imageList" :key="index"><view class="uni-uploader__file"><image class="uni-uploader__img rounded" :src="data:image" :data-src="data:image"@tap="previewImage" mode="aspectFill"></image></view></block><view class="uni-uploader__input-box"><view class="uni-uploader__input rounded" @tap="chooseImage"></view></view></view></view></view></view>
上传图片成功的内容保存 上传图片的回调success方法中
success: (res) => {this.imageList = this.imageList.concat(res.tempFilePaths);this.$emit('choose',this.imageList);},<uploadImage @choose="choose"></uploadImage>choose(e){console.log(e);this.imageList=e;}
删除选中图片功能实现
静态图标的实现
<block v-for="(image,index) in imageList" :key="index"><view class="uni-uploader__file position-relative"><image class="uni-uploader__img rounded" :src="data:image" :data-src="data:image"@tap="previewImage" mode="aspectFill"></image><view class="bg-dark position-absolute top-0 right-0 rounded"style="padding: 0 15rpx; background-color: rgba(0, 0, 0, 0.5);"><text class="iconfont icon-shanchu text-white"></text></view></view></block>
添加删除功能的函数, 通知父组件, 优化父组件方法, 给予交互反馈提示
<text class="iconfont icon-shanchu text-white" @click="deleteImage(index)"></text>deleteImage(index){uni.showModal({title:'提示',content:'是否要删除该图片',confirmText:'删除',cancelText:'不删除',success: (res) => {if(res.confirm){this.imageList.splice(index,1);this.$emit('change',this.imageList);}}})},
保存草稿功能开发
添加返回首页方法
<uni-nav-bar left-icon="back" statusBar @clickLeft="goBack"><view class="flex justify-center align-center w-100 font-weight-bold">所有人可见<text class="iconfont icon-shezhi ml-1"></text></view></uni-nav-bar>goBack(){uni.navigateBack({delta:1})},
监听返回, 交互提示反馈 return true即能返回
onBackPress() {if((this.content!==''||this.imageList.length>0)&&!this.showBack){uni.showModal({content: '是否保存为草稿',showCancel: true,cancelText: '不保存',confirmText: '保存',success: res => {if(res.confirm){console.log('保存');}//手动执行返回// goBack(){// uni.navigateBack({// delta:1// })// },this.goBack();}});this.showBack=true;return true;}},
保存的方法
store(){let obj={content:this.content,imageList:this.imageList};uni.setStorage({key:'add-input',data:JSON.stringify(obj)})}
取出的方法 用同步取出
onLoad() {var res=uni.getStorageSync('add-input');if(res){var obj=JSON.parse(res);// console.log(result);this.content=obj.content;this.imageList=obj.imageList;}},
优化图片的草稿功能, 上传图片的组件imageList要用props传值
<uploadImage :list="imageList" @change="change"></uploadImage>//组件里面props: {list: Array},created(){this.imageList=this.list;},
不保存草稿功能的实现, 清楚缓存
onBackPress() {if((this.content!==''||this.imageList.length>0)&&!this.showBack){uni.showModal({content: '是否保存为草稿',showCancel: true,cancelText: '不保存',confirmText: '保存',success: res => {if(res.confirm){// console.log('保存');this.store();}else{uni.removeStorageSync('add-input');}//手动执行返回this.goBack();}});this.showBack=true;return true;}},
下面图标插入图片的方法(优化不需要上传图片时隐藏上传图片组件)
<view class="iconfont icon-tupian footer-btn" @click="iconClickEvent('uploadImage')"></view><uploadImage ref="uploadImage" :show="show" :list="imageList" @change="change"></uploadImage>iconClickEvent(e){switch (e){case 'uploadImage': this.$refs.uploadImage.chooseImage();break;}}computed:{show(){return this.imageList.length>0;}},在子组件中加入v-if=“show”
动态列表页开发
导航栏tab导航开发
自定义导航栏的静态开发
<uni-nav-bar statusBar="true" border="false" ><view class="flex align-center justify-center font-weight-bold w-100"><view class="font-lg text-main mx-1">关注</view><view class="font-md text-light-muted mx-1">话题</view></view><view slot="right" class="iconfont icon-fatie_icon"></view></uni-nav-bar>
取消原生导航栏
{"path": "pages/news/news","style": {"app-plus": {"titleNView": false}}},
导航栏右边图标的单击事件
<uni-nav-bar statusBar="true" border="false" @clickRight="openAddInput"><view class="flex align-center justify-center font-weight-bold w-100"><view class="font-lg text-main mx-1">关注</view><view class="font-md text-light-muted mx-1">话题</view></view><view slot="right" class="iconfont icon-fatie_icon"></view></uni-nav-bar>openAddInput(){uni.navigateTo({url: '../add-input/add-input'})}
tabBar的动态循环渲染
<uni-nav-bar statusBar="true" border="false" @clickRight="openAddInput"><view class="flex align-center justify-center font-weight-bold w-100 font-md text-light-muted"><view v-for="(item,index) in tabBars" :key="index":class="tabIndex===index? 'text-main font-lg':''"@click="changeTab(index)" class="mx-1">{{item.name}}</view></view><view slot="right" class="iconfont icon-fatie_icon"></view></uni-nav-bar>data() {return {tabIndex:0,tabBars:[{name:'关注'},{name:'话题'}]}},changeTab(index){this.tabIndex=index;}
关注列表页开发
滑动滚动区域计算
引入首页的swipper和scrollview组件, 对应修改即可
<swiper duration=150 @change="onChange" :current="tabIndex" :style="'height:'+scrollH+'px'"><swiper-item><scroll-view scroll-y="true" :style="'height:'+scrollH+'px'"></scroll-view></swiper-item></swiper>
计算区域高度
onLoad() {const res = uni.getSystemInfoSync();this.scrollH=res.screenHeight-res.statusBarHeight-44;console.log(this.scrollH);},
导航列表联动实现
有两个swipperitem 表示关注和话题
<swiper duration=150 @change="onChange" :current="tabIndex" :style="'height:'+scrollH+'px'"><swiper-item><scroll-view scroll-y="true" :style="'height:'+scrollH+'px'"><view v-for=" (item,index) in 100" :key="index">{{item}}</view></scroll-view></swiper-item><swiper-item><view>话题</view></swiper-item></swiper>
引入common-list组件
分割线的使用
<swiper-item><scroll-view scroll-y="true" :style="'height:'+scrollH+'px'"><block v-for="(item,index) in list" :key="index" ><commonList :item="item" :index="index"></commonList><divider></divider></block></scroll-view></swiper-item><swiper-item><view>话题</view></swiper-item>
导航与列表的联动实现
<swiper duration=150 @change="onChangeTab" :current="tabIndex" :style="'height:'+scrollH+'px'"><swiper-item><scroll-view scroll-y="true" :style="'height:'+scrollH+'px'"><block v-for="(item,index) in list" :key="index" ><commonList :item="item" :index="index"></commonList><divider></divider></block></scroll-view></swiper-item><swiper-item><view>话题</view></swiper-item></swiper>onChangeTab(e){// console.log(e.detail);this.tabIndex=e.detail.current;}
顶踩操作和下拉加载功能 copy首页即可
- 移植顶踩操作
- 下拉加载的开发
关注列表页开发
热门分类组件开发
静态页面开发
<swiper-item><view class="flex justify-between align-center px-2"><text class="font-md">热门分类</text><view class="flex align-center font text-secondary">更多<text class="iconfont icon-jinru"></text></view></view><view class="flex align-center border-bottom px-2 py-3"><view class="rounded border bg-light mx-1 px-2">关注</view><view class="rounded border bg-light mx-1 px-2">关注</view><view class="rounded border bg-light mx-1 px-2">关注</view><view class="rounded border bg-light mx-1 px-2">关注</view></view></swiper-item>
添加点击动画效果
<view class="rounded border bg-light mx-1 px-2 animated" hover-class="jello">关注</view>
封装热门分类组件
热门分类对象数组构建
hotCate:[{name:'关注'},{name:'推荐'},{name:'体育'},{name:'军事'}]
封装组件, 导入组件,遍历输出, 父子传值
留两个接口
<hotCate :hotCate="hotCate"></hotCate><template><view><view class="flex justify-between align-center px-2"><text class="font-md">热门分类</text><view class="flex align-center font text-secondary animated" hover-class="jello" @click="openMore">更多<text class="iconfont icon-jinru"></text></view></view><view class="flex align-center border-bottom px-2 py-3"><view class="rounded border bg-light mx-1 px-2 animated" hover-class="jello"v-for="(item,index) in hotCate" :key="index" @click="openDetail">{{item.name}}</view></view></view> </template><script>export default{props:['hotCate'],methods:{openMore(){console.log("点击更多");},openDetail(){console.log("点击进入详情页");}}} </script><style> </style>
轮播图和搜索框的开发
静态页面开发
<view class="p-2"><view class="flex align-center justify-center py-2 rounded bg-light text-secondary"><text class="iconfont icon-sousuo mr-2"></text>搜索话题</view></view><swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000" class="px-2 pb-2"><swiper-item><image src="/static/demo/banner3.jpg" class="w-100 rounded" style="height: 300rpx;"></image></swiper-item></swiper><divider></divider>
话题列表组件开发
静态页面开发
<view class="p-2 font-md"> 最近更新</view><view class="flex align-center p-2"><image src="../../static/demo/topicpic/1.jpeg" style="width: 150rpx; height: 150rpx;"class="rounded mr-2"></image><view class="flex flex-column "><text class="font-md text-dark">话题哈哈哈</text><text class="font text-secondary">话题描述</text><view class="flex align-center font text-secondary"><text class="mr-2">今日:0</text><text>关注:0</text></view></view></view>
封装话题列表组件
声明topicList
topicList: [{cover: '/static/demo/topicpic/1.jpeg',title: '话题标题',desc: '话题描述',news_count: '10',today_count: '10'},{cover: '/static/demo/topicpic/1.jpeg',title: '话题标题',desc: '话题描述',news_count: '10',today_count: '10'},{cover: '/static/demo/topicpic/1.jpeg',title: '话题标题',desc: '话题描述',news_count: '10',today_count: '10'},{cover: '/static/demo/topicpic/1.jpeg',title: '话题标题',desc: '话题描述',news_count: '10',today_count: '10'}]
封装组件,引入组件
<block v-for="(item,index) in topicList" :key="index"><topicList :item="item" :index="index"></topicList></block><view class="flex align-center p-2"><image :src="item.cover" style="width: 150rpx; height: 150rpx;"class="rounded mr-2"></image><view class="flex flex-column "><text class="font-md text-dark">{{item.title}}</text><text class="font text-secondary">{{item.desc}}</text><view class="flex align-center font text-secondary"><text class="mr-2">动态:{{item.news_count}}</text><text>今日:{{item.today_count}}</text></view></view></view>
话题分类页开发
新建页面
{"path" : "pages/topic-nav/topic-nav","style" : {"navigationBarTitleText": "话题分类"}}
导航进入
openMore(){uni.navigateTo({url:'../topic-nav/topic-nav'})},
引入首页,修改topic—nav页面,修改common-list组件, 修改数据
<template><view><scroll-view class="scroll-row border-bottom border-light-secondary" scroll-x="true":scroll-into-view="scrollInto" scroll-with-animation="true" style="height: 100rpx;"><view v-for="(item,index) in tabBars" :key="index" class="scroll-row-item px-3 py-2 font-md ":id="'tab'+index" :class="tabIndex===index?'text-main font-lg font-weight-bold':''"@click="doTab(index)">{{item.name}}</view></scroll-view><swiper duration=150 @change="onChange" :current="tabIndex" :style="'height:'+scrollH+'px'"><swiper-item v-for="(item,index) in newList" :key="index"><template v-if="item.list.length>0"><scroll-view scroll-y="true" :style="'height:'+scrollH+'px'" @scrolltolower="loadMore(index)"><block v-for="(item2,index2) in item.list" :key="index"><!-- <commonList :item="item2" :index="index2" @follow="follow()" @doSupport="doSupport()"></commonList> --><topicList :item="item2" :index="index2"></topicList></block><loadMore :loading="item.loading"></loadMore></scroll-view></template><template v-else><no-thing></no-thing></template></swiper-item></swiper></view> </template><script>import topicList from '@/components/news/topic-list';import loadMore from '@/components/common/load-more';const demo = [{cover: '/static/demo/topicpic/1.jpeg',title: '话题标题',desc: '话题描述',news_count: '10',today_count: '10'},{cover: '/static/demo/topicpic/1.jpeg',title: '话题标题',desc: '话题描述',news_count: '10',today_count: '10'},{cover: '/static/demo/topicpic/1.jpeg',title: '话题标题',desc: '话题描述',news_count: '10',today_count: '10'},{cover: '/static/demo/topicpic/1.jpeg',title: '话题标题',desc: '话题描述',news_count: '10',today_count: '10'},{cover: '/static/demo/topicpic/1.jpeg',title: '话题标题',desc: '话题描述',news_count: '10',today_count: '10'},{cover: '/static/demo/topicpic/1.jpeg',title: '话题标题',desc: '话题描述',news_count: '10',today_count: '10'},{cover: '/static/demo/topicpic/1.jpeg',title: '话题标题',desc: '话题描述',news_count: '10',today_count: '10'},{cover: '/static/demo/topicpic/1.jpeg',title: '话题标题',desc: '话题描述',news_count: '10',today_count: '10'}];export default {components: {topicList,loadMore},data() {return {scrollH: 200,tabIndex: 0,scrollInto: '',newList: [],tabBars: [{name: '首页'},{name: '体育'},{name: '军事'},{name: '热点'},{name: '新闻'},{name: '娱乐'},{name: '电竞'},{name: '国际'},{name: '国家'}]}},onNavigationBarSearchInputClicked() {uni.navigateTo({url: '../search/search'})},onLoad() {const res = uni.getSystemInfoSync();this.scrollH = res.windowHeight - uni.upx2px(101);this.getData();},onNavigationBarButtonTap() {uni.navigateTo({url:'../add-input/add-input'})},methods: {getData() {let arr = [];for (var i = 0; i < this.tabBars.length; i++) {let obj = {loading: '上拉加载更多',list: []}if (i < 2) {obj.list = demo;}arr.push(obj)};this.newList = arr;},follow(index) {this.list[index].isFollow = true;uni.showToast({title: '关注成功'})},doSupport(e) {let obj = this.list[e.index];if (obj.support.type === '') {//无操作obj.support[e.type + '_count']++;} else if (obj.support.type === 'support' && e.type === 'unsupport') {//之前是顶,顶减一,踩加一obj.support.support_count--;obj.support.unsupport_count++;} else if (obj.support.type === 'unsupport' && e.type === 'support') {//之前是踩,顶加一,踩减一obj.support.support_count++;obj.support.unsupport_count--;}obj.support.type = e.type;let msg = e.type === 'support' ? '顶' : '踩';uni.showToast({title: msg + '成功'})},doTab(index) {this.tabIndex = index;this.scrollInto = 'tab' + index;},onChange(e) {this.doTab(e.detail.current);},loadMore(index) {let item = this.newList[index];if ((item.loading) !== '上拉加载更多') {return;}item.loading = '加载中...';setTimeout(() => {item.list = [...item.list, ...item.list];item.loading = '上拉加载更多';}, 2000)}}} </script><style></style>
话题详情页开发
page.json配置
新建topic-detail页面
配置导航栏, 渐变式透明, 图标
{"path" : "pages/topic-detail/topic-detail","style" : {"navigationBarTitleText": "","app-plus": {"titleNView": {"type": "transparent","buttons": [{"type": "menu"}]}}} }
导航到话题详情页, 传递json字符串对象, 接受数据转换object
<view class="flex align-center p-2" @click="openDetail(item)">openDetail(item){uni.navigateTo({url:'../topic-detail/topic-detail?detail='+JSON.stringify(item)})}onLoad(e){if(e.detail){var obj=JSON.parse(e.detail);// console.log(obj);}},
话题介绍组件开发
图片模糊状态
静态开发
<view><view class="position-relative"><image src="/static/demo/topicpic/1.jpeg" mode="aspectFill"style="height: 300rpx;" class="w-100 filter"></image></view><view class=" px-2 bg-white position-relative" style="z-index: 10;"><view class="flex align-center"><image src="/static/demo/topicpic/1.jpeg" class="w-100" style="height: 150rpx; width: 150rpx;margin-top: -75rpx;"></image><text class="font-md">#话题标题#</text></view><view class="flex align-center font text-secondary mt-2"><text class="mr-1">动态:0</text><text>今日:0</text></view><view class="font text-secondary">话题描述</view></view></view><style> .filter{filter: blur(10px); } </style>
封装话题介绍组件
新建topic-info组件
动态替换, 数据渲染
<template><view><view class="position-relative"><image :src="info.cover" mode="aspectFill" style="height: 300rpx;" class="w-100 filter"></image></view><view class=" px-2 bg-white position-relative pb-1" style="z-index: 10;"><view class="flex align-center"><image :src="info.cover" class="w-100" style="height: 150rpx; width: 150rpx;margin-top: -75rpx;"></image><text class="font-md">{{info.title}}</text></view><view class="flex align-center font text-secondary mt-2"><text class="mr-1">动态:{{info.news_count}}</text><text>今日:{{info.today_count}}</text></view><view class="font text-secondary">{{info.desc}}</view></view></view> </template><script>export default {props:['info']} </script><style> </style><topicInfo :info="info"></topicInfo><divider></divider>
精华帖子列表组件开发
<view class="flex p-2 border-bottom"><text class="iconfont icon-xihuan text-main"></text><text class="font text-darker text-ellipsis"> 【新人必读】uni-app实战项目第四季社区交友开发</text></view><view class="flex p-2 border-bottom"><text class="iconfont icon-xihuan text-main"></text><text class="font text-darker text-ellipsis"> 【新人必读】uni-app实战项目第四季社区交友开发</text></view>
tab选项卡组件开发
优化精华帖子列表开发, 用循环
<block v-for="(item,index) in hotList" :key="index"><view class="flex p-2 border-bottom"><text class="iconfont icon-xihuan text-main"></text><text class="font text-darker text-ellipsis">{{item.title}}</text></view></block>hotList: [{title: '【新人必读】uni-app实战项目第四季社区交友开发'},{title: '【新人必读】Hillky社区规范'}]
tab选项开发
<view class="flex align-center py-2"><text class="flex-1 flex align-center justify-center font-weight-bold font-lg text-main">默认</text><text class="flex-1 flex align-center justify-center font-weight-bold font-md text-dark">最新</text></view>
列表开发, 引入公共列表, 声明两个数组list1,2
<block v-for="(item,index) in list1" :key="index"><commonList :item="item" :index="index"></commonList></block>
tab切换实现
<view class="flex align-center py-2" ><text class="flex-1 flex align-center justify-center"v-for="(item,index) in tabBar" :key="index":class="tabIndex===index?'font-lg text-main font-weight-bold':'font-md text-dark'"@click="changeTab(index)">{{item.name}}</text></view>tabIndex: 0,tabBar:[{name:'默认'},{name:'最新'}]
利用计算属性实现列表切换
用计算属性切换数组
computed: {listData() {if (this.tabIndex === 0) {return this.list1;}if (this.tabIndex === 1) {return this.list2;}}},
遍历列表要分割线
判断数组长度, 用nothing组件
<template v-if="listData.length>0"><block v-for="(item,index) in listData" :key="index"><commonList :item="item" :index="index"></commonList><divider></divider></block></template><template v-else><no-thing></no-thing></template>
话题详情上拉加载实现
触底事件
onReachBottom() {this.loadMore();},
引入上拉加载组件
import loadMore from '@/components/common/load-more';<loadMore :loading="loadText"></loadMore>
loadText计算属性区分是哪个列表的上拉加载
loadText1:'上拉加载更多', loadText2:'上拉加载更多'loadText(){if(this.tabIndex===0){return this.loadText1}else{return this.loadText2}}
上拉加载更多事件
loadMore(){let index =this.tabIndexif(this['loadText'+(index+1)]!=='上拉加载更多'){return;}this['loadText'+(index+1)]='加载中...'setTimeout(()=>{this['loadText'+(index+1)]='上拉加载更多';this['list'+(index+1)]=[...this['list'+(index+1)],...this['list'+(index+1)]];},2000)}
消息列表页面开发
page.json配置
配置顶部导航栏, 配置左右图标
{"path": "pages/msg/msg","style": {"navigationBarTitleText": "消息列表","app-plus": {"titleNView": {"buttons": [{"color": "#333333","colorPressed": "#FD597C","float": "left","fontSize": "20px","fontSrc": "/static/iconfont.ttf","text": "\ue611"},{"color": "#333333","colorPressed": "#FD597C","float": "right","fontSize": "20px","fontSrc": "/static/iconfont.ttf","text": "\ue649"}]}}}
消息列表组件开发
静态开发
引入数字脚标组件
<view><view class="flex align-center justify-center p-2 border-bottom border-light-secondary"><image src="../../static/default.jpg" style="height: 80rpx; width: 80rpx;" class="rounded-circle mr-2"></image><view class="flex-column flex flex-1"><view class="flex align-center justify-between"><text class="font-md text-dark">昵称</text><text class="font-sm text-secondary">17:00</text></view><view class="py-1 flex align-center justify-between"><view class=" font-sm text-secondary">内容</view><uni-badge text="1" type="error"></uni-badge></view></view></view></view>
封装消息列表组件
优化内容, 添加对应css和最大宽度
<view class="pt-1 flex align-center justify-between"><view class=" font-sm text-secondary text-ellipsis" style="max-width: 500rpx;">内容内容内容内容内容内容内容内容内容内容内容内容内容</view><uni-badge text="1" type="error"></uni-badge></view>
封装数据,封装组件, 时间使用在线时间戳
引入time.js, 使用对应库,使用过滤器
import $T from '@/common/time.js'filters:{formatTime(value){return $T.gettime(value);}},
组件分离
<block v-for="(item,index) in list" :key="index"><msgList :item="item" :index="index"></msgList></block><template><view class="flex align-center justify-center p-2 border-bottom border-light-secondary"><image :src="item.avatar" style="height: 80rpx; width: 80rpx;" class="rounded-circle mr-2"></image><view class="flex-column flex flex-1"><view class="flex align-center justify-between"><text class="font-md text-dark">{{item.username}}</text><text class="font-sm text-secondary">{{item.update_time | formatTime}}</text></view><view class="pt-1 flex align-center justify-between"><view class=" font-sm text-secondary text-ellipsis" style="max-width: 500rpx;">{{item.data}}</view><uni-badge :text="item.noread" type="error"></uni-badge></view></view></view> </template><script>import $T from '@/common/time.js'export default {props:{item:Object,index:Number},filters: {formatTime(value){// console.log(value);return $T.gettime(value);}}} </script><style> </style>
下拉刷新功能实现
page.json配置
"enablePullDownRefresh": true,
监听下拉刷新, 写入方法
onPullDownRefresh() {this.refresh();},refresh(){setTimeout(()=>{this.list=demo;uni.stopPullDownRefresh();},2000);}
引入nothing组件, v-if判断
<template><view><template v-if="this.list.length>0"><block v-for="(item,index) in list" :key="index"><msgList :item="item" :index="index"></msgList></block></template><template v-else><no-thing></no-thing></template></view> </template><script>const demo=[{avatar:'../../static/default.jpg',username:'昵称',update_time:1648458088,data:'内容内容内容内容内容内容内容内容内容内容内容内容内容',noread:20},{avatar:'../../static/default.jpg',username:'昵称',update_time:1648458088,data:'内容内容内容内容内容内容内容内容内容内容内容内容内容',noread:20},{avatar:'../../static/default.jpg',username:'昵称',update_time:1648458088,data:'内容内容内容内容内容内容内容内容内容内容内容内容内容',noread:20},{avatar:'../../static/default.jpg',username:'昵称',update_time:1648458088,data:'内容内容内容内容内容内容内容内容内容内容内容内容内容',noread:20}];import msgList from '@/components/msg/msg-list';export default {components:{msgList},data() {return {list:[]}},onLoad() {this.list=demo;console.log(this.list);},onPullDownRefresh() {this.refresh();},methods: {refresh(){setTimeout(()=>{this.list=[...this.list,...this.list];uni.stopPullDownRefresh();},2000);}}} </script><style></style>
下拉弹出层组件使用
使用uni-poup组件,
监听原生导航栏按钮事件,弹出弹出层
<uni-popup ref="popup" type="top" background-color="#fff">123</uni-popup>onNavigationBarButtonTap(e) {switch (e.index){case 0:break;case 1:this.$refs.popup.open();break;}},
下拉弹出选项完善
静态开发
添加点击事件
<uni-popup ref="popup" type="top" background-color="#fff"><view class="flex justify-center align-center font-md border-bottom py-2" hover-class="bg-light"@click="popupEvent('findFriend')"><text class="iconfont icon-sousuo mr-2" ></text>搜索好友</view><view class="flex justify-center align-center font-md py-2" hover-class="bg-light"@click="popupEvent('deleteList')"><text class="iconfont icon-shanchu mr-2"></text>删除列表</view></uni-popup>popupEvent(event){switch (event){case 'findFriend':{console.log('findFriend');this.$refs.popup.close();break;}case 'deleteList':{console.log('deleteList');this.$refs.popup.close();break;}}}
我的好友列表页开发
page.json配置
新建user-list, 导航进入该页面
onNavigationBarButtonTap(e) {switch (e.index){case 0:uni.navigateTo({url:'../user-list/user-list'})break;case 1:this.$refs.popup.open();break;}},
配置page.json
{"path": "pages/user-list/user-list","style": {"navigationBarTitleText": "","app-plus": {"animationType": "slide-in-left","titleNView": {"autoBackButton": true,"searchInput": {"align": "center","backgroundColor": "#F5F4F2","borderRadius": "4px","disabled": true,"placeholder": "搜索用户","placeholderColor": "#6D6C67"},"buttons": [{"color": "#333333","colorPressed": "#FD597C","float": "right","fontSize": "14px","text": "取消"}]}}}
监听点击输入框事件, 监听取消按钮事件
onNavigationBarSearchInputClicked() {// console.log('跳转');uni.navigateTo({url:'../search/search'})},onNavigationBarButtonTap() {uni.navigateBack({delta: 1})},
tab导航组件再次优化
引入tabBar导航
条件渲染数字
<view class="flex align-center py-2"><text class="flex-1 flex align-center justify-center" v-for="(item,index) in tabBar" :key="index":class="tabIndex===index?'font-lg text-main font-weight-bold':'font-md text-dark'"@click="changeTab(index)">{{item.name}} <text v-if="item.num>0" class="ml-1">{{item.num}}</text> </text></view>
好友列表组件开发
引入首页的scrollview, 下拉, 对应修改和引入
列表样式静态开发
<swiper duration=150 @change="onChange" :current="tabIndex" :style="'height:'+scrollH+'px'"><swiper-item v-for="(item,index) in newList" :key="index"><template v-if="item.list.length>0"><scroll-view scroll-y="true" :style="'height:'+scrollH+'px'" @scrolltolower="loadMore(index)"><block v-for="(item2,index2) in item.list" :key="index2"><view class="flex align-center p-2 border-bottom border-light-secondary"><image src="../../static/default.jpg" class="rounded-circle mr-2" style="width: 100rpx; height: 100rpx;"></image><view class="flex flex-column flex-1"><text class="font-md text-dark">昵称</text><text class="font-sm mt-1">性别</text></view><view class="uni-icon uni-icon-checkbox-filled text-light-muted "></view></view></block><loadMore :loading="item.loading"></loadMore></scroll-view></template><template v-else><no-thing></no-thing></template></swiper-item></swiper>getData() {let arr = [];for (var i = 0; i < this.tabBars.length; i++) {let obj = {loading: '上拉加载更多',list: []}if (i < 2) {obj.list = [1,2,3,4];}arr.push(obj)};this.newList = arr;},changeTab(index){this.tabIndex=index;},onChange(e){this.changeTab(e.detail.current);},loadMore(index) {let item = this.newList[index];if ((item.loading) !== '上拉加载更多') {return;}item.loading = '加载中...';setTimeout(() => {item.list = [...item.list, ...item.list];item.loading = '上拉加载更多';}, 2000)}
强化badge组件开发
使用uni-badge, 插入图标, 优化性别显示
<view><text class="iconfont icon-nv text-secondary"style="font-size: 18rpx;"></text><uni-badge type="error" text="24"></uni-badge></view>
封装好友列表组件
测试demo数据
const demo=[{avatar:'../../static/default.jpg',username:'昵称',sex:1,age:24,isFollow:false},{avatar:'../../static/default.jpg',username:'昵称',sex:2,age:24,isFollow:true}];
数据渲染,动态绑定性别class, 点击灰色
封装组件, 引入组件
<template><view><view class="flex align-center p-2 border-bottom border-light-secondary " hover-class="bg-light"><image :src="item.avatar" class="rounded-circle mr-2" style="width: 100rpx; height: 100rpx;"></image><view class="flex flex-column flex-1"><text class="font-md text-dark">{{item.username}}</text><view v-if="item.sex>0"><text class="iconfont text-secondary" :class="item.sex===1?'icon-nv':'icon-nan'" style="font-size: 18rpx;"></text><uni-badge :type="item.sex===1?'error':'primary'" :text="item.age"></uni-badge></view></view><view class="uni-icon uni-icon-checkbox-filled " :class="item.isFollow?'text-light-muted':'text-main'"></view></view></view> </template><script>export default {name:"user-list",props:{item:Object,index:Number},data() {return {};}} </script><style></style>import userList from '@/components/user-list/user-list.vue';<userList :item="item2" :index="index2"></userList>
优化我的好友列表页面
优化scrollH问题,引入首页方法
onLoad() {this.getData();const res = uni.getSystemInfoSync();this.scrollH = res.windowHeight - uni.upx2px(101);// console.log(this.scrollH);},
隐藏上拉加载组件
<loadMore :loading="item.loading" v-if="item.list.length>10"></loadMore>
聊天界面开发
page.json配置
新建页面user-chat, 导航进入
配置导航栏
{"path" : "pages/user-chat/user-chat","style" :{"app-plus": {"titleNView": {"buttons": [{"color": "#333333","colorPressed": "#FD597C","float": "right","fontSize": "20px","fontSrc": "/static/iconfont.ttf","text": "\ue628"}]}}}
聊天输入框组件开发
底部操作条开发
<view class="flex fixed-bottom align-center bg-white border-top" style="height: 100rpx;"><view class="flex-1"><input type="text" placeholder="请文明发言" class="rounded ml-2 bg-light p-1" /></view><view class="iconfont icon-fabu flex align-center justify-center font-lg animated" style="width: 100rpx;"hover-class="jello text-main"></view></view>
聊天列表组件开发
scrollH获取
<scroll-view :style="'height: '+this.scrollH+'px;'" scroll-y="true"><view v-for="i in 100" :key="i">{{i}}</view></scroll-view>onLoad() {const res = uni.getSystemInfoSync();this.scrollH = res.windowHeight - uni.upx2px(101);},
聊天列表组件开发
右边气泡的开发
<scroll-view :style="'height: '+this.scrollH+'px;'" scroll-y="true"><view class="flex align-start px-2 my-2"><image src="../../static/default.jpg" class="rounded-circle"style="height: 100rpx; width: 100rpx;"></image><view class="bg-light mx-2 p-2 rounded mt-1" style="max-width: 400rpx; min-width: 100rpx;">你好啊</view></view><view class="flex align-start px-2 my-2" style="flex-direction: row-reverse;"><image src="../../static/default.jpg" class="rounded-circle"style="height: 100rpx; width: 100rpx;"></image><view class="bg-light mx-2 p-2 rounded mt-1" style="max-width: 400rpx; min-width: 100rpx;">你好啊</view></view></scroll-view>
封装聊天列表组件完善时间显示
新建user-chat-list, 封装数据
计算属性, 是否本人
isShelf(){return this.item.userId===1},
时间显示开发
<view class="my-2 flex align-center justify-center text-secondary font-sm">{{shortTime}}</view>
引入time.js, 优化时间显示, 用计算属性
shortTime(){return $T.getChatTime(this.item.create_time,this.preTime);}<userChatList :item="item" :index="index" :preTime=" index>0 ? list[index-1].create_time : 0"></userChatList>
完善聊天页功能
输入框绑定内容, 绑定发送事件, 发送功能实现
sendMessage(){let obj={userId:1,avatar: '../../static/default.jpg',data: this.content,type: 'text',create_time: (new Date()).getTime()};if(obj.data===''){uni.showToast({title:"请输入内容"});return;}this.list.push(obj);this.content=''}
优化功能, 最小宽度去掉, 键盘推页面false, 清空输入框, 丢弃scrollH
<input type="text" placeholder="请文明发言" class="rounded ml-2 bg-light p-1" v-model="content" adjust-position="false" /><scroll-view style="position: absolute; left: 0 ; top: 0; right: 0; bottom: 100rpx;" scroll-y="true">
滚动到底部实现
<scroll-view style="position: absolute; left: 0 ; top: 0; right: 0; bottom: 100rpx;" scroll-y="true":scroll-into-view="scrollInto" scroll-with-animation><block v-for="(item,index) in list" :key="index"><userChatList :id="'chat'+index" :item="item" :index="index" :preTime=" index>0 ? list[index-1].create_time : 0"></userChatList></block></scroll-view>pageToBottom(){let lastIndex=this.list.length-1;if(lastIndex < 0){return}this.scrollInto='chat'+lastIndex;console.log(this.scrollInto);}onReady() {this.pageToBottom();},
搜索列表页开发
搜索列表功能完善
添加搜索标识
onNavigationBarSearchInputClicked() {uni.navigateTo({url: '../search/search?type=post'})},
获取类型, 修改搜索占位, 添加如果说是app端
if (e.type) {this.type = e.type;}let pageTitle='';switch (this.type) {case 'post':pageTitle='搜索帖子'break;case 'topic':pageTitle='搜索话题'break;case 'friend':pageTitle='搜索好友'break;}console.log(this.type);// #ifdef APP-PLUSlet currentWebview=this.$scope.$getAppWebview();let tn=currentWebview.getStyle().titleNView;tn.searchInput.placeholder=pageTitle;console.log(tn);currentWebview.setStyle({titleNView:tn})// #e
搜索结果完善优化, 根据不同搜索,组件,数据都要不同
searchEvent() {uni.hideKeyboard();uni.showLoading({title: '加载中'})setTimeout(() => {switch (this.type) {case 'post':this.serachList = demo1;break;case 'topic':this.serachList = demo2;break;case 'friend':this.serachList = demo3;break;}uni.hideLoading();}, 3000)},<block v-for="(item,index) in serachList" :key="index"><template v-if="type==='post'"><commonList :item="item" :index="index"></commonList></template><template v-if="type==='topic'"><topicList :item="item" :index="index"></topicList></template><template v-if="type==='friend'"><userList :item="item" :index="index"></userList></template></block>
文章详情页开发
page.json配置
新建页面,detail, 导航入口
,{"path" : "pages/detail/detail","style" : {"app-plus": {"titleNView": {"buttons": [{"float": "right","type": "menu"}]}}}}
把对象作为参数传过去,初始化
openDetail(){console.log("打开详情页");uni.navigateTo({url:'../../pages/detail/detail?detail='+JSON.stringify(this.item)})},onLoad(e){if(e.detail){this.__init(JSON.parse(e.detail));}},methods: {__init(data){uni.setNavigationBarTitle({title:data.title})}}
强化公共列表组件功能
修改公共列表组件, 添加isDetail, prop, 评论和分享功能
props: {item: Object,index: {type: Number,default: -1},isDetail: {type: Boolean,default: false}},doComment(){if(!this.isDetail){return this.openDetail();}this.$emit('doComment');},doShare(){if(!this.isDetail){return this.openDetail();}this.$emit('doShare');}
<commonList :item="this.item" :isDetail="true" @doComment="doComment" @doShare="doShare">帖子详请</commonList>
完善详情页关注顶踩功能
关注事件, 修改index默认值
follow() {this.info.isFollow = true;}index: {type: Number,default: -1}
顶踩方法改写
doSupport(e) {let obj = this.infoif (obj.support.type === e.type) {uni.showToast({title: '你已经操作过了'})return;}if (obj.support.type === '') {//无操作obj.support[e.type + '_count']++;} else if (obj.support.type === 'support' && e.type === 'unsupport') {//之前是顶,顶减一,踩加一obj.support.support_count--;obj.support.unsupport_count++;} else if (obj.support.type === 'unsupport' && e.type === 'support') {//之前是踩,顶加一,踩减一obj.support.support_count++;obj.support.unsupport_count--;}obj.support.type = e.type;let msg = e.type === 'support' ? '顶' : '踩';uni.showToast({title: msg + '成功'})}
增加content,image
content:"Hillky正在开发ing.....",images:[{url:"https://tupian.qqw21.com/article/UploadPic/2020-5/20205622141239876.jpg"},{url:"https://tse1-mm.cn.bing.net/th/id/R-C.df1d553893d9b7888c725b8dbcbcf439?rik=hpbIzO6xZ3Qchw&riu=http%3a%2f%2fwww.chabeichong.com%2fimages%2f2016%2f11%2f12-04122113.jpg&ehk=%2fe971CgX%2bMeAgZuGCVac3td74wDOd1%2bWzz0q4IsP1Lc%3d&risl=&pid=ImgRaw&r=0&sres=1&sresct=1"}]
增加图片预览功能
<image v-for="(item,index) in info.images" :src="item.url" class="w-100" mode="widthFix" @click="preview(index)"></image>preview(index){// console.log(this.imageList);uni.previewImage({urls:this.imageList,current:index})}computed:{imageList(){return this.info.images.map(item=>item.url);}},
评论输入框组件封装
先对聊天室底部操作条的封装,测试是否成功
<template><view class="flex fixed-bottom align-center bg-white border-top" style="height: 100rpx;"><view class="flex-1"><input type="text" placeholder="请文明发言" class="rounded ml-2 bg-light p-1" v-model="content"adjust-position="false" /></view><view class="iconfont icon-fabu flex align-center justify-center font-lg animated" style="width: 100rpx;"hover-class="jello text-main" @click="sendMessage"></view></view> </template><script>export default {data(){return{content:''}},methods:{sendMessage(){if (this.content === '') {uni.showToast({title: "请输入内容",icon:"none"});return;}this.$emit('submit',this.content);this.content = '';}}} </script><style> </style><bottomBtn @submit="submit"></bottomBtn>submit(content) {let obj = {userId: 1,avatar: '../../static/default.jpg',data: content,type: 'text',create_time: (new Date()).getTime()};this.list.push(obj);this.pageToBottom();},
再到detail页面使用该组件,需要占位
列表评论组件开发
使用官方评论界面,进行静态开发
<view class="px-2"><!-- 评论区 start --><view class="uni-comment"><view class="uni-comment-list"><view class="uni-comment-face" style="margin-top: 15rpx;"><image src="https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/uni@2x.png" mode="widthFix"></image></view><view class="uni-comment-body"><view class="uni-comment-top"><text>网友</text></view><view class="uni-comment-date"><text>08/10 08:12</text></view><view class="uni-comment-content">很酷的HBuilderX和uni-app,开发一次既能生成小程序,又能生成App</view></view></view></view></view>
分享功能组件开发
弹出层,底部弹出, 监听导航栏按钮触发, 层级关系的修改-z-index
<uni-popup ref="popup" type="bottom" background-color="#fff"><view style="height: 300rpx;">123</view></uni-popup>onNavigationBarButtonTap() {this.$refs.popup.open();},uni-popup {position: fixed;/* #ifndef APP-NVUE */z-index: 9999;
监听返回事件,隐藏弹出层
onBackPress() {this.$refs.popup.close();},
静态开发
<view class="font-md border-bottom border-light-secondary text-center py-2">分享到</view><view class="flex align-center "><view class="flex flex-1 flex-column justify-center align-center py-2"><view class="iconfont icon-QQ rounded-circle bg-primary text-white flex align-center justify-center font-lg" style="width: 100rpx; height: 100rpx;"></view><view class="font mt-1 text-light-muted">QQ好友</view></view>...</view><view class="font-md border-top border-light-secondary text-center py-2">取消</view>
遍历图标
<block v-for="(item,index) in btnList" :key="index"><view class="flex flex-1 flex-column justify-center align-center py-2"><viewclass="iconfont rounded-circle bg-primary text-white flex align-center justify-center font-lg":class="item.icon+' '+item.color "style="width: 100rpx; height: 100rpx;"></view><view class="font mt-1 text-light-muted">{{item.name}}</view></view></block>
封装组件 more-share.vue
<template><view><uni-popup ref="popup" type="bottom" background-color="#fff"><view class="font-md border-bottom border-light-secondary text-center py-2">分享到</view><view class="flex align-center "><block v-for="(item,index) in btnList" :key="index"><view class="flex flex-1 flex-column justify-center align-center py-2"><viewclass="iconfont rounded-circle bg-primary text-white flex align-center justify-center font-lg":class="item.icon+' '+item.color " style="width: 100rpx; height: 100rpx;"></view><view class="font mt-1 text-light-muted">{{item.name}}</view></view></block></view><view class="font-md border-top border-light-secondary text-center py-2">取消</view></uni-popup></view> </template><script>export default {data(){return{btnList: [{"icon": 'icon-QQ',"color": 'bg-primary',"name": 'QQ好友'},{"icon": 'icon-QQ',"color": 'bg-primary',"name": 'QQ好友'},{"icon": 'icon-QQ',"color": 'bg-primary',"name": 'QQ好友'},{"icon": 'icon-QQ',"color": 'bg-primary',"name": 'QQ好友'}],}},methods:{open(){this.$refs.popup.open();},close(){this.$refs.popup.close();}}} </script><style> </style>
<moreShare ref="share"></moreShare>onNavigationBarButtonTap() {this.$refs.share.open();},onBackPress() {this.$refs.share.close();},
用官方组件分享动态渲染数据, 子组件用created()
created(){uni.getProvider({service: 'share',success: (e) => {console.log(e);let data = []for (let i = 0; i < e.provider.length; i++) {switch (e.provider[i]) {case 'weixin':data.push({name: '微信好友',id: 'weixin',icon:'icon-weixin',color:'bg-success',sort:0})data.push({name: '朋友圈',id: 'weixin',icon:'icon-huati',color:'bg-dark',type:'WXSenceTimeline',sort:1})break;case 'sinaweibo':data.push({name: '新浪微博',icon:'icon-xinlangweibo',color:'bg-danger',id: 'sinaweibo',sort:2})break;case 'qq':data.push({name: 'QQ好友',id: 'qq',icon:'icon-QQ',color:'bg-primary',sort:3})break;default:break;}}this.providerList = data.sort((x,y) => {return x.sort - y.sort});},fail: (e) => {console.log('获取分享通道失败', e);uni.showModal({content:'获取分享通道失败',showCancel:false})}});},
分享方法
async share(e) {console.log('分享通道:'+ e.id +'; 分享类型:' + this.shareType);if(!this.shareText && (this.shareType === 1 || this.shareType === 0)){uni.showModal({content:'分享内容不能为空',showCancel:false})return;}if(!this.image && (this.shareType === 2 || this.shareType === 0)){uni.showModal({content:'分享图片不能为空',showCancel:false})return;}let shareOPtions = {provider: e.id,scene: e.type && e.type === 'WXSenceTimeline' ? 'WXSenceTimeline' : 'WXSceneSession', //WXSceneSession”分享到聊天界面,“WXSenceTimeline”分享到朋友圈,“WXSceneFavorite”分享到微信收藏 type: this.shareType,success: (e) => {console.log('success', e);uni.showModal({content: '已分享',showCancel:false})},fail: (e) => {console.log('fail', e)uni.showModal({content: e.errMsg,showCancel:false})},complete:function(){console.log('分享操作结束!')}}switch (this.shareType){case 0:shareOPtions.summary = this.shareText;shareOPtions.imageUrl = this.image;shareOPtions.title = '欢迎体验uniapp';shareOPtions.href = 'https://uniapp.dcloud.io';break;case 1:shareOPtions.summary = this.shareText;break;case 2:shareOPtions.imageUrl = this.image;break;case 5:shareOPtions.imageUrl = this.image ? this.image : 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/b6304f00-5168-11eb-bd01-97bc1429a9ff.png'shareOPtions.title = '欢迎体验uniapp';shareOPtions.miniProgram = {id:'gh_33446d7f7a26',path:'/pages/tabBar/component/component',webUrl:'https://uniapp.dcloud.io',type:0};break;default:break;}if(shareOPtions.type === 0 && plus.os.name === 'iOS'){//如果是图文分享,且是ios平台,则压缩图片 shareOPtions.imageUrl = await this.compress();}if(shareOPtions.type === 1 && shareOPtions.provider === 'qq'){//如果是分享文字到qq,则必须加上href和titleshareOPtions.href = 'https://uniapp.dcloud.io';shareOPtions.title = '欢迎体验uniapp';}uni.share(shareOPtions);},
个人中心页面开发
page.json配置
配置page.json
{"path": "pages/my/my","style": {"navigationBarTitleText": "我的","app-plus": {"titleNView": {"buttons": [{"type": "menu"}]}}}},
个人中心ui构建
静态开发第一个view
<view class="flex align-center p-2"><image src="../../static/default.jpg" style="width: 100rpx; height: 100rpx;" class="rounded-circle"></image><view class="flex flex-column flex-1 px-2"><text class="font-lg font-weight-bold text-dark ">昵称</text><text class="font text-muted mt-1"> 总帖子10 今日发帖0</text></view><view class="iconfont icon-jinru"></view></view>
第二个view开发,使用遍历方式
<view class="flex align-center px-3 py-2"><view class="flex-1 flex-column flex align-center justify-center" v-for="(item,index) in this.itemList " :key="index"><text class="font-lg text-dark">{{item.num}}</text><text class="text-muted fony">{{item.name}}</text></view></view>
第三个view, 广告位的开发
<view class="px-3 py-2"><image src="/static/demo/banner1.jpg" style="height: 300rpx; width: 100%;" mode="aspectFill" class="rounded"></image></view>
引入uni-list-item
<uni-list-item title="浏览历史" :showExtraIcon="true" :extra-icon="extraIcon1" link :border="false"></uni-list-item><uni-list-item title="社区认证" :showExtraIcon="true" :extra-icon="extraIcon2" link :border="false"></uni-list-item><uni-list-item title="审核帖子" :show-extra-icon="true" link :border="false"><text slot="icon" class="iconfont icon-keyboard font-lg"></text></uni-list-item>import uniListItem from '@/components/uni-list-item/uni-list-item.vue';extraIcon1: {type: 'eye',color: '#000000',size: 20},extraIcon2: {type: 'vip',color: '#000000',size: 20},
设置页面开发
新建页面,导航进入
退出登录静态开发
<template><view><uni-list-item title="账号与安全" link :border="false" ></uni-list-item><uni-list-item title="资料编辑" link :border="false" ></uni-list-item><uni-list-item title="清楚缓存" link :border="false"></uni-list-item><uni-list-item title="意见反馈" link :border="false"></uni-list-item><uni-list-item title="关于社区" link :border="false"></uni-list-item><view class="py-2 px-3"><button class="bg-main text-white" style="border-radius: 50rpx;">退出登录</button></view></view> </template><script>import uniListItem from '@/components/uni-list-item/uni-list-item.vue';export default {components:{uniListItem},data() {return {}},methods: {}} </script><style></style>
修改密码页面开发
修改密码UI界面开发
新建页面,导航进入
<uni-list-item title="账号与安全" link :border="false" @click="open"></uni-list-item>uni.navigateTo({url:'../userPassword/userPassword'})
静态页面开发
<view class="px-1"><input class="uni-input" value="" type="text" placeholder="输入旧密码"/><input class="uni-input" value="" type="text" placeholder="输入新密码"/><input class="uni-input" value="" type="text" placeholder="输入确认密码"/><view class="py-2 px-3"><button class="bg-main text-white" style="border-radius: 50rpx;">设置</button></view></view>
表单验证功能实现
输入框绑定vue, disabled属性绑定
computed:{disable(){return this.oldPassword===''||this.newPassword===''||this.renewPassword==='';}},<button class="bg-main text-white" style="border-radius: 50rpx;" :disabled="disable">设置</button>
验证功能实现
check(){if(this.newPassword!==this.renewPassword){uni.showToast({title:'两次输入密码不一致',icon:"none"})return false;}return true;},submit(){if(this.check()){console.log('提交成功');}}
修改邮箱页面开发
修改邮箱页UI界面开发
新建页面, 配置page.json
,{"path" : "pages/userEmail/userEmail","style" : {"navigationBarTitleText": "设置邮箱"}}
拼接字符串, 配置导航,引号不一样用1左边的那个,${}拼接
open(path){uni.navigateTo({url:`../${path}/${path}`,fail(e) {console.log(e);}})}
静态页面开发,与修改密码差不多的功能,禁用
<template><view><input type="text" class="uni-input" placeholder="请输入邮箱" v-model="email"/><input type="text" class="uni-input" placeholder="请输入密码" v-model="password"/><button class="bg-main text-white mt-1" style="border-radius: 50rpx;" :disabled="disable">绑定邮箱</button></view> </template><script>export default {data() {return {email:'',password:''}},computed:{disable(){return this.email===''||this.password===''}},methods: {}} </script><style></style>
表单验证功能实现
利用正则表达式完成邮箱功能验证js常用正则表达式
methods: {check(){var ePattern = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;if(!ePattern.test(this.email)){uni.showToast({title:'邮箱格式不正确',icon:"none"})return false;}return true;},submit(){if(this.check()){console.log("提交成功");}return;}}
编辑资料页面开发
编辑资料UI界面实现
新建页面,配置page.json,配置导航
,{"path" : "pages/userInfo/userInfo","style" : {"navigationBarTitleText": "资料编辑"}}
使用uni-list-item实现静态页面,使用插槽修改
<template><view><uni-list-item title="头像" :border="false" ><view slot="right" class="flex"><image class="rounded" style="width: 100rpx; height: 100rpx;" src="../../static/default.jpg"></image><text class="flex align-center iconfont icon-bianji1 ml-2" ></text></view></uni-list-item><uni-list-item title="昵称" :border="false"><view slot="right" class="flex ">哈哈<text class="flex align-center iconfont icon-bianji1 ml-2 " ></text></view></uni-list-item><uni-list-item title="性别" :border="false"><view slot="right" class="flex ">未知<text class="flex align-center iconfont icon-bianji1 ml-2 " ></text></view></uni-list-item><uni-list-item title="生日" :border="false"><view slot="right" class="flex ">2021-4-1<text class="flex align-center iconfont icon-bianji1 ml-2 " ></text></view></uni-list-item><uni-list-item title="情感" :border="false"><view slot="right" class="flex ">已婚<text class="flex align-center iconfont icon-bianji1 ml-2 " ></text></view></uni-list-item><uni-list-item title="职业" :border="false"><view slot="right" class="flex align-center">程序员<text class="flex align-center iconfont icon-bianji1 ml-2 " ></text></view></uni-list-item><uni-list-item title="家乡" :border="false"><view slot="right" class="flex ">广东广州<text class="flex align-center iconfont icon-bianji1 ml-2 " ></text></view></uni-list-item><view class="py-2 px-3"><button class="bg-main text-white" style="border-radius: 50rpx;">完成</button></view></view> </template><script>import uniListItem from '@/components/uni-list-item/uni-list-item.vue';export default {components:{uniListItem},data() {return {}},methods: {}} </script><style></style>
修改头像功能
添加点击事件, 动态绑定userPIc
<uni-list-item title="头像" :border="false"><view slot="right" class="flex"><image class="rounded" style="width: 100rpx; height: 100rpx;" :src="userPic"></image><text class="flex align-center iconfont icon-bianji1 ml-2" @click="changePic" ></text></view></uni-list-item>
uni.chooseImage的使用, 修改头像功能实现
changePic(){uni.chooseImage({count:1,sizeType:["compressed"],sourceType:["album","camera"],success:(e)=>{this.userPic=e.tempFilePaths[0];}})}
showActionSheet接口使用
修改昵称,用输入框
<input v-model="nickname" class="text-right"/>
修改性别, 使用showActionSheet,使用计算属性渲染
<uni-list-item title="性别" :border="false"><view slot="right" class="flex ">{{sexText}}<text class="flex align-center iconfont icon-bianji1 ml-2 " @click="changeSex"></text></view></uni-list-item>const sexArray=["保密","男","女"];sex:0,sexText(){return sexArray[this.sex];},changeSex(){uni.showActionSheet({itemList:sexArray,success:(e)=>{// this.sex=sexArray[e.tapIndex];this.sex=e.tapIndex;}})},
修改情感, 使用一样的方法
修改职业, 使用一样的方法
changeJob(){uni.showActionSheet({itemList:jobArray,success:(e)=>{this.job=jobArray[e.tapIndex];}})}
修改生日功能实现
使用picker,完成该功能
<picker mode="date" :value="birthday" @change="onDateChange"><uni-list-item title="生日" :border="false"><view slot="right" class="flex ">{{birthday}}<text class="flex align-center iconfont icon-bianji1 ml-2 "></text></view></uni-list-item></picker>onDateChange(e){this.birthday=e.detail.value;}
三级城市联动多列选择器选择城市
使用官方组件mpvueCityPicker
<uni-list-item title="家乡" :border="false"><view slot="right" class="flex ">{{pickerText}}<text class="flex align-center iconfont icon-bianji1 ml-2 " @click="showCityPicker"></text></view></uni-list-item><mpvue-city-picker :themeColor="themeColor" ref="mpvueCityPicker" :pickerValueDefault="cityPickerValueDefault"@onConfirm="onConfirm"></mpvue-city-picker>import mpvueCityPicker from '@/components/mpvue-citypicker/mpvueCityPicker.vue'mpvueCityPickerthemeColor:'#007AFF',cityPickerValueDefault:[0, 0, 1],pickerText:'广东广州'onBackPress() {if (this.$refs.mpvueCityPicker.showPicker) {this.$refs.mpvueCityPicker.pickerCancel();return true;}},onUnload() {if (this.$refs.mpvueCityPicker.showPicker) {this.$refs.mpvueCityPicker.pickerCancel()}},onConfirm(e){this.pickerText = e.label;},showCityPicker(){this.$refs.mpvueCityPicker.show()}
帮助反馈页面开发
帮助反馈UI界面实现
新建页面,配置page.json
使用组件uni-collapse
<view><uni-collapse accordion><uni-collapse-item title="默认开启" ><text>折叠内容</text></uni-collapse-item><uni-collapse-item title="默认开启" ><text>折叠内容</text></uni-collapse-item></uni-collapse><view class="py-2 px-3"><button class="bg-main text-white" style="border-radius: 50rpx;">意见反馈</button></view></view>
关于页面开发
关于页面UI界面
新建页面,配置page.json
静态页面开发
<view><view class="flex align-center justify-center flex-column pt-4 pb-3"><image src="../../static/common/nothing.png" style="width: 300rpx; height: 300rpx;" class="rounded-circle"></image><text class="font text-muted mt-2">version 1.0.1</text></view><uni-list-item title="新版本检测" :border="false" link></uni-list-item><uni-list-item title="社区用户协议" :border="false" link></uni-list-item></view>
登录页开发
page.json配置
新建页面,取消原生导航,导航进入
,{"path" : "pages/login/login","style" : {"navigationBarTitleText": "","app-plus": {"titleNView": false}}}<navigator url="../login/login"><view class="flex align-center p-2" hover-class="bg-light"><image src="../../static/default.jpg" style="width: 100rpx; height: 100rpx;" class="rounded-circle"></image><view class="flex flex-column flex-1 px-2"><text class="font-lg font-weight-bold text-dark ">昵称</text><text class="font text-muted mt-1"> 总帖子10 今日发帖0</text></view><view class="iconfont icon-jinru"></view></view></navigator>
x的样式开发
<view class="flex iconfont icon-guanbi algin-center justify-center font-lg " style="width: 100rpx; height: 100rpx;position: fixed; left: 0;":style="'top:'+statusBarHeight+'px;'" hover-class="bg-light" @click="back"></view>var res=uni.getSystemInfoSync();this.statusBarHeight=res.statusBarHeight;back(){uni.navigateBack({delta:1})}
登录页UI界面构建
对之前的开发进行修改,引用一个view代替状态栏即可
<template><view><view class="status_bar"><!-- 这里是状态栏 --></view><view> 状态栏下的文字 </view></view> </template> <style>.status_bar {height: var(--status-bar-height);width: 100%;} </style>
静态页面开发
<view class="flex iconfont icon-guanbi algin-center justify-center font-lg " style="width: 100rpx; height: 100rpx;position: fixed; left: 0;" hover-class="bg-light" @click="back"></view><view class="flex algin-center justify-center " style="margin-top: 300rpx;"><text class="text-secondary " style="font-size: 60rpx;">账号密码登录</text></view><view class="flex algin-center border-bottom py-3 px-2 " style="margin-top: 100rpx;"><input type="text" placeholder="昵称/手机号/邮箱" class="" /></view><view class="flex algin-center border-bottom"><input type="text" placeholder="请输入密码" class="py-3 px-2 flex-1" /><text style="width: 150rpx;" class="text-muted py-3">忘记密码</text></view><view class="py-2 px-3 " style="margin-top: 100rpx;"><button class="bg-main text-white" style="border-radius: 50rpx;">登录</button></view><view class="mt-5 flex algin-center justify-center"><view class="text-primary pr-2">验证码登录</view><view class="text-secondary">|</view><view class="text-primary pl-2">登录遇到问题</view></view><view class="flex algin-center justify-center mt-5"><view style="width: 100rpx; border-bottom: solid #ddd ;" class="mb-2" ></view><view class="text-muted mx-2">社交账号登录</view><view style="width: 100rpx; border-bottom: solid #ddd ; "class="mb-2" ></view></view>
登录类型切换效果实现
静态开发图标列表
<view class="flex align-center px-5 py-3" style="padding-left: 100rpx; padding-right: 100rpx;"><view class="flex-1 flex align-center justify-center"><viewclass="iconfont icon-QQ font-lg bg-primary text-white flex align-center justify-center rounded-circle "style="width: 100rpx;height: 100rpx;"></view></view><view class="flex-1 flex align-center justify-center "><viewclass="iconfont icon-QQ font-lg bg-primary text-white flex align-center justify-center rounded-circle"style="width: 100rpx;height: 100rpx;"></view></view><view class="flex-1 flex align-center justify-center "><viewclass="iconfont icon-QQ font-lg bg-primary text-white flex align-center justify-center rounded-circle"style="width: 100rpx;height: 100rpx;"></view></view></view><view class="flex algin-center justify-center px-5 text-muted">注册即代表同意<text class="text-primary">《xxx社区协议》</text></view>
切换验证码的静态显示
<view class="flex algin-center justify-center " style="margin-top: 300rpx;"><text class="text-secondary " style="font-size: 60rpx;">{{status?'账号密码登录':'验证码登录'}}</text></view><template v-if="status"><view class="flex algin-center border-bottom py-3 px-2 " style="margin-top: 100rpx;"><input type="text" placeholder="昵称/手机号/邮箱" class="" /></view><view class="flex algin-center border-bottom"><input type="text" placeholder="请输入密码" class="py-3 px-2 flex-1" /><text style="width: 150rpx;" class="text-muted py-3">忘记密码</text></view></template><template v-else><view class="flex algin-center border-bottom py-3 px-2 " style="margin-top: 100rpx;"><text class="text-dark mr-2">+86</text><input type="text" placeholder="手机号" class="" /></view><view class="flex algin-center border-bottom px-2"><input type="text" placeholder="请输入验证码" class="py-3 px-2 flex-1" /><text style="width: 200rpx;" class="text-white bg-main py-3 flex justify-center">获取验证码</text></view></template>changeStatus(){this.status=!this.status}
表单基础功能实现
输入框绑定内容,计算属性disable要对于账号密码与手机验证码都ok
<input type="text" placeholder="昵称/手机号/邮箱" v-model="username" class="" />disabled(){if((this.username===''||this.password==='')&&(this.phone===''||this.code==='')){return true;}return false;}<button class="bg-main text-white" style="border-radius: 50rpx;" :disabled="disabled">登录</button>
切换登录方式要初始化表单
initForm(){this.username='';this.password='';this.phone='';this.code='';},changeStatus(){this.initForm();this.status=!this.status}
获取验证码的功能, 倒计时的功能
getCode(){if(this.codeTime>0){return;}this.codeTime=60;let timer=setInterval(()=>{if(this.codeTime>=1){this.codeTime--;}else{this.codeTime=0;clearInterval(timer);}},1000)}<text style="width: 200rpx;" class="text-white py-3 flex justify-center" @click="getCode":class="codeTime>0?'bg-main-disable':'bg-main'">{{codeTime>0?this.codeTime+'s':'获取验证码'}}</text>
验证手机号规则编写,用正则表达式验证, 提交方法绑定
getCode() {if (this.codeTime > 0) {return;}if(!this.validate()){return;}this.codeTime = 60;let timer = setInterval(() => {if (this.codeTime >= 1) {this.codeTime--;} else {this.codeTime = 0;clearInterval(timer);}}, 1000)},validate() {var mPattern = /^1[34578]\d{9}$/;var flag = mPattern.test(this.phone)// console.log(flag);if (!flag) {uni.showToast({title: '手机格式不正确',icon: "none"})return false;}return true;},submit() {if(!this.validate()){return;}console.log('验证成功');this.validate();}
第三方登录组件功能实现
新建other-login组件,实现第三方登录
<template><view class="flex align-center px-5 py-3" style="padding-left: 100rpx; padding-right: 100rpx;"><view class="flex-1 flex align-center justify-center" v-for="(item,index) in this.resultList" :key="index"><view :class="item.icon+' '+item.bgColor"class="iconfont font-lg text-white flex align-center justify-center rounded-circle "style="width: 100rpx;height: 100rpx;"></view></view></view> </template><script>export default{data(){return {providerList: [],resultList:[]}},mounted() {uni.getProvider({service: 'oauth',success: (result) => {this.providerList = result.provider.map((value) => {let providerName = '';let icon='';let bgColor='';switch (value) {case 'weixin':providerName = '微信登录'icon='icon-weixin';bgColor='bg-success';break;case 'qq':providerName = 'QQ登录';icon='icon-QQ';bgColor='bg-primary';break;case 'sinaweibo':providerName = '新浪微博登录'icon='icon-xinlangweibo';bgColor='bg-danger';break;default:break;}return {name: providerName,id: value,icon:icon,bgColor:bgColor}});console.log(this.providerList);for(var i=0;i<this.providerList.length;i++){if(this.providerList[i].id==='weixin'||this.providerList[i].id==='qq'||this.providerList[i].id==='sinaweibo'){this.resultList.push(this.providerList[i]);}}console.log(this.resultList);},fail: (error) => {console.log('获取登录通道失败', error);}});}} </script><style> </style>
个人空间开发
page.json配置
新建页面, 配置导航栏按钮,导航进入
,{"path" : "pages/user-space/user-space","style" : {"navigationBarTitleText": "","app-plus": {"titleNView": {"titleText": "个人空间","buttons": [{"type": "menu"}]}}}}openSapce() {uni.navigateTo({url:'../../pages/user-space/user-space'})},
个人空间头部开发
静态开发
<view class="flex align-center justify-center p-3 border-bottom border-light-secondary"><image src="../../static/default.jpg" class="rounded " style="width: 180rpx; height: 180rpx;"></image><view class="flex flex-column flex-1 align-center justify-center " ><view class="flex align-center justify-center " style="width: 400rpx;"><view class=" flex-1 flex align-center justify-center flex-column "><text class="font-lg font-weight-bold">1</text><text class="font text-muted">粉丝</text></view><view class=" flex flex-1 align-center justify-center flex-column"><text class="font-lg font-weight-bold">1</text><text class="font text-muted">粉丝</text></view><view class=" flex flex-1 align-center justify-center flex-column"><text class="font-lg font-weight-bold">1</text><text class="font text-muted">粉丝</text></view></view><view class="flex align-center justify-center pt-2"><button class="bg-main text-white" style="width: 400rpx;">关注</button></view></view></view>
个人空间UI界面实现
借用好友列表的tabBar
<view class="flex align-center py-4" style="height: 100rox;"><text class="flex-1 flex align-center justify-center" v-for="(item,index) in tabBars" :key="index":class="tabIndex===index?'font-lg text-main font-weight-bold':'font-md text-dark'"@click="changeTab(index)">{{item.name}}</text></view>data() {return {tabIndex:0,tabBars: [{name: '主页',},{name: '帖子',},{name: '动态',}]}},changeTab(index){this.tabIndex=index;}
主页的实现
<template v-if="tabIndex===0"><view class="px-3 border-bottom py-2"><view class="font-md">账号信息</view><view class="font">账号年龄:12个月</view><view class="font">账号id:1</view></view><view class="px-3 border-bottom py-2"><view class="font-md">个人信息</view><view class="font">星座:天蝎座</view><view class="font">职业:IT</view><view class="font">故乡:中国</view><view class="font">情感:未婚</view></view></template><template v-else><text>帖子/动态</text></template>
帖子动态的实现, 引入commonlist组件,loadMore组件,引入方法,添加动画效果
<view class="animated fast fadeIn"><block v-for="(item,index) in list" :key="index"><commonList :item="item" :index="index" @follow="follow" @doSupport="doSupport"></commonList><divider></divider></block><loadMore :loading="loading"></loadMore></view>follow(index) {let obj=this.tabBars[this.tabIndex].list[index];obj.isFollow=true;uni.showToast({title: '关注成功'})},doSupport(e) {let obj=this.tabBars[this.tabIndex].list[e.index]console.log(obj);if (obj.support.type === '') {//无操作obj.support[e.type + '_count']++;} else if (obj.support.type === 'support' && e.type === 'unsupport') {//之前是顶,顶减一,踩加一obj.support.support_count--;obj.support.unsupport_count++;} else if (obj.support.type === 'unsupport' && e.type === 'support') {//之前是踩,顶加一,踩减一obj.support.support_count++;obj.support.unsupport_count--;}obj.support.type = e.type;let msg = e.type === 'support' ? '顶' : '踩';uni.showToast({title: msg + '成功'})},
个人空间操作菜单
使用弹出层,进行修改即可
<uni-popup ref="popup" type="top" background-color="#fff"><view class="flex justify-center align-center font-md border-bottom py-2" hover-class="bg-light"@click="popupEvent('findFriend')"><text class="iconfont icon-sousuo mr-2" ></text>加入黑名单</view><view class="flex justify-center align-center font-md py-2" hover-class="bg-light"@click="popupEvent('deleteList')"><text class="iconfont icon-shanchu mr-2"></text>聊天</view></uni-popup>onNavigationBarButtonTap() {this.$refs.popup.open();},
全局功能开发
清楚缓存的功能
- 添加点击事件,清除缓存的方法
==文档只有一些功能缺失,但源码已经完善所有功能,详情请点击码云地址下载源码学习 https://gitee.com/HelLichu/friend ==
使用uniapp开发社区交友网站的项目教程相关推荐
- uni-app开发社区交友类项目
本项目使用uni-app开发社区交友类项目源码
- uni-app实战社区交友
前言 本文是针对<uni-app实战社区交友>系列视频教程的笔记和补充说明, 帮助编程新手快速找到捷径 2021.2.16更新 提示:着重说明比较难的部分,比较简单的教程不详述 免费资源在 ...
- java项目交友网如何实现,基于jsp的交友网站-JavaEE实现交友网站 - java项目源码
基于jsp+servlet+pojo+mysql实现一个javaee/javaweb的交友网站, 该项目可用各类java课程设计大作业中, 交友网站的系统架构分为前后台两部分, 最终实现在线上进行交友 ...
- uniapp开发h5微信授权登录(详细教程)
uniapp开发h5微信授权登录 文章目录 uniapp开发h5微信授权登录 前言 一.前期准备--申请测试账号 二.正式开发--前端代码 三.打包发布 总结 前言 我也是第一次做h5授权微信登录,网 ...
- Uni-app 实战社区交友类app开发
环境搭建和创建项目 开发环境搭建 工具的使用 创建uniapp项目 开发环境搭建 工具的使用 dhttps://www.dcloud.io/hbuilderx.html ,输入网址下载. 插件安装 : ...
- 网易云课堂uni-app实战社区交友类app开发笔记
文章目录 前言 代码展示 前言 提示:可以在这里引入话题,记得删除示例哦. 例如:我们在进行项目开发的时候可能会遇到一些获取屏幕宽度,dp px的相互转换等问题,我们当然不能每用一次就复制粘贴一次.这 ...
- 学习笔记(2):uni-app实战社区交友类app开发-引入css动画库
立即学习:https://edu.csdn.net/course/play/28009/381722?utm_source=blogtoedu 1. 百度搜索并打开 animate.css . ...
- 学习笔记(1):uni-app实战社区交友类app开发-引入自定义图标库
立即学习:https://edu.csdn.net/course/play/28009/381721?utm_source=blogtoedu 1. 在iconfont.cn图标库中打包下载图标文件压 ...
- 中国最大同性交友网站--Gitee入门教程
你好,我是江潮 你有没有遇到过这种情况: 在开发项目的时候,我们会不断地去修改代码,但是有时候会遇到,想查看某一时间的代码这种情况,如果没有版本控制器,你可能需要不断地定时备份代码,但这样显然是很麻烦 ...
最新文章
- xubuntu 19.10安装tensorflow-gpu-2.0(本文很乱,供自己参考)
- maven 主工程 java_Maven创建Java Application工程(既jar包)
- 我是发起人Sumtec
- jsp 中forward 和 Redirect 的用法区别
- linux父子进程同步实验,Linux-父子进程的简单同步
- Spring MVC——ConverterltString, Dategt DEMO
- boost::fruchterman_reingold_force_directed_layout用法的测试程序
- .NET 泛型,详细介绍
- 中南大学c语言试题期末考试,2011年中南大学C语言期末试题卷A
- JavaScript---DOM事件
- hash存储结构【六】
- db2 控制台执行创建函数语句_Python函数定义及调用
- 全程2分钟!教你如何免费下载Windows 10
- CVPR学习(三):CVPR2019-各个方向
- glassfish3新建domain
- CCFTF17(上海):认知计算产业化如何落地(知识图谱、智能问答等)
- ISO国家和地区代码
- 类型函数(type function)
- 硬盘检测重映射扇区计数失败
- 【python】LOFTER抽奖程序
热门文章
- 计算机系统中设置保护系统还原,如何对电脑进行系统还原
- 南京工资个税计算机,2017南京工资交税标准及个税起征点
- 输入法/非输入法切换 无法取消快捷键问题 以及 shift按键关闭CapsLock问题
- python校园失物招领系统毕业设计开题报告
- ActiveMQ——消息的生产和消费
- 火山引擎云原生大数据在金融行业的实践
- 阿噗啊噗服务器维护,这些App我能笑一年!阿噗整理的20个奇葩App,没玩过你就OUT了!...
- 织梦文章发布 html仅动态,织梦dedecms采集文章后导出为仅动态的解决方案
- win2008找不到无线网络
- NLP模型集锦----pynlp