项目效果预览:
如果在写的过程中出现了
401状态码,请将local Storage中的token删除,重新登录即可解决。因为token的有效期是2小时,2小时候需要重新生成token, 接口才能正常返回数据
1-项目初始化
了解项目中每个大的功能模块中的小功能
首页
首页顶部搜索
文章详情页
登录和退出功能
我的个人中心
模块介绍
01:了解了5个大的功能模块,开始了解项目的流程示意,
1:使用 Vue CLI 创建项目
2:加入 Git 版本管理
3: 调整初始目录结构
4: 导入图标素材
5: 引入 Vant 组件库
6: 移动端 REM 适配
7: 关于 .postcssrc.js 配置文件
8: 封装请求模块
使用VueCLI创建项目
02:了解了项目的功能,和实现流程,开始使用vue cli命令窗口创建创建项目,看图
加入Git版本管理
03;用vue cli 创建了本地项目,开始创建远程github项目,创建远程仓库成功后,连接本地仓库,更新远程仓库
调整初始目录结构
重置文件结构和内容
04:根据图片,清理不必要的文件,重置vue主页面,测试重置是否成功,显示正常表示成功
主分支本地和远程更新
提交本地主分支,更新远程主分支
导入图标素材
05:完成了项目操作,开始完成将svg图片用inconfont转换为字体图标,以及使用方法
使用inconfont把ui准备的svg图片转换成图标,并把样式拷贝到icon.less在index.less中导入,vue页面中测试,图标成功显示
引入Vant组件库
06:完成了图标的制作和使用,开始下载和使用vant组件测试框架是否安装成功
1-2-3:下载并导入
4-5-6:import是必须导入在页面前面的,在页面测试了vant的组件,成功显示。提交本地仓库,记录操作。
移动端REM适配
07:学习和使用了vant,开始使用第三方插件完成页面rem适配 【!注意,一定停掉,再重新 npm run serve, 否则不生效!】
1-2-3:安装和导入动态设置rem基准值的插件
4-5-6:下载px转换rem插件,并在.postcssrc.js里面配置根字体基准值,
移动端REM适配(关于PostCSS配置文件)
08:完成了rem页面适配功能,开始对.postcssrc.js分析,让它在设置根文字大小时,按需渲染根基准值。
封装请求模块
09:完成了文字的基准值设置和了解后,开始完成配置axios请求,设置请求的根地址。
1-2:下载并创建request.js配置axios请求,配置请求的基准路径,并导出这个reques请求对象
模块总结
10:配置了axios的根请求地址,开始独一该项目创建阶段的总结,其实就是把md中的流程示意来了一遍复习。
2-登录注册
模块介绍
11:完成了项目出事故中,开始创建login组件,并配置路由,完成页面布局。实现登录基本功能,和登录的状态提示。对表单进行验证,点击发送验证码和倒计时,处理用户的token
创建组件并配置路由
12:了解业务流程后,开始完成login组件的创建和路由配置,默认登录login页面
1:创建组件页面,因为App.vue中,已经有了router-view.所以组件能在页面上展示
2:在router/index.js中配置路由,当请求地址是/login,就使用组件import('@/views/login')就使用该页面作为组件
3:页面效果,/login页面就显示login组件
布局结构
13:创建好login组件页面后,开始完成登录页面的布局
1-2-3:导入navBar组件和From表单组件,@submit触发表单提交事件,native-type="submit"原生按钮。
4:完后了页面表单的基础布局
布局样式
14:完后了页面表单的基础布局,开始完成表单细节样式的优化
1:可以使用slot=left-icon插槽在输入框内的左内侧插入字体图标, 图标可以是自己下载的图标
2:插槽方式二:template #button, 插入一个按钮。
2.1:有的页面样式需要在调试台中找到类名去调试修改样式。
3:完成了表单样式的美化和第三方图标的使用
实现基本登录功能
15:完成了表单样式的美化和第三方图标的使用,开始完成调用接口获取登录的状态
1:在user.js中导入request文件,导出一个login需要携带data参数,
2:在自己的页面中,异步处理函数中接收自己的user表单对象,调用user.js中导出的login方法携带参数发起数据请求,登录成功就打印成功的信息,错误就打印错误的信息。
登录状态提示
01: 完成了表单数据的请求,把登录的状态打印到控制台中了。开始完成登录状态的轻提示
1-2:导入toast组件,在js中调用this.#toast.loading弹出轻提示,设置轻提示的配置参数,message提示的文本,forbidClick:true禁用背景点击,duration一直持续时间。
2.1:使用了第一个toast提示登录中后,开始完成this.$toast.success成功的提示,this.$toast.fail失败的提示信息。
3:页面效果,弹出轻提示提示框,将提示信息提醒
表单验证
02:完成了弹出轻提示提示框,将提示信息提醒,开始完成表单的验证功能
1::rules绑定验证规则,在data中定义验证规则, userFormRules:{mobile:[{ }]}定义了手机号的验证规则
2-3:页面效果,完成了对表单的预验证功能
发送验证码-验证手机号
03:完成了对表单的预验证功能,开始完成提交表单时,触发表单的预验证
1:ref=loginForm绑定表单对象, @submit提交时触发的事件函数,this.$refs.loginForm.validate('mobile')触发表单的验证规则
2:页面效果,点击登录,就对表单中的内容进行了预验证。
发送验证码-使用倒计时组件
04:完成了点击登录,就对表单中的内容进行了预验证,开始完成CountDown倒计时组件
1-2:导入倒计时组件,开始配置倒计时组件:v-if因为data中的isCountDown默认值隐藏的,只有点击的时候会显示,就会显示倒计时组件,:time倒计时时间, format格式化的配置:ss秒, s字符串。 @finish倒计时完成时将倒计时组件隐藏起来。
3-4-5:点击登录时,触发了表单的预验证功能,让倒计时组价你显示。
验证码处理-发送验证码
05:完成了验证码的倒计时功能,开始调用接口完成发送验证码功能
1:接口文档,必须携带mobile电话号码
2:在user.js中配置了sendSms请求接口,里面配置了请求地址,携带了手机号码
3:在login页面中导入解构出了该方法,在点击显示倒计时的时候,调用刚才封装好的sendSms接口,传入手机号码,完成发送验证码功能。如果是429表示接口访问次数受限制,其他通过轻提示,弹出提示信息。
4-5:点击发送验证码和显示倒计时功能
处理用户Token
06:点击发送验证码和显示倒计时功能,开始完成将token储存在store共享数据中,并临时存放在localStorage中。实现持久化。
1:实现该方法的流程示意
2-3:通过setUser接口能返回数据,数据中包含了token和refresh
4: 在store中定义了user属性,属性的值就是获取到的本地储存中的token字符串,并转换为对象,mutations中封装函数,用来把获取到的接口数据拿到,并设置到本地会话中以JSON字符串的形式储存的
5-6:能看到localStorage中已经储存了token信息是以json字符串的,而组件中的数据是对象类型的
封装本地存储操作模块
07:完成了本地会话中的token存储以及token的数据共享,开始完成获取和设置token抽离为一个单独的工具文件。store中只负责调用函数,调用封装的方法实现token储存功能
1:在utils/storeage.js中封装了,并道出了一个常量接收一个函数的返回值,如果是字符串的object类型,需要转换为json字符串, 获取token的函封装,从本地存储中获取到数据,并将数据转换为对象类型,
2:在store中导入并解构出这2个方法,在state中调用获取token的方法,携带参数属性名称。 在mutations中设置token信息,携带token属性名和属性值就是获取到的数据对象。实现token的储存
3-4:页面效果,在localstorage中实现了token的设置储存,在state中完成了token数据共享功能。
关于Token过期问题
08:完成了函数抽离封装,在localstorage中实现了token的设置储存,在state中完成了token数据共享功能。开始了解token的过期问题
1:token2小时有效,refresh_token14天有效
3-个人中心
模块介绍
09:完成了登录页面的功能,开始了解个人中心的业务流程
Tabar4大件的切换,
页面布局: 未登录头部的状态,已登录头部的,宫格导航,单元格导航
处理已登录和未登录的页面展示
用户退出功能
展示用户信息功能
优化设置token
TabBar处理
10:了解了业务流程,开始完成底部Tabar 4大件的切换效果,点击跳转到对应的路由页面
1-2:创建了4个子组件,文件夹和对应的组件页面。
3:创建layout/index.vue用来当做父组件,挂载其他4个子组件,router-view路由占位符, 导入仪tabbar组件,to属性是跳转的路由页面,完成了子组件的挂载和渲染,开始配置路由,这里只是渲染了一个tabbar组件,用来导航用的,它只负责点击跳转到对应的页面,
4;配置路由,当页面请求的是/地址,默认展示的是layout这个父组件,给这个父组件配置children属性,每个子组件都有自己对应的请求路由
5:点击底部的导航菜单,切换子路由页面。
页面布局-顶部未登录
11:完成了底部的导航菜单渲染,点击跳转到对应的路由页面。开始完成注册的头部制作
1:完成了注册头部的css样式布局,点击$router.push('/login')点击跳转到登录页面
2:登录页面左侧添加x关闭按钮,点击关闭按钮,返回到之前的页面
3:设置全局样式,让关闭按钮的颜色为白色
4: 页面效果。点击登录跳转登录页面,点击关闭按钮,返回注册页面
页面布局-顶部已登录状态
12:完成了注册页面的头部制作,和点击跳转登录页面,开始完成用户个人信息的渲染
1-2-3:完成了头像和昵称,编辑资料+头条+关注+粉丝+获赞的制作
在css制作中多使用flex布局,快速完成页面的布局
页面布局-宫格导航
13:完成了个人中心页面的布局,开始完成收藏和历史的页面布局
1:使用宫格插件,:columun-num=2,表示一行2个,i标签用slot使用插槽渲染自定义图标,
2:页面效果,完成了收藏和历史的页面样式布局
处理页面显示状态
14:完成了收藏和历史的页面样式布局,开始完成退出登录和登录功能的伪开发
1-2:通过v-if如果有token,就显示个人中心页面,如果没有token就显示登录注册页面,
3-4:如果页面中{{$store.state.user}}存在就显示我的, 不存在就显示未登录
5-6:页面如果有token就可以点击退出登录,退出登录,点击登录可完成登录功能,点击关闭按钮,可以页面退回
用户退出
15:实现了点击退出功能,开始完成点击真正的退出功能
1-2:点击事件中弹出对话框,this.$store.commit( )调用setUser函数,将user给null清空,实现退出功能
3-4-5:点击完成弹出对话框,将localStorage中的token给清空,实现了退出功能
展示当前登录用户信息
16:实现了点击退出功能,开始完成封装请求,页面调用请求数据获取个人数据,在把用户数据渲染到页面上
1-2-3:在api/user.js中封装获取用户信息的函数,需要设置headers将Authoriazation设置,
在layout/index.vue中引入并解构出该方法,在data数据中定义空对象,在create如果用户已经登录调用函数的封装,
函数封装中调用请求方法,将数据请求回来,并用data接收,在把data赋值给this.userInfo,如果发生错误就提示用户失败,
在把请求回来的数据渲染到自己页面的元素中,实现了用户信息的渲染
优化设置Token
17:完成了用户数据的请求和渲染,开始完成将token设置在请求拦截的时候,让每个请求都能拿到token
1:axios在github中的请求拦截和响应拦截的代码示例
2:将请求拦截写在request中,设置根请求地址后,开始设置请求头携带Authoriazatuion字段,其实就是代码粘贴过来修改了一点,如果用户存在,就给用户设置请求头
4-首页-展示文章列表
页面布局-头部导航栏
01:完成了个人中心的功能,开始完成首页的顶部的搜索框布局
1-2:使用nav-bar和button,slot是插槽,round是圆角,icon图标。
max-width:unset, 取消设置最大宽度,完成了首页顶部搜索的样式布局
处理文章频道列表-使用Tab标签页组件
02:完成了首页顶部搜索的样式布局,开始完成顶部tab栏切换的功能
1-2:tabs标签页,v-model数据绑定的当前高亮,amimated点击切换动画,swipeable轮播图左右切换,data中的active:0, 表示默认第一个高亮
3:页面样式,完成可tabs切换的效果
处理文章频道列表-样式调整(基础样式)
03:完成可tabs切换的效果,开始完成标签页面的基础布局
1-2:/deep/深度影响,可以影响子元素的样式, !important提高权重
3:页面效果,完成了tab栏的布局样式
处理文章频道列表-样式调整(处理汉堡按钮)
04:完成了标签页面的基础布局,开始完成右侧汉堡包布局
1-2-3:在tabs右侧插入插槽,placeholder是最后一个元素,是为了占位,flex-shrink是为了不参与flex布局平分,单独设置自己的宽高,
汉堡包的左侧边框线是用一张图片做的,在真机中才可以看见,
4:完成了tabs的右侧汉堡包和底下的占位盒子的布局
处理文章频道列表-获取展示数据
05:完成了tabs的右侧汉堡包和底下的占位盒子的布局,开始完成tabs标签的数据获取
1:在api的user.js中封装getUserChannels获取tab的接口函数,
2:在home中导入并解构出来该方法,在data创建空数组用来接收空数据,在created中调用事件函数,函数中调用接口函数,将请求到的数据,赋值给tabs标签页空数组。
3:拿到频道列表的数据,开始在tab中渲染,:title标签页的名称,v-for循环数组,渲染多个独立的tab标签,
4:完成了页面标签的名字渲染,并拿到了用户判断列表的数据
文章列表-创建列表组件
06:完成了页面标签的名字渲染,并拿到了用户判断列表的数据,开始完成完成列表页面的创建
原理: 就是常见也就卖你article-list.vue子组件,用来渲染所有的文章列表,它去父组件home中拿到数据,在自己页面中操作而已
1:原理分析,共用一个,节省请求和性能
2:创建子组件,,data中创建channel频道对象,用来接收频道的数据
3:因为接口中返回来了数据,通过:channel接收频道所有的数据,传递了给了子组件
4:此时子组件拿到了数据,可以看得出,不同的tab中渲染了不同的频道
展示文章列表-使用List列表组件
07:tabs共用了一个组件渲染频道,该文章列表组件接收到了数据,开始完成list列表组件的布局使用
1:导入list组件,v-model加载的状态, :finished加载的结束状态,finished-text结束的文本,@load触发的加载事件。
2:将底部的4大件,用底内边距把list组件给撑开,要不看不到加载提示信息。
3:完成了使用list组件,完成列表的样式布局
请求获取数据
处理响应结果
08-09:完成了使用list组件,完成列表的样式布局,开始完成lsit列表的数据渲染,
1:在api的article.js中封装getArticle接口函数,
2:在hoem中导入并解构出来,在自己的函数中调用接口,携带频道ID,时间戳,是否包含置顶,传递给后台,请求到的数据给用展开运算符push到list数组中,实现了获取到所有list列表数据,并把获取到的时间错给赋值重新设置,关闭加载更多。如果请求失败,就下拉显示请求失败。
3:那拿到的数据,在cell表格行中渲染展示,:title列表行的标题信息
4:完成了列表页面的数据渲染。
请求失败的处理
10:完成了列表页面的数据渲染,开始完成文章列表list的参数配置
1-2-3-4::errpor.sync能捕获到错误信息,error-text错误提示信息。
error默认的失败提示状态,只有在catch发生错误的时候,才会触发this.error=true,显示错误提示状态
5:当下拉加载列表数据发生错误的时候,提示请求失败,
下拉刷新
11:完成了list下拉加载失败的提示信息,开始完成下拉列表刷新数据的功能,
1;使用pull-refresh元素包裹list数据,就能出发该组件的下拉刷新的功能。v-model下拉刷新的加载状态, :success-text下拉提示的文本信息,:success-duration下拉加载的时间,@refresh下拉刷新触发的事件函数。
2:配置下拉参数,下拉的loading的状态默认是false, 提示的文本信息,默认是刷新成功
3:如果下拉刷新失败,提示刷新失败,关闭刷新图标
4-5:刷新失败,刷新成功的话,就加载了10条数据。
头部固定定位
12:完成了下拉list列表刷新数据列表的功能。刷新失败,刷新成功的话,就加载了10条数据。开始完成home首页页面布局的调整修改
1:顶部搜索框fixed固定定位,
2: 内容容器区域标签栏设置顶内边距,把自己撑下来,和底部也撑开。
3:tabs区域设置fixed固定定位,left0, right0,是为了元素不被撑大。
页面效果,完成了home页面的布局,顶部搜索框和底部的4大件,布局的修改
记住列表的滚动位置
13:完成了home首页的样式调整,开始完成切换tab页面,滚动的时候不会影响其他列表页面的滚动
1-2:给article-list组件设置height:79vh, overflow-y: auto每个列表页面出现自己的滚动条,vh看图解释,目的就是不让body去滚动,让list产生自己滚动条,实现滚动不影响其他页面的功能
3:页面效果:完成切换tab页面,滚动的时候不会影响其他列表页面的滚动位置
文章列表项-准备组件
14:完成切换tab页面,滚动的时候不会影响其他列表页面的滚动位置,开始完成每个文章列表的数据渲染
1:子组件中接收一个article文章对象,
2:home页面导入该组件,并配置为自己的子组件,在自己页面中挂载,用来渲染数据。
3-4:挂载article-item中遍历数据, :artcile接收文章对象,
5:实现了子组件接收数据在页面中渲染,当做文章列表在文章列表中渲染
展示列表项内容
15:实现了子组件接收数据在页面中渲染,当做文章列表在文章列表中渲染,开始完成插槽方式把数据渲染
1:在文章列表页面,用cell单元格渲染列表数据, slot插入文章标题, slot插入描述,在div盒子中遍历图片数组,实现数据的3张图片的数据获取, van-image中把图片渲染。
2:如果是一张图片,直接在img中渲染, 判断图片的类型,如果是单独一张的图片,将图片渲染在右侧。
3-4:完成了文章列表的数据渲染,和3张图片以及一张图片的渲染
样式调整
01:完成了文章列表的数据渲染,和3张图片以及一张图片的渲染,开始完成文章列表中的样式布局
1:完成一张图片的样式布局,flex: unset不参与flex布局。
2:$:not(:last-child)不包含最后一张图片
3:van-multi-ellipsis最多显示2行简介,多余省略。
4-5:单张和多张图片的样式布局
关于第三方图片资源403问题
02:完成了列表图片布局的处理,开始完成第三方图片的不显示问题
直接在public中导入meta标签,no-refrerr不使用引用声明,就能解决一大部分图片的不显示问题。欺骗了浏览器以为是自己的数据。
处理相对时间(初始化DayJS配置)
03:解决了第三方图片不显示问题,开始完成简介中的日期使用插件格式化
1:dayjs的使用流程
2:在utils工具文件夹中创建,dayjs.js用来格式化日期。导入下载的dayjs插件, 导入中文语言包, 全局使用dayjs.locale('zh-cn')中文语言。 打印格式化信息, dayjs().format('YYYY-MM-DD')设置格式化类型
3:打印了测试能格式化时间
处理相对时间(处理完成)
04:完成了dayjs的使用配置,开始完成时间信息的修改展示
1:参考使用手册
2:Vue.filter配置过滤器,把时间给格式化
3:在页面中用管道符去格式化,完成了时间的格式化处理
5-频道编辑
模块介绍
05:完成了文章列表页面的功能开发,开始了解编辑频道的功能介绍
点击能添加和删除频道,完成状态下点击能跳到对应的tabs页面
使用弹出层组件
06: 了解了编辑频道的功能介绍后,开始完成点击弹编辑频道出层
1:弹出层默认是false,点击事件时,改为true,弹出弹出层,v-model绑定了弹出层的开关启状态,closeable关闭图标,close-icon-position关闭图标的位置,position弹出层,弹出的位置
2-3:页面效果,点击汉堡包弹出弹出层
创建频道编辑组件
07: 完后了点击汉堡包弹出弹出层,开始完成在弹出层内嵌套一个channel-edit频道编辑的子组件,挂载在home页面中显示
1:创建频道编辑组件
2:在home页面导入并解构出组件,在components声明组件,然后在页面元素区域中挂载组件。
3:页面效果,点击弹出频道编辑弹出层,弹出proup中嵌套了一个频道编辑组件。
页面布局
08: 完成了点击弹出频道编辑弹出层,弹出proup中嵌套了一个频道编辑组件。开始完成宫格将频道内的初始布局完成
1:在刚才创建的子组件中,导入宫格组件,:gutter间隔, v-for生成多少个宫格,text文字
2:频道编辑中就在子组件中渲染了宫格
样式调整
09:完成了在频道编辑中就在子组件中渲染了宫格, 开始完成宫格样式的调整
1:white-space: nowrap不允许换行,flex-direction:row一行显示元素。
2::border=false不显示边框,slot=title标题插槽, plain朴素按钮,round圆角,size=mini。 icon=clear清除的图标。
3:页面效果,完成了宫格导航的样式布局
展示我的频道
10: 完成了宫格导航的样式布局 , 开始完成我的频道数据的渲染
1:在home页面吧自己channel数据,在子组件中通过:my-channels接收了我的频道的数据,传递给了子组件。
2:子组件在props数据指定中,设置myChannels我的频道的参数设置,数组类型,必填项。在元素中通过v-for遍历myChannels数据对象,channel数据对象, index序号, 完成了grid-item的渲染。
3:完成了编辑弹出层的我的频道宫格的数据渲染
处理激活频道高亮
11:完成了编辑弹出层的我的频道宫格的数据渲染,开始完成点击tabs我的频道同步被高亮
1:home中是通过active让自己的元素高亮, 在channel-edit通过:active接收这个active高亮属性,
2:在channel-edit频道编辑子组件,在自己的props中设置active的参数,type数值型,required必填项,
3:听听歌:class动态渲染样式, active是类名, 后面是条件渲染,后面的条件如果是真,前面的类样式就会被添加上
4-5:完成了点击tabs我的频道同步被高亮
展示推荐频道-获取所有频道
12:完成了点击tabs我的频道同步被高亮, 开始完成所有频道的数据获取。
1:在api中创建了channel.js请求接口函数, 在home页面导入并解构,在data创建空数组用来接收所有频道的数据, 在created中调用自己的函数,函数中调用接口函数,把拿到的数据赋值给data,在把channels赋值给allChannels,拿到了所有频道的数据
3:通过vue可以查看channelEdit组件中allChannels已经拿到数据了。
处理完成
13: 完成了channelEdit组件中allChannels已经拿到数据了, 开始把数据渲染到推荐频道中
1:在computed计算属性中封装含糊,函数中通过filter过滤出所有频道,find找出那些不是mayChannels我的频道的数据,找到了频道推荐的数据,
2:把拿到的recommendChannels推荐频道的数据,通过v-for遍历,展示在grid-item推荐频道的宫格中,
3:完成了推荐频道的数据渲染,
添加频道
14:完成了推荐频道的数据渲染,开始完成添加频道的功能
1:点击推荐频道的宫格是,触发点击事件,函数中通过myChannels.push把选中的宫格添加到了我的频道中,
2:实现了点击推荐频道,把推荐频道宫格,添加到我的频道中。
处理编辑状态
15:实现了点击推荐频道,把推荐频道宫格,添加到我的频道中。 开始完成编辑状态下我的频道的样式布局
1:data中的isEdit默认是false,点击编辑按钮将状态改为true,如果是true显示完成按钮,不是就显示编辑按钮,但是在data中设置了fiexChannels固定的,不允许删除的频道, 在显示删除图标的时候,v-show=isEdir && !fiexChannels.includes(channel.id)如果id和规定的数值一样,就是不允许删除的频道,就不显示删除图标。
2-3:点击编辑,就显示了删除小图标,除了推荐显示删除图标,点击完成删除小图标就隐藏了
切换频道
16: 完成了点击编辑,就显示了删除小图标,除了推荐显示删除图标,点击完成删除小图标就隐藏了,开始完成点击我的频道,实现tab标签页面的同步高亮
1:在我的频道中点击宫格触发自己的事件,把点击的频道和index携带过去,事件中如果处于编辑状态,触发父级的自定义事件函数update-active,携带了index, 父组件home中通过@update-active接收了子传递的自定义事件,交给了onUpdateActive函数,在父组件自己的事件中,让子组件的index=active,实现了父组件中的active高亮修改,关闭我的频道弹出层
原理其实就是子组件通过自定义事件,把index传递给了父组件,父组件中的active和index一致,就实现了点击tab标签页面高亮效果
删除频道
17:完成了点击我的频道中的宫格,对应的tab标签实现了高亮。开始完成点击我的频道删除图标,实现删除功能。
1:在点击我的频道中的宫格事件中,如果有固定的频道,直接return不允许删除的,其他的就直接调用splice从我的频道数组中根据index删除1项,
删除后如果当前的序号小于高亮的序号,就通过自定义事件,让父组件函数中自己处理让删除后的的宫格,前一个自动高亮。如果是非编辑转态,点击就关闭弹出层,跳转到对应的tab频道,让当前的频道高亮
2:父组件home接收了自定义事件, 在事件中,参数1是序号,参数2是频道弹出层的显示与隐藏状态, 让但当前的tab高亮和关闭弹出层
3:完成了我的频道点击宫格删除宫格的功能,并且删除宫格的前一个高亮,如果不是编辑状态就让点击的tab标签高亮
数据持久化-业务分析
01:完成了我的频道点击宫格删除宫格的功能,并且删除宫格的前一个高亮,如果不是编辑状态就让点击的tab标签高亮,开始完了解数据持久化的方式,实现登录和为登录:的频道数据存储的问题。
1-2: 未登录就将数据储存在localStoreage中,登录就将数据储存在后台服务器,这样就能实现跨设备同步功能
添加频道
02:了解了未登录就将数据储存在localStoreage中,登录就将数据储存在后台服务器,这样就能实现跨设备同步功能,开始完成持久化的添加频道功能
1:在channel.js中封装了后台添加的接口,在channel-edit事件函数中,如果用户是登录的,调用接口把id和频道的数量传递给后台,实现了持久化的添加频道, 发生错误就提示,反之就是没有登录,就将数据存储在storage中。
2:实现了 未登录就将数据储存在localStoreage中,登录就将数据储存在后台服务器,这样就能实现跨设备同步功能,通过调试工具也能看出,未登录数据存储在了localStorage中,通过response能看到数据的响应。如果登录了就在channelEdit的state中能看到
删除频道
03:完成了持久话的频道添加功能,区分了登录和未登录添加频道的功能,开始完成持久的删除频道的功能
1:在channel.js中封装了删除的接口,
2:在channel-edit中导入并解构出该接口,在自己的点击删除中,去调用持久化删除函数,把频道的数据携带,如果用户登录了就直接调用接口完成删除我的频道功能,反之未登录就将删除后的数据,通过storeage.js中的setItem完成本地储存中的数据更新,变相的实现了删除功能。如果删除失败提示,提示删除失败
3:完了登录和未登录的我的频道的持久化的数据的删除功能
正确的获取展示首页频道列表
04:完了登录和未登录的我的频道的持久化的数据的删除功能,开始完成正确的数据渲染,
1:如果登录,就调用接口实现了频道的数据获取, 未登录就获取本地储存中的数据,如果本地中有数据,就直接把数据渲染到未登录的频道中。 反之如果本地中没有任何数据,就调用接口获取到所有的频道数据,把所有的判断数据给未登录的频道。如果获取频道数据失败,就弹出获取频道数据失败
2:完成了正确的频道数据获取,区分了登录和未登录的所有频道数据的获取,和本地中有数据,就用本地的数据,如果没有才把所有数据给到本地。实现了完整的频道数据渲染
6-文章搜索
模块介绍
05:完成了频道页面的编辑,开始了解搜索框的功能开发, 点击搜索框跳转到搜索框页面,搜索关键字出现搜索联想,回车搜索页面展示搜索结果列表, 清空输入框显示历史记录,点击删除单条记录,点击删除全部实现全部的记录删除
创建组件并配置路由
06:了解了搜索的功能,开始创建search搜索组件,在router中配置配置为单独的search路由,在home页面中的搜索按钮,点击跳转到搜索页面。
页面布局-搜索栏
07:完成了搜索组件和路由的创建,点击跳转搜索页面,开始完成顶部搜索框的布局
1:注意from是为了ios在搜索打字中出现search按钮,shoew-icon取消按钮, @search搜索时触发的事件, @cancel取消时触发
2-3:点击跳转到搜索页面,搜索页面就多了顶部搜索框
页面布局-完成
08:完成了搜索页面的顶部搜索框的布局,开始完成搜索历史和联想建议和搜索列表的布局
1:在search文件夹的components中创建了3个子组件,在search中导入,在components中声明组件,在template中挂载组件去渲染
2:使用cell单元格,完成了搜索历史的布局
3:完成了联想建议的布局
4:完成了list搜索结果列表的布局,v-model加载状态, :finished是否已经加载完成, @load滚动底部加载时触发,在list组件页面中,嵌套了cell单元格,v-for循环展示了10个列表数据, 下拉还可以展示更多的数据
5:完成了搜索页面的布局,完成了搜索历史和联想建议和搜索列表的布局。
处理页面展示逻辑
09:完成了搜索历史和联想建议和搜索列表的布局。开始完成按需渲染不同的搜索组件
1:如果输入框中没有内容,默认显示搜索历史记录
2:搜索时出现联想建议
3:按钮回车键,所有的搜索结果,显示在搜索结果列表页面
4:点击输入框自动获取焦点,实现搜索联想建议
逻辑分析:搜索结果默认是不显示的,只有在触发搜索的时候显示,如果搜索结果不显示,就显示搜索联想建议,如果联想建议也不显示,就默认显示搜索历史记录。
联想建议-获取并监视输入框内容的变化
10:完成了按需渲染搜索组件,开始获取到输入框中的值,用父传子通信将数据传递给子组件,在子组件大打印输入框中的值
1:在search中父传子通信 :search-text将搜索的文本传递给子组件,
2:在子组件中props指定数据类型,字符串类型是比必填的。在watch中创建searchText中,handler数固定的写法,value就是书输入框中的数据,immediate:true实时触发事件函数,输入时,一致触发。
3:页面效果,在控制台中打印了数据,因为输入框是search父组件的,在子组件挂载的时候,通过动态属性的方式将数据传递给了子组件本体文件中。在prps中设置参数类名,在watch中打印了输入框中值
请求获取展示数据
11:完成了父传子通信将数据传递给子组件,在子组件大打印输入框中的值,开始完成联想建议的数据渲染。
1:封装search.js接口,需要携带q输入框的值
2:在联想建议组件中导入并解构出该接口,在data中创建联想建议空数组,在methods的函数中调用接口获取到数据,携带输入的值,把返回的联想建议储存在联想建议数组中,如果数据获取失败,就提示获取数据失败
3:把拿到的联想建议在cell单元格中循环,实现了联想建议的真实数据渲染
4:页面效果,输入时能根据关键字出现联想建议
优化防抖
12:完成了输入时能根据关键字出现联想建议, 开始完成输入框防抖
1:下载lodash插件
2:在组件中导入并解构插件,在watch的handler中使用debounce包裹this.loadSearchSuggestions,每隔0.2秒触发一次搜索请求
3:页面效果,用lodash实现了请求的防抖,就是使用debounce方法实现了防抖
搜索关键字高亮-思路分析
13:用,用lodash实现了请求的防抖,就是使用debounce方法实现了防抖。开始完成了解搜索关键字的高亮原理
1: 说明文档
2:在data中声明htmlStr属性, 在元素中挂载渲染, 可以使用slot插槽, v-html才能将标签的数据渲染为真实元素效果
3:页面效果,通过在data中声明了一个样式,在template的插槽中渲染了带标签的文本
搜索关键字高亮
14:了解了搜索联想建议的文字高亮效果的方式,开始实现正则表达式将联想建议渲染
1: 在控制台中进行数据的调试
2:在联想建议子组件中,v-html触发函数封装,携带每一项的联想建议。
在函数封装中,创建高亮的字符串,将联想建议通过插槽渲染在该元素的样式中,创建正则表达式,gi全局匹配,忽略大小写。使用text.replace(reg, highligtstr)用自己的数据,代替样式中的文字。实现联想建议的关键字高亮效果
3:原理就是,v-html接收函数的返回结果,在函数中用样式把匹配的输入的值给找出来, 在样式中高亮渲染
传递搜索内容
15:实现了输入框中的联想建议关键字的高亮,开始完成点击联想建议通过自定义事件触发父组件的搜索事件,父组件中的子组件的:search-text接收搜索的文本信息,search-result子组件通过props接收输入框的数据,配置输入框的参数,实现搜索结果页面的搜索内容的获取
1:联想建议组件通过。 $emit触发父组件的search中的onSearch事件,并把每项联想建议给携带过去
2:在父组件中通过@search接收了联想建议传递过来自定义事件,事件函数中把输入框的内容赋值,并搜索结果页面显示
3:父组件页面中:search-text通过自定义把搜索的内容传递给了搜索结果页面, 搜索结果页面通过Props接收并设置输入框中的文本参数类型,通过vue组件的调试工具能看到SearchResult组件已经能拿到props中的输入框中的内容
4-5:联想建议组件触发了search父组件的事件函数,父组件的事件函数中拿到数据框中的数据,子组件通过父传子通信的传值,把获取到输入框中的内容给传递到了搜索结果页面,完成了搜搜结果页面的搜索内容的获取
处理完成
16:完成了联想建议组件触发父组件的事件函数,拿到了输入框中的内容,并通过父传子通信传递给了搜索结果页面。搜索结果页面设置搜索框内容的参数配置。在vue调试中能拿到props输入框的数据了,开始完成搜索结果页面数据的渲染
1:在api中search.js封装函数请求,将请求搜索结果的接口导出去
2:在搜索结果页面中通过导入并解构拿到接口,在onload渲染函数中调用接口,携带了参数,当前的页面,和每页多少条数据,和搜索的关键。将获取到的搜索结果, 添加到list数组中, 如果数据还存在,就下拉加载更多数据, 如果没有设置已经加载完毕。关闭loading状态。完成了搜索结果的数据获取,开始在元素中将真实的数据给渲染,并设置了记载的参数设置,
4:设置了index首页的布局修改,完成了顶部的搜索布局和list列表页面的数据布局
5:页面效果,完成了搜索结果页面的数据获和渲染
添加历史记录
01:完成了搜索页面的搜索结果的数据渲染,开始完成搜索历史记录的数据获取
1:@search触发子组件的onSearch事件函数,拿到输入框中的值,通过indexOf找到这个历史记录,如果该历史记录已经存在,就将它从搜索历史记录的列表中拿出来,并通过unshift插入到历史记录列表中的最前面。 显示历史记录表格。
2-3:页面效果,通过vue调试面板中能看到searchHistories中能看到历史记录中已经存在数据了,如果再次搜索的值是一样的,是直接从搜索历史记录中拿出来,在次渲染到历史记录列表的第一条。但是还没有做数据的渲染,只是做到了历史记录的数据获取
展示历史记录
02:拿到了搜索历史记录的数据后,开始完成搜索历史记录的数据渲染
1:将父组件中的历史记录数据通过:search-histories传递给了,搜索历史记录页面,
2:历史记录组件,通过props接收了父组件传递过来的历史记录,并设置了历史记录的参数类型,在cell单元格中v-for渲染搜索历史记录,把历史记录渲染到了搜索历史记录页面
3:搜索历史记录页面实现了数据的渲染
处理删除显示状态
03:完成了搜索历史记录页面实现了数据的渲染, 开始完成删除状态的显示
1:具体的实现流程
2:设置了删除按钮的显示状态,默认是隐藏的,通过v-if删除图标,显示关闭的图标,并且显示全部删除和完成的按钮,如果点击完成就隐藏关闭按钮,出现删除的图标
3-4:页面效果,点击删除的图标,出现关闭按钮和全部删除和完成的按钮,点击完成就还原删除图标
处理删除操作
04:完成了删除图标的切换显示,开始完成真正的删除功能,完成删除单个,和清空历史记录的功能
1:点击删除历史记录的事件函数,携带了item要删除的项,和index要删除的id,在事件函数中,如果显示历史记录的表格,就调用splice根据index从历史记录中删除一条历史记录数据,如果不是删除状态,点击就直接进入到搜索结果页面。
2:完成全部删除的功能:子组件通过@click触发了父组件的自定义事件, 父组件接收到了自定义事件,将自己的历史记录给清空,实现了搜索历史数据的清空功能
3-4-5-6:页面效果点击删除单个,和点击清空输入框。如果不是删除状态,点击历史记录就会跳转到搜索结果页面。
数据持久化
05:完成了单个和全部历史记录的删除功能,开始完成历史记录的数据持久化
1:在search父组件页面中, 在data中获取到本地存储中的数据,如果没有数据,就渲染空数组。 在watch中调用setItem把数据添加到历史记录中
2:实现了将历史记录储存在本地会话中,实现了刷新页面。搜索历史记录也存在。
7-文章详情
模块介绍
06:完成了文章搜索的功能开发,开始完成文章页面的关注--点赞--收藏的开发
创建组件并配置路由
07:了解了要完成关注-收藏-点赞功能的开发,开始创建文章页面的布局开发
1: 配置路由,
2:创建组件,通过:to属性,可以用对象的形式,跳转到article这个路由地址,params就是携带文章的id,实现了动态传参的形式跳转到不同的文章页面
3:击文章简介,跳转到文章详情页
使用组件Props解耦路由参数
08:完成了点击简介跳转到文章详情页的路由和组件页面的创建,开始开启路由传参,实现点击跳转到不同的页面
1:需要在该对应路由中声明props: true,开启路由传参。
2:在文章页面的props中接收并设置articleId的参数类型,就能在文章页面点击把文章的id传递到url地址中
3:页面效果,点击完成文章就能在地址后面携带参数
页面布局
09:开启了url地址传参,把文章的id携带在请求中,开始快速用导师准备好的页面代码,实现了文章详情页面的布局
1:将笔记中的文章详情页面的代码覆盖本页面的代码,就实现了文章页面的布局
请求获取文章数据(404)
10:使用已有代码快速完成了文章页面的布局,开始调用接口把点击的文章显示到文章详情页面
1:在api/article.js中封装获取新闻文章的接口函数,并携带ID
2: 文章页面导入该接口,在created中调用自己的函数,函数中调用接口把请求到的数据打印到控制台中
2:获取数据失败,是因为js精度问题
关于后端返回数据中的大数字问题(为什么404)
11:封装接口在created中调用接口获取数据失败,原因是大数字问题,开始通过空盒子台模拟和演示大数字问题
1:network中获取到的是真正的数据,就是原始数据,而vue面板中获取到的id,是错误的。所以出现了404,找不到文件的问题
2:在控制台中演示了js精度的问题
3:流程示意
json-bigint的使用
12:通过空控制台模拟和演示大数字问题,开始使用插件解决,演示js精度问题的处理
1:下载插件
2:在utils/request.js导入插件,演示插件的使用。JSONBig.parse().toString()能拿到真正的ID,并是准确的。 JSONBig.stringify能把js转换成字符串
3:转换的效果,js原生的和插件处理的效果展示
处理完成
13:演示用插件能解决js的精度问题,开始在请求中处理js大数字问题
1:在api/request.js中通过配置了transformResponse:在该函数中配置,使用创建插件JSONBig.parse(data)将请求的数据转换并返回,实现了数据转换
2:由于插件转换出来的是object类型的,所以article文章页面,需要在props中设置articleId的类型,这次控制台返回的是真正的数据了,而且vue工具中的ArticleIndex也能接收到新闻列表的数据了
展示文章详情
14:通过使用插件解决了js大数字的问题,并且拿到数据了,开始完成文章详情页面数据的渲染
1:在调用接口拿到了所有的文章数据
2:在文章详情组件中渲染, :src动态接收文章的头像, v-html能将带标签的数据渲染成真正的文章数据
3:页面效果,完成了文章详情页面的数据渲染
处理内容加载状态
15:完成了文章详情页面的数据渲染,开始完成内容加载的状态提示
2:如果文章数据加载失败,就显示内容加载失败的提示信息
3:如果加载成功,就直接显示文章的数据
1:页面请求数据,默认是loading状态过后再显示数据的,如果已经拿到了文章的数据,就将文章详情展示,如果没有拿到,就加载文章的错误提示。或者其他未知错误提示加载失败。
关于文章正文的样式
16:完成了文章状态的错误处理提示的按需展示, 开始使用插件美化文章的样式
1:去github中下载github-markdown.css插件,将下载好的css文件,放在自己的v-ews/article/git-markdown.css中。
2:在文章的详情页面中导入,并将该类名渲染到文章内容的父节点,实现了文章的样式美化
3:虽然美化了样式,但是文字字体过小,需要在.postcssrc中将github-markdown排除出去,不用对他进行px转换,用它原来自己的样式大小即可
4-5:页面字体大小刚好,样式也被美化了
图片点击预览(使用ImagePreview 组件)
17:完成了用插件美化了自己文字详情页的样式美化,开始完成点击图片实假图片的预览
1:在页面导入组件,在组件中配置images要显示的图片, startPosition起始位置, onClose图片的关闭触发的事件函数
2: 页面直接显示图片的预览功能
图片点击预览(处理完成)
18:使用了ImagePreview图片预览组件在文章页面实现了预览功能,开始完成真正的图片点击预览放大功能
1:通过ref拿到了article-content文章的内容,在加载文章函数中调用了图片预览的事件,图片预览事件中获取到所有的文章内容。并从引用对象中使用querySelectorAll获取到引用对象中所有的数据, 使用forEach遍历数据, 每次遍历都往图片空数据中添加一张图片,并在循环中给每一个图片绑定了点击事件, 点击事件中使用Imgpreview配置要渲染图片的地址,和点开显示的是第几张图片
2:页面效果,在文章列表页面,点击能预览大图
关注用户(视图处理)
01:完成了点击图片预览大图的功能,开始完成关注按钮的转态切换
1:关注按钮在多处都显示了,文章详情页+我的个人中心首页,都有关注状态的显示
2:给button按钮的状态,通过v-if判断数据中的article.is_follwed关注状态,如果是true显示已关注, false就显示未关注
3:页面效果,通过调试工具,能切换关注按钮的转态切换了
关注用户(实现基本功能)
02:完成了给按钮判断数据的状态,显示与切换关注状态。开始完成点击关注的功能,但是不能自己关注自己
1:在user.js中封装了关注和取消用户的相关请求, 需要携带target当前关注用户的ID
2:在文章页面中导入该接口,在点击关注事件中,通过判断如果已关注,点击删除关注, 如果是未关注,点击就是调用接口实现关注。如果失败的状态是400表示是关注了自己,导致该关注失败,所有提示用户,关注失败
3:你不能关注你自己,只有看其他用户,就能实现点击关注该用户,或者取消关注
loading处理
03:完成了点击关注功能,开始完成关注时点击过多,使用loading圈圈解决请求过多的问题
1:点击关注时触发loading圈圈,结束时关闭圈圈,以为在元素中通过:loading绑定加载的状态, data中设置了圈圈的默认值是fasle,只有点击了时,才会触发圈圈,请求结束后关闭圈圈
2:页面内效果。点击了时,触发圈圈,请求结束后关闭圈圈
组件封装
04:完成了使用loading解决了多次点击发送的请求,开始完成关注用户使用组件化的方式抽离。实现关注重用的功能
1:在页面的多出都有使用到关注按钮:他人的主页+粉丝列表+文章类表,都有关注按钮
2:将关注按钮抽离的组件,导入并挂载在自己页面中,并配置了参数,将关注状态和用户的id以及接收自定义事件更新自己的关注状态。在components中配置了该组件
3:在组件页面中将按钮剪切了过来, 并绑定props配置接收过来的参数, 在data中设置了loading的默认状态。事件函数中用了接口实现了关注和取消关注的功能。如果是400,提示你自己不能关注你自己,其他的失败,就提示操作失败
3.1: 并通过this.$emit触发自定义事件,把关注的状态取反传递给父组件,父组件@接收了自定义事件,并将关注的状态和$event一致,其实$event就是子组件的参数2,就是取反
4:页面实现了抽离关注组件,关注功能一切正常
在组件上使用v-model
05:完成了关注组件的抽离复用,功能一切正常,开始使用v-model对关注的参数配置简化
1:在父组件中沟通过v-model,能代替 :is-followed和@自定义事件。直接使用v-model接收数据中的是否关注数据
2:通过model能修改配置value的默认参数, 这样更有可读性, prop的值是is_followed, event的值是update-is_followed, 就是change改变时触发的自定义事件。
3:优化关注事件中的,如果已关注,点击就调用取消关注的接口,实现取消关注功能,
发起自定义事件,把自己的关注状态传递给父组件,父组件通过v-model接收到了子组件的自定义事件,修改了自己组件中的关注状态,实现子组件通知修改父组件中的数据。
3.1:一个组件只能使用功能一个v-model,如果想多次使用,后期会教大家使用.sync去在一个组件中使用多个v-model的功能
文章收藏(准备组件)
06:完成了关注组件的v-model抽离优化,开始完成收藏组件抽离式复用的方式去渲染收藏按钮
1-2-3:在文章详情页+我的个人中心页面+文章收藏列表都使用到了收藏的数据,抽离成一个组件开发
4:在src/commponents/collect-article创建了组件, 在页面中剪切了按钮过来,但是样式保留在组件挂载中去调用,否则不会生效
5:在文章页面导入了收藏组件,实现了收藏组件的抽离渲染,样式正常。
视图处理
07:完成了收藏组件的抽离渲染,开始完成收藏按钮的切换显示
1:父组件article在子组件渲染的时候,把数据传递到了子组件本身, 使用v-model简化形式去优化了收藏功能的开发
2:子组在props中接收并配置了v-mdeol中的参数配置项, 关注的状态默认是布尔值, 且是必选项。:icon通过value的布尔值渲染图标,如果已经是关注,就显示实心的按钮,反之是空心的。
通过:class动态接收了按钮的颜色, 类名接收对象形式的配置,类名:布尔值,如果值是true,就显示了黄色反之没有颜色
3:页面效果,实现了按需渲染收藏按钮的样式与颜色
处理完成
08:完成了需渲染收藏按钮的样式与颜色, 开始调用接口实现真正的收藏与取消收藏
1:在api/article.js中配置了收藏与取消收藏的接口配置,需要携带target当前的关注状态,
2:在收藏组件中导入了接口,在事件中如果已经收藏了,点击调用取消收藏的接口,反之调用收藏接口, 并通过$emit通知父组件完成了数据渲染,你也改一下自己收藏状态数据。收藏后会有提示弹出, 如果错误就提示请重试。关闭loading状态
3:父组件,因为需要将该文章的id携带给子组件,所以通过:article-id把id给了子组件,子组件在props中配置了参数信息。在接口请求时代id携带了
4:页面效果,完成了文章详情页的收藏功能
文章点赞(准备组件)
09:完成了文章详情页的收藏功能,开始完成点赞组件的抽离式布局
1:接口参数点赞的说明
2:父组件导入点赞组件,配置后挂载,在组件挂载时,v-model简化了状态修改,:article-id接收了文章的ID
3:子组件接收了v-model的数据,并配置了参数,在组件的按钮中:icon根据布尔值按需渲染图标, :class按需渲染高亮的背景色
4:页面效果,通过vue测试,能修改点赞的样式
处理完成
10:完成了点赞组件的抽离和样式配置,开始调用接口实现真正的点赞功能
1:在api/article中封装接口,请求参数是文章的ID
2:在子组件中导入接口,在事件函数中如果是点赞,在点击就调用取消点赞的接口,反之就是调用点赞的接口。通过$emit去通知父组件把id给同步修改一下。并提示修改的信息,修改失败,就提示修改提示修改失败的信息。并关闭loading状态
3:页面效果,实现了点赞功能的开发
8-文章评论
模块介绍
11:完成了文章点赞的功能,开始了解所需完成文章的评论功能,
1:文章页面下方的文章评论功能
2:点击胁迫了按钮,下弹出评论卡片
3:点击某用户后面的回复按钮, 弹出回复评论的卡片
4:在回复评论卡片中的内容会出现在评论列表中
展示文章评论列表-准备组件
12:了解了评论所需要的完成的功能,开始创建列表完成评论页面的初始布局
1:创建了评论列表组件,设置loading和finished的初始状态,在函数中初始化了10条列表数据
2:在文章页面导入该组件,并声明后,挂载在页面中显示
获取数据并展示
13:完成了评论列表的创建,开始完成列表的数据渲染
1:封装接口,params是需要携带type类型, source数据源, offset表示从第一页获取数据, limit获取评论数据的个数
2:在评论列表组件中导入接口, 在props中设置了source数据的参数配置, 在data中配置了加载的状态和默认第一页。
3:在js函数中调用接口,携带了type,offset,limit评论的数据个数。 把获取到的数据通过数据解构的方式全部都添加到list数组中, 如果获取到了数据,关闭架子啊,下拉就会触发下一页的数据, 没有更多数据就设置借宿。 如果发生了错误就将状态设置为错误状态true。 关闭加载状态
4:在文章页面展示了评论列表
展示文章评论总数量
14:完成了列表页面的数据渲染, 开始完成页面评论总数量的展示
1: 子组件通过自定义事件,将数据传给了父组件,
2:父组件通过@接收了子组件的事件,并在data中的出初始数据设置为了0, 在接收自定义时间的时候把数据中的total_count给了该初始值,就拿到了总数据条数,实现而来父组件页面的incon图标的数量渲染
3:页面效果, 在文章列表页面渲染了数据总数量
评论列表项组件
15:完成了文章详情页面评论图标的评论总数量渲染,开始完成评论列表页面的数据渲染
1:父组件把item每一项的数据传递给了子组件
2:子组件接收后设置了数据的参数配置,配置好后,在cell单元格中开始渲染数据,
3: 完成了列表页面的数据渲染
评论点赞-视图处理
16:完成了评论列表页面的数据渲染,开始完成评论点赞的视图渲染
1:给点赞按钮设置动态绑定类名,如果类名后面的布尔值是true就表示添加高亮, :icon动态绑定图标, 如果is_liking是true就是实心的,反之不是实心的点赞图标
2:页面效果,完成了图标的切换和高亮的渲染
评论点赞-处理完成
17:完成了点赞图标组件的视图渲染,开始调用接口完成真正的点赞功能
1:封装接口,点赞的接口和取消点赞的接口
2:列表项组件中,点击事件中如果已经点赞了,调用接口取消点击, 如果没有点赞,调用接口实现点赞。 操作失败弹出提示,关闭loading加载状态
3:页面实现了点赞功能
发布文章评论-准备弹出层
18:完成了真正的点赞功能,开始完成点击评论按钮,评论卡片的弹出层页面布局
1:在文章详情页面的点击写评论按钮,将评论组件的状态改为了true点击就会弹出显示评论框组件
2:点击写评论, 就会弹出基本评论框组件,虽然组件中还未有内容
发布文章评论-准备组件
19:完成了点击写评论弹出评论组件,开始完成评论组件的页面样式布局
1:创建了post评论组件,在组件中使用field完成了页面的评论组件页面的布局
2:在文章页面导入该组件,但是是嵌套在popup弹出层里面,这样点击写评论就能显示评论框了。
3:页面效果,点击完成了评论框的页面渲染
发布文章评论-请求发布
20:完成了文章评论组件的页面布局,开始调用接口拿到评论的数据
1:封装接口,需要携带data,请求体中需要携带评论的ID和评论的内容,文章的ID,
2:文章详情页,通过:target自定义属性绑定,在post评论组件中,将评论的id传递给了评论框组件
3:评论框组件导入接口, 并接收了评论ID,设置了评论id的参数类型,在点击发布触发自己的事件函数,函数中调用了接口携带了必填参数,评论目标的ID+内容+文章的ID, 将获取到到数据打印到控制台中查看
4:页面效果,在评论框中写了内容,点击发布,成功拿到数据了
发布成功处理
21:完成了点击发表评论后,通过接口成功拿到了服务器的评论数据, 开始完成评论展示的功能
1:子组件post评论框,点击发布事件中设置了taost状态提示,并清空了评论框中的内容,发布自定义事件让父组件自己去修改页面列表的数据, 成功发布则弹出成功, 失败则弹出失败
2:文章列表组件,通过@在post组件挂载的位置接收了自定义事件, 该自定义事件的值,就是父组件的事件函数,触发了父组件的事件函数,
父组件通过:list在评论列表中去拿到评论列表组件的数据, list子组件接收到了list数据,设置了数据的参数类型。
3:在父组件文章列表页面中、的事件函数中将新的评论数据,更新到了list评论组件中的评论项,实现了评论功能
4:页面效果,点击写评论--弹出评论框,点击发布,提示发布,完成评论发布的功能
空内容处理
22:完成了评论功能的开发,开始完成如果评论框中有多个空格,是不允许点击发布的
1:v-model.trim中自动获取到输入框中的评论框中的数据,并清除了空格
2:发布按钮绑定了:disabled属性, 如果message没有长度,表示没有数据, 发布按钮就是灰色的,不能点击
3:页面效果,留言框中没有数据,是无法点击发布的
评论回复-功能介绍
01:完成了评论功能的开发,开始了解回复评论的功能
1:文章下方默认显示文章评论列表
2:点击默认的回复按钮,会进入到回复列表,里面能看到所有的回复,
3:点击写评论,就会在该回复中,进行盖楼。
4:在回复列表中,点击某人的回复按钮,会弹出评论框,点击发布,就在回复列表中的第一楼显示
准备弹出层
02:完成了回复的功能细节了解,开始完成点击弹出层
1:在在文章页面中使用popup内置组件,默认高度是100%,只有在isReplyShow的时候,才为true,就会弹出评论回复组件
2:通过vue面板,将值改为了true,显示了评论回复的对话框
点击回复展示弹出层
03:完成了点击回复,显示弹出回复的内置组件页面,开始完成点击评论列表项的回复按钮,显示父组件的内置弹出层
1:在item列表项中通过自定义事件触发list父组件的自己组件挂载的位置去接收,本体传过来的自定义事件函数,列表组件通过自定义事件,触发了爷爷文章详情组件自定义事件函数,函数中就拿到了item孙组件传递过来的点击对象了。在爷爷文章组件中打印了点击回复点击的那个对象
2:点击回复,文章组件就拿到了被点击的那个对象
封装组件
04:完成了点击回复按钮,在文章详情页面中获取到了被点用户的个人信息,开始完成评论回复组件页面的创建
1:创建了评论回复的组件,
2:文章详情页面中挂载,
3:在文章详情页中默认就能显示评论回复的组件页面了
将点击回复的评论项传递给评论回复组件
05:完成了回复组件页面的创建,并挂载在文章详情页面中挂载显示, 开始完成被评论的对象数据,从父组件中传递给子回复组件
1:在文章详情页面中,设置了回复的数据对象, 在评论组件中通过自定义属性键给数据传递给本体, 在父组件的点击事件中,把被点的评论对象的数据获取
2:在回复组件中接收了被点评论对象的个人信息,并设置了个人信息的参数配置。
3:页面效果,在评论回复页面中就拿到了父组件传递过过来的数据对象了
处理头部及当前评论项
06:完成了页面文章详情向子组件评论回复组件传递了被点人的个人信息,开始回复页面的基础样式布局
1:导入item列表项组件,将评论列表组件渲染到自己的页面中,这就是自己组件封装的优势,实现了代码的重用。在顶部 :title绑定了如果有评论数量,就显示回复条数, 在点击关闭图标的事件中,自定义事件在文章详情页面中通知本体去将回复列表组件,点击关闭。
2:点击回复,显示回复组件。回复组件中的数据实现了页面布局的样式搭建
展示回复列表(基本处理)
07:完成了回复列表页面的样式布局,开始调用接口渲染回复列表的数据渲染
1: 封装接口,需要携带params评论的数据对象,
2:在list评论列表页面中调用了接口,携带了必须参数,并且设置了type的类型, 默认是a,可选类型是ac,评论回复组件页面也罢文章的id和类型传递给了父组件文章列表页面, 在文章列表页面中使用toString将id进行了转换,解决了js精度问题
3:默认真正的请求源中是有""引号的,在preview中看得更清楚,不需要aixos帮我们转换评论,因为它会携带引号拼接错误。我们手动使用toString将数据拼接成了字符串,解决了js精度问题成功拿到了回复列表的数据
展示回复列表(解决重复数据问题)
08:解决了js温度问题,拿到了回复列表的数据,开始完成回复列表数据的渲染展示
1:回复组件拿到了数组,禁用了默认滚动位置检查,要不会默认渲染2次数据,出现重复的评论。 在create中手动开启loading,实现了滚动才能再次获取数据。
2:回复列表页面本来默认渲染2次重复的数据,解决后,页面只渲染了一次数据
解决内容不重新获取问题
09:完成了评论回复的列表数据渲染,开始完成评论列表数据展示所出现数据不清空重用的问题
1:在文章详情页中,使用v-if如果关闭了回复弹框,就把回复列表中的数据给清空,实
2:完美解决了,点击不同的回复,出现的永远是第一次出现的回复内容。在关闭回复弹出框后,会把回复框中的列表数据给重新获取渲染,实现了点谁,显示谁
发布回复(处理底部视图布局)
10:完成了回复页面数据重复的问题,开始完成回复页面的样式修改
1:完成了写评论按钮的样式布局,
2:完成可回复列表中的产生滚动条,距离上下有一定的距离
3:页面效果,底部出现了写评论的按钮,中间出现了回复列表的滚动效果
参数处理
11:完成了回复列表的滚动和底部按钮的样式布局,开始完成父组件将数据传递给子组件
1:评论回复组件页面通过:target把数据传递给了某某组件,
2:父组件使用了provide将数据传给了所有的子组件
3:子组件通过inject接收到了父组件传递过来的ID,实现了文章id的获取
4:页面评论框组件就能拿到父组件传递过来的文章id了
处理完成
12:完成了父组件快速共享数据的方法,开始完成恢复评论的功能
1:评论组件将自己的数据,通过自定义事件,将数据传递给了评论回复组件,
2:评论回复组件接收到了评论框发过来的数据,就在自己的事件中,将最新的回复,添加到回复列表中的第一项。并让评论数量累加
3:页面效果点击发表了评论回复,评论总条数就累加显示了。
9-编辑用户资料
模块介绍
13:完成了文章评论的功能开发,开始了解点击编辑资料,进入资料页面的编辑
1:头像+昵称+性别+生日,都是可以修改的
创建页面组件并配置路由
14:完成了对编辑资料页面功能的了解,开始完成编辑资料页面组件的创建
1:创建用户资料组件,
2:在router中配置好路由, 在my里面的编辑资料的按钮,点击跳转到用户资料页面
3:点击编辑资料,跳转到用户资料页面
页面布局
15:完成了用户资料页面的创建,开始完成用户资料页面的个人信息布局
1:头部用nav-bar组件, left-arrow顶部左侧的箭头,下面的个人资料是cell单元格,title标题, value占位符,is-link右箭头,img fit填充模式,等比例占满。round圆角,src图片地址
2:页面效果,完成了资料页面的个人信息的样式布局。
展示用户信息
16:完成了资料页面的个人信息的样式布局,开始完成个人资料页面的数据渲染
1:封装请求接口,
2:在index中导入该接口,在data中创建user:{}对象,用来接收这个用户的信息, 在函数中调用接口获取数据,获取到用户的数据,将数据填充到user中,而user在页面的元素区域,进行了渲染,
3:在页面中显示了个人数据
修改昵称-处理弹出层
17:完成了个人页面的数据渲染,开始完成点击用户昵称,跳转到用户昵称内置弹出组件
1:在index页面中使用功能了popup弹出层组件,v-model绑定了弹出层的显示状态,在点击昵称,显示昵称弹出组件
2:页面效果,点击昵称,弹出内置的昵称组件
内容组件
18:完成了击昵称,弹出内置的昵称组件,开始完成昵称组件的内置子组件,渲染组件的创建,挂载在index中的弹出层组件中
1:创建了更新昵称的个人组件,在index中的弹出层里面挂载,这样点击弹出层,就嵌套显示了个人的昵称详情组件
2:点击昵称,弹出内置组件,内置组件中嵌套了个人昵称的组件,
内容布局
19:完成了点击昵称,弹出内置组件,内置组件中嵌套了个人昵称的组件,开始完成个人昵称组件的样式布局
1:nav-bar组件完成了顶部的样式布局,@click-left点击左侧箭头,触发父组件中本体中的事件,关闭昵称修改的弹出层
2:使用filed完成了输入框的布局
3:在index页面和纵横设置了所有弹出层的背景色
4:完成了昵称页面的用户数据渲染
数据处理
20:完成了昵称页面的用户数据渲染,开始完成昵称的数据获取,点击取消,将输入框中的内容给还原回本用户
1:父组件中的本体通过v-model监听了昵称的数据,个人子组件中props配置了value,其实就是昵称的参数配置信息, 将个人的用户昵称渲染到了输入框中
2:传值流程分析,父组件的本体通过v-model传了数据给个人子组件,个人子组件中配置昵称的参数配置,用localName接收了昵称,个人组件中的filed用v-model双向数绑定了父组件传递过来的昵称,在自己的留言框中展示
3:在update-name个人组件中,通过v-if,如果点击关闭了设置昵称,里面个人子组件就会被清空,实现了每次打开设置昵称,都是还原用户本人的昵称。
处理完成
21:完成了设置昵称输入框的昵称数据获取展示,和点击关闭设置昵称组件将输入框中的昵称还原回该用户,开始完成昵称的修改功能
1:封装接口,需要携带修改的用户昵称给后台
2:在个人子组件的右点击事件中,先弹出提示框,提示保存中,获取到用户的昵称,调用接口携带昵称,完成昵称的修改,开始用$emit触发父组件的v-model实现父组件中的昵称数据发生改变。try中处理成功,catch处理失败
3-4:完成了修改昵称的功能
修改性别
22:完成了修改昵称的功能,开始完成性别组件的布局和调用接口完成性别的修改
1-2:创建个人子性别组件,在index父组件中的popup弹出层中挂载本体,并且在关闭弹出层的时候还原回性别的默认选中,子组件本体通过v-model双向数据绑定,将性别传递给了子组件,并在个人子组件中触发自定义事件给子组件本体去关闭弹出层。子组件本体用来还原数据状态和传递性别给回个人组件,并触发自定义事件去关闭弹出层。
3-4:子组件本体用picker滚动组件完成布局,:cloumns接收多个性别,:default-index接收porps中的value,显示男女。 @cancel组件本体关闭事件, @confirm点击确定触发,调用接口,把数据中的男女序号给携带给后台,完成性别修改,触发组件本体中的关闭事件,@change触发选中是的性别。把选中的性别传递给数据中的性别序号。
5:页面效果,完成了点击性别,弹出性别修改,选择性别完成性别的修改。
修改生日-准备
23:完成了点击性别,弹出性别修改,选择性别完成性别的修改,开始完成点击生日,弹出生日修改的组件简单样式布局
1:在index父组件中使用内置弹出层,嵌套自己的个人子组件,将创建好的个人子组件导入父组件中,并声明挂载渲染
2:-3:页面效果,点击生日修改,弹出生日弹出框
处理完成
24:完成了点击生日弹出生日组件,开始完成生日页面的布局和完成生日的修改功能
1:父组件中的本体,通过v-if关闭时还原了用户的生日,@close触发自己的关闭弹出层,
2:子组件用props接收了v-model的实现数据绑定,
3:使用了datetime-picker时间组件搭建了布局,v-model双向数据绑定当前用户的生日,@cancel触发组件本体的关闭事件,@confirm触发确定事件
4:在data中设置时间组件需要监听的数据值,
5:在确认函数中使用dayjs格式化日期,调用接口,把生日时间给后台,携带生日。完成生日的修改,$emit将修改的生日时间传递给组件本体的v-model.和触发组件的关闭事件
6:页面效果,点击弹出时间组件,点击确认完成了生日的修改。
功能介绍
01:完成了点击弹出时间组件,点击确认完成了生日的修改,开始了解头像修改的功能
1:点击选择相册中的图片实现头像的修改
2:点击照相机拍摄,使用拍摄的照片设为头像,图片和以拉伸移动裁剪。实现头像的修改功能
图片上传预览(处理file-input)
02:了解了修改头像的功能细节,开始使用隐藏的input图片哦空间,点击头像通过控件把图片的地址获取到
1:在cell头像的上方添加了一个input控件,默认是hidden隐藏的,
2:在头像中点击中通过$refs.file.click()触发图片控件的点击选择图片的功能
3:图片控件通过@change拿到选择时触发的事件,拿到图片控件的files[0],就是本地图片的地址,在创建对象地址,并打印输出。
4:在点击头像,选中了图片,就能将图片的地址打印出来
功能处理
03:完成了点击头像能拿到选中图片的图片地址,开始完成大图基础的预览功能
1:创建了个人图片预览组件,组件中用img标签:src动态接收了图片的地址
2:在index父组件中导入,并声明挂载,在挂载的时候通过:img接收动态的图片地址
3:data数据中img默认是null,只有在点击头像的时候,把刚才打印的图片地址赋值给img,这样就实现了img赋值,子组件本体接收了img设置了参数类型。并在父组件中清空了选中的图片地址
4-5:页面效果,点击头像,弹出头像预览层
样式处理
04:完成了点击头像预览头像的功能,开始完成完后预览头像的页面样式布局处理
1: 父组件页面中的本体,通过:img把图片地址传递给了个人子组件,个人子组件在props中接收和设置了参数配置,在img中被:src给接收到,实现了图片的预览功能,在点击事件中触发组件本体的关闭事件,
2-3:预览图片页面就实现了图片的预览,流程就是组件本体把img对象传递给了个人子组件,个人子组件设置了参数类型,并通过:src接收而来该图片的地址,实现了预览
图片裁切(初始化)
05:完成了头像预览的功能和页面布局,开始使用cropperjs去快速完成预览的功能
1:下载插件
2:在js中导入css和js文件
3:需要预览的图片,必须要有父容器
4:img必须转换为块级元素
5:在mounted页面元素渲染后,通过它操作DOM,获取到图片裁剪的信息
6:通过使用该加减,快速完成了图片的预览功能
配置说明
06:完成了使用插件预览图片和预览页面的样式布局,开始了解预览图片中的参数配置
1:具体的参数配置信息详解,请看图,有说明
获取结果的两种方式
07:完成了插件图片裁切的各个参数的含义,开始了解服务器端裁切和客户端裁切的使用场景和如何使用它们的方法,获取到裁切的数据
1:点击完成成,触发自己的事件函数
2:设置裁剪的参数信息,
3:这个裁剪信息调用了getCroppedCanvas获取到了图片裁剪的数据对象信息。
4-5-6: 两种方式都能获取裁切的数据,服务器的裁切兼容性比较好,客户端不用后台写接口也能完成,因为是手机端不用担心兼容问题。拿到了裁切的数据
处理完成
08:完成了裁剪数据的获取,开始完成真正的头像上传功能
1:封装接口,需要携带裁剪对象的信息
2:调用单独封装的函数,自己值做裁剪数据的获取,
3;完成头像上传的事件中,裁剪form表单对象,往photo中填充裁剪的数据,调用接口把裁剪的数据携带,完成头像修改的功能,触发了本体中的关闭事件,和父组件中的图片修改,实现了头像修改
4:页面效果,点击头像,弹出图片修改,选中照片后,调整图片,点击完成,完成头像的修改功能