一起从零开始学VUE(13)移动端头条案例

文章目录

        • 初始化
        • 完成User组件的内容
        • 使用Vant组件库中的tabbar组件和navbar组件
        • 修改NavBar的默认样式
        • 完成articleItme.vue组件的布局结构
        • 使用request模块进行请求数据
          • 挂载axios的两种方法
          • 获取文章的列表数据
        • 传递文章详情信息
          • 格式化时间
        • 上拉加载更多、下拉刷新
          • 上拉加载更多
          • 下拉刷新
        • 文章列表图片的懒加载
      • 反馈操作
        • 一级反馈页面
        • 二级反馈页面

初始化

  1. 创建工程,vue create 工程名称

  2. 重置App.vue中的代码

  1. 重置index.js中的代码
import Vue from 'vue'
import VueRouter from 'vue-router'Vue.use(VueRouter)// 清空路由规则
const routes = []const router = new VueRouter({routes
})export default router
  1. 清空component和views目录下的组件

  2. VUE配置ESLint->刚开始可省略这步,不然会很痛苦!!!

参考博文:https://www.cnblogs.com/sinosaurus/p/11275671.html

  1. 首页和我的两个组件放到views文件夹下,与路由相关的组件放到views下

完成User组件的内容


在这里插入图片描述

使用Vant组件库中的tabbar组件和navbar组件

官方链接:https://vant-contrib.gitee.io/vant/#/zh-CN/tabbar

在Home.vue中添加navBar导航栏


在App.vue组件中添加Tabbar标签栏,点击Tabbar中的item会有路由跳转,因此还需要配置index.js




首页我的

routes: [{ path: '/', component: Home },{ path: '/user', component: User }
]

请添加图片描述

从上面的动图中我们可以看见,首页中显示的最后一个元素是123456,但是实际中最后一个元素应该是单一元素1,这是由于固定在底部的tabbar占据了部分空间从而导致元素显示不完全,为了解决这个问题我们可以采用下面两种方法:

  1. 为最外层的div标签添加padding值
.home-container{padding: 46px 0 50px 0;
}
  1. 在NavBar或TabBar中添加 fixed placeholder

请添加图片描述

修改NavBar的默认样式

如果使用的是placeholder的方法,修改默认样式的时候需要添加/deep/,否则无效

/deep/ .van-nav-bar{background: #007bff;
}
/deep/ .van-nav-bar__title{color: white;
}

在这里插入图片描述

覆盖第三方样式时,如果直接覆盖不生效,则需要添加/deep/,这样修改的局限性在于只能修改当前组件的样式,如果想要修改全部的,可以使用定制主题,使其全局生效。

完成articleItme.vue组件的布局结构

使用request模块进行请求数据

挂载axios的两种方法
  1. 在main.js中添加Vue.prototype.$http = axios,但这种方法无法实现复用,每一个新地址都要重新声明

  2. 在utils文件夹中创建request.js

    import axios from 'axios'const request = axios.create({baseURL: 'https://www.escook.cn'
    })export default request
    
获取文章的列表数据

为了获取到文章的列表数据,我们需要定义一个initArticleList函数来向接口发起GET请求。并在生命周期函数created()中进行调用

created() {this.initArticleList()
},
methods: {async initArticleList() {// 发起GET请求,获取文章的列表数据// 解构赋值const { data: res } = await request.get('/articles', {//   请求参数params: {_page: this.page,_limit: this.limit}})console.log(res)}
}

为了方便代码的复用,我们将请求列表数据的代码进行封装

// 向外按需导出一个方法
import request from '@/utils/request.js'export const getArticleListAPI = function(_page, _limit) {// 返回一个Promise实例return request.get('/articles', {params: {_page,_limit}})
}

在需要使用API接口的组件中,按需进行导入和传参

import { getArticleListAPI } from '@/utils/articleAPI.js'

传递文章详情信息

在父组件中,将元素传递给子组件,子组件中使用插值表达式和自定义属性进行接收。

  • 父组件Home.vue向子组件articleItem.vue进行传值

  • 子组件接收父组件的值

**注意:**带有默认值的对象或数组,其默认值必须从一个工厂函数获取

props: {title: {type: String,default: ''},author: {type: String,default: ''},imgList: {type: Object,default: function() {return { type: 0 }}},pubTime: {type: String,default: ''},comment: {type: [Number, String],default: 0}}

通过观察效果图,我们发现图片的显示形式有两种,一种是三张图片并排,另一种是单张图片,通过type=1和type=3来控制,因此为了区分显示这两种形式,我们使用v-if进行判断,具体代码如下:
在这里插入图片描述


格式化时间

如果我们想要像csdn这样将文章发布的时间变成相对时间的话,我们可以利用dayjs来快速实现。

  1. 下载安装dayjs
npm install dayjs --save
  1. 在main.js入口文件中导入dayjs相关的模块
// 导入 dayjs 的核心模块
import dayjs from 'dayjs'// 导入计算相对时间的插件
import relativeTime from 'dayjs/plugin/relativeTime'// 导入中文语言包
import zh from 'dayjs/locale/zh-cn'
  1. 在main.js入口文件中,配置插件和语言包
// 配置“计算相对时间”的插件
dayjs.extend(relativeTime)// 配置中文语言包
dayjs.locale(zh)
  1. 在 main.js 入口文件中,定义格式化时间的全局过滤器:
// dt 参数是文章的发表时间
Vue.filter('dateFormat', dt => {// 调用 dayjs() 得到的是当前的时间// .to() 方法的返回值,是计算出来的“相对时间”return dayjs().to(dt)
})
  1. 调用过滤器实现相对时间的计算

在这里插入图片描述
在这里插入图片描述

上拉加载更多、下拉刷新

需要使用到vant 2的list组件,通过loading和finished两个变量控制加载的状态,当组件滚动到底部时,会触发load事件并将load设置为true,此时应该发起请求加载更多数据。在请求新一页的数据时,会将loading的值变成true,如果这期间,用户频繁上拉加载框,此时不会多次调用load事件,只有load为false时,才会触发请求事件。此处需要注意load的状态的变化。

官方示例:https://vant-contrib.gitee.io/vant/v2/#/zh-CN/list

上拉加载更多

在Home.vue中添加van-list组件后,需要在methods节点下定义onLoad方法。

  1. 为了实现上拉请求下一页的十条数据,我们需要将this.page++并且重新调用请求数据的方法this.initArticleList()
  2. 在方法中请求完后需要将this.loading设置为false
  3. 为了不让新请求到的数据覆盖原来的数据需要将数据进行合并this.artList = [...this.artList, ...res]旧数据在前,新数据在后
async initArticleList() {// 发起GET请求,获取文章的列表数据// 解构赋值const { data: res } = await request.get('/articles', {//   请求参数params: {_page: this.page,_limit: this.limit}})this.artList = [...this.artList, ...res]this.loading = falseconsole.log(this.artList)// 如果请求的数据为空数组,则说明到底了,finished =trueif (res.length === 0) {this.finished = true}
},// 滚动到底部onLoad() {console.log('loading')this.page++this.initArticleList()}
下拉刷新

list组件可以与pullRefresh组件结合使用,实现下拉刷新功能,操作完成后将v-model设置为false表示加载完成。

注:此处下拉刷新做成从头开始请求数据

onRefresh() {console.log('refreshing')// 清空列表数据this.finished = false// 重新加载数据// 将 loading 设置为 true,表示处于加载状态if (this.refreshing) {this.page = 1this.artList = []this.initArticleList()this.refreshing = false}this.loading = true
}

请添加图片描述

文章列表图片的懒加载

为了优化网站的性能,可以采用图片懒加载。此处使用基于 Vant 的 Lazyload 懒加载,可以轻松实现列表中图片的懒加载效果。

官方示例:https://vant-contrib.gitee.io/vant/v2/#/zh-CN/lazyload

  1. 引入 Lazyload 指令,并将 Lazyload注册为全局可用的指令
import { Lazyload } from 'vant';
Vue.use(Lazyload);
  1. 将v-lazy指令的值设置为你需要懒加载的图片
<div class="title-box"><span>{{ title }}span><imgalt=""class="thumb"v-if="imgList.type === 1"v-lazy="imgList.images[0]"/>
div>

<div class="thumb-box" v-if="imgList.type === 3"><imgalt=""class="thumb"v-for="(image,index) in imgList.images":key=indexv-lazy="image"/>
div>

反馈操作

接下来我们要实现点击×出现一级反馈页面,可以选择”不感兴趣“,”拉黑作者“,”反馈垃圾内容“三种选项,进行前两种操作后,页面中对应的文章信息将会被”删除“,选择反馈垃圾内容则会出现二级反馈页面。

一级反馈页面

请添加图片描述
使用vant的ActionSheet 动作面板能够轻松的帮助我们实现反馈页面
官方示例:https://vant-contrib.gitee.io/vant/v2/#/zh-CN/action-sheet
具体实现步骤

  1. 在data中定义一个属性show,默认值为false,用来控制动作面板的显示与隐藏,action数组中存放的是操作的名称,即”不感兴趣“,”拉黑作者“,”反馈垃圾内容“,动作面板通过 actions 属性来定义选项,actions 属性是一个由对象构成的数组,数组中的每个对象配置一列,
data() {return {show: false,actions: [{ name: '不感兴趣' },{ name: '拉黑作者' },{ name: '反馈垃圾内容' }]}}
  1. 添加actionSheet动作面板组件
<van-action-sheet v-model="show" :actions="actions" @select="onSelect" />
  1. 为了实现点击×出现动作面板需要给van-icon绑定click事件,点击×后show变为true,即动作面板显示,
          <van-icon name="cross" @click="show = true" />
  1. 设置选中后的事件onSelect:默认情况下,点击选项时动作面板不会自动收起可以通过改变show的值来控制显示与隐藏,也可以为van-action-sheet添加close-on-click-action 属性开启自动收起
    onSelect(item) {// 默认情况下点击选项时不会自动收起// 可以通过 close-on-click-action 属性开启自动收起if (item.name === '不感兴趣') {this.show = false} else if (item.name === '拉黑作者') {this.show = false} else {console.log(item.name)}}
  1. 不感兴趣和拉黑作者需要将对应的文章内容进行逻辑上的删除,我们可以对item的id进行操作,通过自定义属性将操作好的id值传递给父组件Home.vue,在Home.vue组件中对id进行过滤输出
 onSelect(item) {if (item.name === '不感兴趣') {this.show = falseconsole.log(this.artId)this.$emit('remove-article', this.artId)} else if (item.name === '拉黑作者') {// this.show = false} else {console.log(item.name)}}}

其中this.artId是计算属性,将文章的art_id转换成字符串类型

  computed: {artId() {return this.article.art_id.toString()}

在Home.vue中对原数组进行filter方法的过滤

    removeArticle(id) {// 对原数组进行 filter 方法的过滤this.artList = this.artList.filter(item => item.art_id.toString() !== id)}

二级反馈页面

二级反馈页面与一级反馈页面的操作累死,为了区分两个页面,在data中添加isFirst属性,默认isFirst为true

<van-action-sheetv-model="show":actions="actions"@select="onSelect"v-if="isFirst"
/>
<van-action-sheetv-model="show":actions="reports"cancel-text="取消"close-on-click-action@select="onSelect2"@closed="isFirst = true"v-else
/>

点击一级菜单中的反馈垃圾内容时,将this.isFirst = false此时二级菜单会显示出来,其他操作与一级反馈菜单一致

    onSelect2(item) {Toast('举报成功')this.$emit('remove-article', this.artId)}

请添加图片描述


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部