使用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,引入文件 测试图标使用

    
    		
    
    

引入css动画库

  • 下载animate.css

  • 引入animate.css

  • 测试css动画库的使用

     
    			
    				点击效果
    			
    		
    

设置全局属性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

  • 测试

    
    
    
    
    
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gyz1MrF9-1649380676447)(uniapp社区交友开发.assets/image-20220323154220758-16480213421241.png)]

计算属性

  • 常用于数据的格式化

  • computed

  • 测试运用

    
    
    
    
    
    
    

首页开发

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库

  • 列表开发

    
    		
    			
    			
    				
    				
    				
    					昵称
    					2022-3-15
    				
    			
    			
    			
    				关注
    			
    		
    		
    		
    			哈哈哈
    		
    		
    		
    			
    		
    		
    		
    			
    				
    				
    			
    			
    				
    				
    			
    			
    				
    				评论
    			
    			
    				
    				转发
    			
    		
    	
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-daoAQo1N-1649380676447)(uniapp社区交友开发.assets/image-20220323193232107.png)]

封装列表样式

  • 继续使用free.css封装代码

    
    		
    			
    				
    				
    					
    					
    					
    						昵称
    						2022-3-15
    					
    				
    				
    				
    					关注
    				
    			
    			
    			
    				我是标题
    			
    			
    			
    				
    			
    			
    			
    				
    					
    					
    				
    				
    					
    					
    				
    				
    					
    					评论
    				
    				
    					
    					转发
    				
    			
    		
    	
    
  • 封装本项目公共css(common.css 记得引入)

    .bg-main{
    	background: #FF4A6A;
    }
    
  • 封装成组件动态渲染

    
    			
    		
    
    import commonList from '@/components/common/common-list';
    
    components:{
    			commonList
    		},
    
    
    				
    					
    					
    						
    						
    						
    							{{item.username}}
    							{{item.newstime}}
    						
    					
    					
    					
    						关注
    					
    				
    				
    				
    					{{item.title}}
    				
    				
    				
    					
    				
    				
    				
    					
    						
    						{{item.support.support_count}}
    					
    					
    						
    						{{item.support.unsupport_count}}
    					
    					
    						
    						{{item.comment_count}}
    					
    					
    						
    						{{item.share_num}}
    					
    				
    			
    
    export default{
    		props:{
    			item:Object,
    			key:Number
    		}
    	}
    

全局分割线开发

  • 封装组件divider.vue

    
    	
    
  • 引入全局组件(分割线常用)

    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事件 (头像、关注、标题、图片、点赞、踩)






优化列表组件-关注功能

  • 关注按钮的显示
  • 子组件触发父组件方法更新isFollowz

					关注
				

follow(){
				// 触发父级follow方法
				this.$emit('follow',this.index);
			},



methods: {
			follow(index){
				this.list[index].isFollow=true;
				uni.showToast({
					title:'关注成功'
				})
			}
		}

优化列表组件-顶踩功能

  • 绑定class渲染
  • 方法参数传递
  • 父方法实现

					
					{{item.support.support_count>0?item.support.support_count:'支持'}}
				

doSupport(type){
				this.$emit('doSupport',{
					type:type,
					index:this.index
				})
			}



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导航开发

  • 顶部导航选项卡

    
    			
    				{{item.name}}
    			
    		
    
    				tabIndex:0,
    				scrollInto:'',
    				tabBars:[
    					{
    						name:'首页'
    					},
    					{
    						name:'体育'
    					},
    					{
    						name:'军事'
    					},
    					{
    						name:'热点'
    					},
    					{
    						name:'新闻'
    					},
    					{
    						name:'娱乐'
    					},
    					{
    						name:'电竞'
    					},
    					{
    						name:'国际'
    					},
    					{
    						name:'国家'
    					}
    				],
    
    
    doTab(index){
    				this.tabIndex=index;
    				this.scrollInto='tab'+index;
    			}
    
  • 下面容器能做到切换与导航栏一样,容器也能拉取

    
    			
    				
    					{{i}}
    				
    			
    		
    
    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);
    		},
    
  • 列表显示

    
    			
    				
    					
    						
    						
    					
    				
    			
    		
    
    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;
    			},
    

上拉加载组件开发

  • 静态的开发

    
    					
    						
    						
    						
    					
    					
    						{{item.loading}}
    					
    				
    
  • 触底函数的开发

    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 并引入

    
    
    
    
    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组件 全局引入

    
    				
    
    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'
    			})
    		},
    
  • 搜索历史开发

    
    		搜索历史
    		
    			
    				{{item}}
    			
    		
    	
    
  • 监听导航输入

    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,遍历,优化搜索历史与列表存在问题

    
    		
    		
    	
    
    import commonList from '@/components/common/common-list.vue';
    
    export default {
    		components:{
    			commonList
    		},
    }
    
  • 点击搜索历史的事件

    
    				
    					{{item}}
    				
    			
    
    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依赖, 根据官方文档调用

    
    			
    				所有人可见
    			
    			
    		
    

textarea组件使用

  • utextarea, 动态绑定