笔记-uni-app入门到实战 以项目为导向 掌握完整开发流程

总结所学

uni.getSystemInfoSync //同步获取设备信息

// #ifndef APP-PLUS||H5 //h5不会编译下面这段话

let menuButton = uni.getMenuButtonBoundingClientRect();//获取微信胶囊信息

插件icons

scoll-view组件

引用数据库 const db = uniCloud.database()

使用get,拿到数据。返回给客户端

await db.collection('user').doc(user_id).get()

客户端调用云函数

uniCloud.callFunction{name,data:dataObj}

封装数据请求

  需求:this.$api.云函数名({参数}).then

封装顺序 云函数=》$http=>call_function.js=>call_list=>mian $api

field能筛选请求结果。flase:不要 true:只要

  const res= await	db.collection('article').field({
	   content:false
   }).get()

聚合 比更加强大

  db.collection('article').aggregate().martch({}).project({}).end()
    //martch:只选取有该字段的数据块  clasify:前端开发        
    //project 与field一样
    
   // 加载更多功能
        .skip(pagesize*(page-1))   //跳过多少数据,在客户端page每次都+1
                .limit(pagesize)    //限制多少数据

懒加载数据,给数据加缓存。

插件:loadmore

5,因为vue特新,往listCindexatchData里面加的是[],引用类型,并不会触发响应式。
这时需要用$set:通知页面,数组或对象发生了变化,要求刷新页面
this.$set(‘要改变的数组或对象’,key或index,要修改的内容)

this.$forceUpdata()//强制更新

const cmd = db.command command为数据库操作符

let dbCom=null
	if (art_likes_ids.includes(article_id)) {
		dbCom= cmd.pull(article_id)
	}
	else {
		dbCom= cmd.addToSet(article_id)
	}
	await db.collection('user').doc(_id).update({
		article_likes_ids:dbCom  //为article_likes_ids添加和删除数据
	})

通过**upload**更改指定数据

定义聚合的操作符
const $ = db.commamnd.aggregete

添加字段

.addFields({
	is_like:$.in(['$_id',art_likes_ids])//添加字段,诺_id在art_likes_ids中存在返回ture
})

加提示

uni.showLoading()  
uni.hideLoading() 
uni.showToast({
        title:
        icon:    
})

input框发送请求,需添加个延时

搜索功能,匹配题目与val’相关的数据

.match({
		title:new RegExp(val)  //正则
	})
  • - uni.navgateTo  :打开新页面自己不关闭
    - navback:返回之前的页面,如果之前没有进入过主页,那么也返回不回去
    - uni.switchTab:可以
    

把历史存放到本地

  histroy:uni.getStorageSync('histroy')||[] //存在是获取,不存在给个[]         
  		 set          
 		 remove

添加字段

addFelds({
	current :$.in(['$_id',$.ifNull([userInfo.label_ids,[]])])
	//ifNull:当第一项为空,则给个空数组
	//$_id:当前项的_id,相当于遍历
	//_id是否存于在用户的labelids,存在返回true,不存在为false
})

aspectFill:保持纵横比缩放图片,只保证图片的短边能完全显示出来

内容预加载navgatato
要把数据转化成String,通过url传递。
"...?params="+JSON.stringfy()//传参注意长度

:固定定位要加背景颜色的
bug:给icons添加阻止冒泡会报stopPropagation未定义的错:解决:将事件给父元 素

富文本插件 u-parser
弹出插件popup

await db.collection('article').doc(artcle_id).update({
		comments:dbCmd.unshift(commentObj)//把数据放进comments里第一个
	})
.unwind('$comments')   //拆分	
 	.replace('$comments')   // 将comments作为根节点

bug:当设置flex-diraction:column , 元素依然时block元素,为了让容器包裹字体,要给字体在报裹一层,把外面那层设置成flex

使用递归组件
在data外面,需要添加一个name值,与组件名一样
name="comment"

基础知识

条件编译

  #ifdef H5 || MP-WEXIN
  #endif

css方面

​ page: 等同body

​ 使用单位: px, rpx(响应式 屏幕宽 = 750rpx) , rem ,vh,vw

​ 建议flex布局

生命周期

​ 应用生命周期

​ onLauch , onshow , onhide

​ 页面生命周期

​ onload: 监听页面加载

​ onready : 页面加载完成

​ onshow: 页面页面显示

​ onhide : 隐藏

​ onUnload : 页面卸载

​ 组件生命周期

​ beforecreated : 实例初始化后调用

​ created:实例创建完成

​ beforemounted : 挂载开始之前被调用

​ mounted: 挂载到实例上被调用

​ beforeUpdata: 数据更新时调用 , 虚拟dom打补丁之前

​ updata:由改变data造成 虚拟dom打补丁重新渲染 . 这之后被调用

​ beforedetory:实例销毁之前被调用

​ destory : 销毁调用, 调用后, vue实例指示的所有东西都会解绑, 事件监听器都会被移除, 所有的子实例也会被消除

项目

首页功能

easyCom:可以不用引入组件就能使用,要目录名与组件名相同

小bug:一开始没有给view加宽,默认宽是100%。当加上position:flex时,会缩小到内容的宽度

动态的style(数据绑定),要加{}

导航栏:小程序调试

1,给个高度占位,对顶部状态栏
2,不同设备的状态栏高度不一样,用

  `uni.getSystemInfoSync   //同步获取设备信息`

3,动态获取导航栏高度,获取微信胶囊的位置。
bottm:胶囊的底部到屏幕顶端的距离。top:胶囊顶部到屏幕顶端的距离。
那么=》
状态栏高度= (bottom - 状态栏高度)+(top-状态栏高度)
bug:内联式style里,margin-right要加双引号,才不报错。{}里的规范

	// #ifndef APP-PLUS||H5   //h5不会编译下面这段话
				let menuButton = uni.getMenuButtonBoundingClientRect();
				console.log(menuButton);
				this.navHeight = menuButton.bottom - this.statusBarHeight + (menuButton.top - this.statusBarHeight);
				this.marginSearch = menuButton.width;
				// #endif

4,h5无端没胶囊API,会报错。=》条件编译

字体图标

安装使用hbuild里的插件icons

tab栏

使用scoll-view组件。
bug:scoll-view里,别直接写item,外面套一层。 item上写flex没有用,不知道为什么

初始化tab栏中的数据

1,创建云函数
2,引用数据库 const db = uniCloud.database()
3,使用get,拿到数据。返回给客户端

await db.collection('user').doc(user_id).get()

4,客户端调用云函数

uniCloud.callFunction{参数}

5,接受到的数据,传给子组件

封装数据请求
  1. 再common里创建这个封装函数,里面返回个promise对象,把原始请求函数丢进去。
  2. export 导出这个函数再main.js中引入,绑定再实例上,即可在组件中使用为方便维护,把export defalt的内容单独弄在另一个js文件中,原来的全部用export 单个导出。
  3. 从代码量并没有得到改变,pormise重复使用,再把返回的promise封装成$http函数
  4. 每增加一个云函数请求,都要在list里面添加导入导出很麻烦。=》批量导出 require.context(目录相对路径,是否查询子目录,查询文件后缀) 。.keys可取到
    bug:export导出已经声明的变量时,要加{};而export defaut不用加,然而 export 依然出错,还是export default吧
  export {module}//然而 export 依然出错,还是export default吧
    // export default module
选项卡切换

每个添加点击事件,把index传给函数,添加activeIndex,activeIndex=index
添加:

<view :class="index===active_index ?  'activeStyle' : '' " @click="showActive(index)" v-for="(item,index) in labelData"
			 class="scroll-view-item_H">{{item.name}}</view>
卡片视图实现

下方添加scroll,实现样式,封装组件,添加插槽,加上card 完全看不懂 在不懂页面布局时,可以给每个元素加个大点的边框
添加card,里面加img,标题,内容
大bug:全写英文竟然直接撑开盒子,不换行
多行文本溢出显示代码

.box {
    width: 100px; 
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
多图模式

1,复制一份单独,把标题放图片上面
2.,新建个类,写多模模式的样式,层叠掉单独模式的
3,创建大图模式
4,v-if,不同模式下显示不同的结构。模式由父组件传进来
bug:图片外需加个div,不然会出现样式冲突

实现内容切换,swiper
选项卡与内容联动

1,利用$emit,实现父子传值
2,swiper的current属性和chengr事件

获取数据渲染

field能筛选请求结果。flase:不要 true:只要
const res= await db.collection(‘article’).field({
content:false
}).get()

数据分类

1,切换tab,触发change事件,将当前tab的name,传递给云函数,进行筛选聚合

      .aggregate().martch({}).project({}).end()
        //martch:只选取有该字段的数据块  clasify:前端开发        
        //project 与field一样

bug:调用云函数传参数,要用{}包裹

懒加载数据,给数据加缓存。

(以前是把数据赋值给单个的数组拿去渲染,每次赋值新值都是覆盖以前的旧值,导致页面滑动到下个页面会直接显示上个页面的值,过一会才刷新)(加缓存的目的是把一个数组变成多个数组,每个页面对应一个数组)
1,data里声明个listCatchData:{}
2,去掉list赋值,改成listCatchData。通过curent进行缓存,在geiList传进来
3.tab值可能来不及拿到,因为在create里调用,而在父组件请求数据。加个监听
4,改下结构中的 :list=‘listCindexatchData[index]’
5,因为vue特新,往listCindexatchData里面加的是[],引用类型,并不会触发响应式。
这时需要用$set:通知页面,数组或对象发生了变化,要求刷新页面
this.$set(‘要改变的数组或对象’,key或index,要修改的内容)

处理遗留问题
添加全部
1.给tab添加个“全部”,
2,把‘全部传递到云函数,对数据进行过滤’
每次滑动都会请求数据。以经加载过的数据就不要请求了
change中加个if

下拉加载更多

1,下载插件:loadmore
结构赋值的一种写法,给默认值
const {
a,
b=2 //如果’…‘中没有b,则默认为2
} = …

2,给云函数添加,page,pagesize。
.skip(pagesize*(page-1)) //跳过多少数据,在客户端page每次都+1
.limit(pagesize) //限制多少数据

3.给scroll,添加底部事件

4,定义page,pagesize,触发底部事件page++,调用云函数

5,客户端接收数据时,赋值覆盖掉了老数据。应该push到老数据后面。 listcatchdata一开始没有值,所以在后加个 || [] ,或者空数组
let oldres = this.listCatchData[current] || []
oldres.push(…res)

6,这时候渲染的数据还是有问题,原因在page,当切换tab时需要将page重置,但这样依然会有问题。会好时想上面一样加个缓存loading,把多个数组存在{}对象里面。首次获取数据,需要初始化loading。
bug: {}:并不是falsely
’‘、0 、undefined是falsely

7,处理loading,当返回数据为0时,再次向上面的思路,通过 s e t 重 新 赋 值 , 为 每 个 页 面 设 置 ’ n o m o r e ‘ 。 / / t h i s . l o a d [ c u r r e n t ] . l o a d i n g = ′ n o m o r e ′ 直 接 这 中 赋 值 也 可 以 , 但 不 能 加 r e t r u n , 需 要 借 助 下 set重新赋值,为每个页面设置’nomore‘。 // this.load[current].loading='nomore' 直接这中赋值也可以,但不能加retrun,需要借助下 setnomore//this.load[current].loading=nomoreretrunset

8,此处nomore还是加载不出来,遇到这情况,再set下,加上
this.$forceUpdata()//强制更新

9,有个bug,没有set page ,导致请求,page空的,又会重0开始请求到数据

10,当load==’nomore‘,应该不要再去请求数据了。需要把activeindex重新赋值下,因为一直没有同步。

11,一个问题,当文章小于5时,不会触发下拉刷新,也就不会改变loading。需要给loadding组件加个if,大于5或=0时才显示
bug:当重新进入相同页bug面,会再次获取数据。解决:再赋值时,加个if判断,诺该页面不是undefined,则return
不能用上面的,return。而是把请求数据放if里。思路要变通
// 当重新进入相同页面,会再次获取数据。解决:再赋值前,加个if判断,诺该页面不是undefined或list长度为0,则请求数据

		if (!this.listCatchData[this.swcurrent]||this.listCatchData[this.swcurrent].length===0) {
			this.getArtcle(this.swcurrent)
		}
收藏功能

1,在评论右侧添加个icons
2,需要单独作成组件,不然每次点击都会去刷新整个页面,耗费性能
3,添加click事件,并阻止冒泡
4,添加个更新收藏的云函数,上传userid和atcleID
可以右键,点击配置参数,可以测试
5,通过upload更改指定数据,command为数据库操作符
cmd.addToSet(id) //把文章id添加到数组中
pull(id) //删除

6,需要拿到用户数据收藏文章的数组,通过include判断,是否包含id,没有则addToSet,有则pull。可用null作为中间件来传值
// 更新
let dbCom=null
if (useInfo.data[0].article_likes_ids.includes(article_likes_ids)) {
dbCom= cmd.pull(article_likes_ids)
}
else {
dbCom: cmd.addToSet(article_likes_ids)
}
await db.collection(‘user’).doc(_id).update({
article_likes_ids:dbCom
})

bug:不能把if写{}里面,因为里面只能写参数
7,请求云函数
8,红心切换
bug:里面得加单引号,type要动态绑定 :type=“is_heart ? ‘heart-filled’ : ‘heart’”

9,刷新了红心也就没了,这时要在云函数的返回数据追加一个is_red的字段。通过聚合里的 .addFelds
10,定义聚合的操作符

  const $ = db.commamnd.aggregete

11,获取用户数据,拿到收藏数组,需要添加参数id,运行配置中配置下参数,使用addFeleds,测试,

.addFields({
	is_like:$.in(['$_id',art_likes_ids])//添加字段,诺_id在art_likes_ids中存在返回ture
})

12,所以的接口都要传userid,在$http里,顶一个{},里面加上id,把原来data解构在里面
13,客户端请求到islike赋值给本地
14,加提示:

uni.showLoading()  
uni.hideLoading() 
uni.showToast({
        title:
        icon:    
})

2搜索页功能

搜索页导航栏修改

1,在pages新建页面,点击搜索跳转到该页面,去掉原始导航,把navbar写上去
2,需要区分下navbar在两个界面的不同样式,传一个bool值,用v-if,在不同页面展示不同的navbar
3,写下面的搜索内容样式
在page加flex ,是要把内容撑开,跟加100%是一个意思
4,添加没有搜索历史,v-if,当数据为空显示
5,导入vuex,引入vue和vuex

6,点击添加历史记录,就加个一条

7, 添加搜索结果,只有input不为空时才显示,添加list组件

​ bug:scoll出现显示异常,在.home_list上加和overflow:hidden得到解决

8,onload和输入时和请求数据,此时是page页面

9,每次输入都会发送请求,需添加个延时

		// 添加延时
			if(!this.flag){   //开始为定义,flag为undefined
					this.flag=true   //下面的定时器没结束前,就进不来if
					setTimeout(()=>{
						this.getArtcle(val)
						this.flag=false
					},1000)
				}

10,建立搜索云函数,只需加个match,new个正则

11,点击内容,保存搜索记录。点搜索记录,能搜索。这里用到组件间的双向数据绑定

在调用的子组件上,不可写@click,会被以为是自定义函数

12,添加没有搜索到相关数据

13,loading

搜索历史数据持久化

1,返回首页

        • uni.navgateTo :打开新页面自己不关闭
        • navback:返回之前的页面,如果之前没有进入过主页,那么也返回不回去
        • uni.switchTab:可以

2,清空历史

3,把历史放到本地缓存

bug:getStorage默认为异步,要改成同步,不然会报错

       histroy:uni.getStorageSync('histroy')||[] //存在是获取,不存在给个[]         
  		 set          
 		 remove

3.标签管理页面布局

​ 1,创建页面

2,获取标签数据

​ 1使用聚合。添加用户表.。主要是看label表的个id,是否存于在用户的labelids。因为一开始没有labelids,所以全为false

​ 2给label添加字段

addFelds({
	current :$.in(['$_id',$.ifNull([userInfo.label_ids,[]])])
	//ifNull:当第一项为空,则给个空数组
	//$_id:当前项的_id,相当于遍历
	//_id是否存于在用户的labelids,存在返回true,不存在为false
})

​ 3,返回指定的label项,前端传一个type,如果为all返回所以label,否则返回current为true的

.match({
	current:true
})

3.编辑标签页

​ 1.编辑和完成要切换,所以要加个中间变量isedit

​ 2.获取数据渲染

​ 3.切换编辑完成

​ 4.标签上移下移

4.上传标签页数据

​ 1.核心思路,主要时根据labeid由没有再ids里面,所以只要拿到“我的标签”里的所有id就行

​ 2。创建云函数,接收一个labelid数组,利用updaat跟新数据的数据

​ 3,用户点击完成时,触发调用云函数

​ 4,加个loading

​ 5,自定义事件来同步

uni.$emit()

4.详情页

1,界面实现

​ 只有给了图片宽高的时候才由这种mode,给图片宽高100%也是给了宽高,跟父元素一样罢 了aspectFill:保持纵横比缩放图片,只保证图片的短边能完全显示出来

2,内容预加载

​ 1,因为在首页已经拿到了一部分数据,为了性能,直接把则部分数据给详情页用

​ 2,要把数据转化成String,通过url传递。

        "...?params="+JSON.stringfy()//传参注意长度

​ 3,直接在onload()能接受到数据,再用JSON.parse转回格式

3,详情数据初始化

​ 1,添加云函数,需要添加字段addFields,是否关注,是否收藏,是否点赞

​ bug:固定定位要加背景颜色的

​ bug:给icons添加阻止冒泡会报stopPropagation未定义的错:解决:将事件给父元 素

		:{'[$_id',kkk]}
		match({
			_id:artcleId  //只匹配该id的文章数据
		})
		.project({
			不要评论
		})

​ 2,添加个富文本插件 u-parser

​ 3,添加个弹出插件popup

5.评论

​ 1,创建提交评论的云函数,里面包含很多字段,用updata来提交,不能再云函数里面直接获取时间,拿到作者信息通过user表,提交到article中;需要添加随机id和时间搓

await db.collection('article').doc(artcle_id).update({
		comments:dbCmd.unshift(commentObj)//把数据放进comments里第一个
	})

​ 2,客户端提交数据,写好样式

​ 3请求评论。因为请求到的数据里多了个comments字段,需要切割,再把comments做成根节点,相当于把comments变成data

​ bug:总忘记加await,直接return res 可以, 但加了{}就返回的空数据了

 	.unwind('$comments')   //拆分	
 	.replace('$comments')   // 将comments作为根节点

​ 4渲染数据

​ 5回复

​ 1,添加回复按钮和回复区域,回复区域就根评论是一样的,这边就自己调用自己的组件,用v-for判断回复数,不然会陷入死循环

​ bug:当设置flex-diraction:column , 元素依然时block元素,为了让容器包裹字体,要给字体在报裹一层,把外面那层设置成flex

​ 2,定义事件,拿到评论id,传给云函数,2个参数:文章id 评论id

​ 3,云函数分两种逻辑:1,评论id===“,就是评论,把回复内容设为[]以防万一 2,没有则是回复

​ 4,获取该文章的所有评论,,

​ 5.获取评论索引 。根据id, 拿到索引是为了下面更新 索引对应的评论

  findIndex(item=> item.commentid = commentid)

​ 6.获取作者信息,得到作者名,是为让客户端知道回复给谁

  find(item=> item.commentid = commentid)
  name=info....

​ 7,为了知道回复的是哪条评论,然后在要上传的obj中加个to=作者名

​ 8,更新回复信息: 其实就是根据索引,跟新了改变了的回复数组,在upload整个评论

   obj={    //跟新数组对象的一种方式
   	[index]:{
   		replys:dbCmd.unshift(obj)  //把添加了to的obj传给replys数组
   	}
   }
   uplaod(obj)  //更新该评论
   
   相当于  跟新数组  obj = {
   							arr:[{name;1},{name:2}]
  							 }
    updata({
    	arr:{
    		0:{
    			name:3
    		}
    	}
    })

​ bug:当实在找不出bug,给全问都上个注释看看,记得单词写正确单词,少写了个字母会死人

​ 9,使用递归组件,在data外面,需要添加一个name值,与组件名一样

     name="comment"

​ 10,点击发布,刷新页面,重新请求下评论ps

​ 11,回复”回复“,

​ 1,因为评论和回复都是同一个组件,所以要区分是点击了谁的回复按钮。所以,给回复组件加个:reply=true ,在评论组件props里填个 reply{default:false } ,这样父组件detail那边就不要写个:reply=false了,因为默认为false

​ 2,给回复按钮的click事件,跟换参数,把reply加进({compopents,is_reply:reply}) ,这样就知道点击的是哪个回复按钮了

​ 3,判断主回复和子回复:评论里有一个coments_id,回复则因该有两个id,1是评论id coments_id; 2是 回复id reply_id

				if(comment.is_reply){
				//改个名字,改成reply_id
					comment.comments.reply_id = comment.comments.comment_id
				//上级的评论id
					comment.comments.comment_id=this.item.comment_id
				}

​ 4,回到更新评论函数,如果reply为true,要添加一个reply_id和is_reply的字段,测试一下,点主回复一个id,子回复2个id

​ 5,处理云函数,里面多加两个参数reply_id和is_reply,通过is_reply判断主回复和子回复,子回复拿到子回复的作者信息,主回复拿到主回复的作者信息

	//回复给谁    拿到索引是为了下面更新 索引对应的评论
		const index = comments.findIndex((item) => item.comment_id === comment_id)
		// 子
		if(is_reply){
				// 拿到此条回复的作者名
			const commemt =comments[index].replys.find((item) => item.comment_id === reply_id)
		}else{
			// 主
			// 拿到此条评论的作者名
			const commemt = comments.find((item) => item.comment_id === comment_id)
		}
		const commemner_name = commemt.commenter.name

		// 添加字段 被回复的名字
		commentObj.to = commemner_name

​ 6加个回复样式,当reply为true,v-if和v-else

​ 7上传成功后要清空form,不然发布也会变成回复

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值