vue2案例--类似今日头条新闻浏览

本文主要是介绍vue2案例--类似今日头条新闻浏览,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

案例效果

在这里插入图片描述

  1. 点击“首页”和“我的”可以切换页面
  2. 首页可以下拉刷新,请求更多数据
  3. 首页下滑可以加载更多

1.创建并梳理项目结构

  1. 创建项目,记得要安装路由 和 eslint
    在这里插入图片描述
  2. 梳理结构,清空 views和components文件夹

在这里插入图片描述

2. 安装和配置Vant组件库

Vant:轻量、可靠的移动端组件库

Vant官网

1. 安装
# Vue2 项目,安装 Vant 2:
npm i vant -S
2. 导入组件

Vant 支持一次性导入所有组件,引入所有组件会增加代码包体积,因此不推荐这种做法。

但是在开发阶段,我们不用考虑体积的问题,怎么快怎么来。在发布的时候,可以对项目体积进行优化,可以直接把vant从项目中抽出去。

举例如下:

输入网址:http://toutiao.liulongbin.top/report.html 可以看到黑马头条项目(该项目已经发布)打包之后生成的结果,如下:

在这里插入图片描述由上图可以看到没有把vant打包进来

在main.js中配置vant组件库
import Vue from 'vue'; 
import Vant from 'vant'; 
import 'vant/lib/index.css'; Vue.use(Vant); // use函数是来安装插件的

之后参考官方文档,根据需求进行使用,看到页面效果出现就成功了。

3. 使用 Tabbar 组件并开启路由模式

<template><div><!-- 路由占位符 --><router-view></router-view><!-- Tabbar 区域 --><van-tabbar route><van-tabbar-item  icon="home-o" to="/home">首页</van-tabbar-item><van-tabbar-item  icon="user-o" to="/user">我的</van-tabbar-item></van-tabbar></div>
</template>

4. 通过路由展示对应的 Tabbar 页面

在router/index.js 中配置路由规则:

在这里插入图片描述

5. 初始化 - 使用Navbar组件以及覆盖默认样式

<template><div class="home-container"><!-- 头部区域 --><van-nav-bar title="黑马头条" fixed /></div>
</template>
<script>
export default {name: 'Home'
}
</script>
<style lang="less" scoped>.home-container {padding-top:46px;padding-bottom: 50px;.van-nav-bar {background-color: #007bff;}/deep/.van-nav-bar__title {color:#fff;}}
</style>
至此,接下来就是完善主页的文章列表

6. 了解获取列表数据的API接口

请求方式
  • GET
请求根路径
  • https://www.escook.cn
请求URL 地址
  • /articles
查询参数–通过&进行拼接
参数名数据类型说明
_pageNumber页码值。从 1 开始
_limitNumber每页展示的数据条数。
响应的数据结构
[{"art_id": "8163","title": "iOS原生混合RN开发最佳实践","aut_id": "1111","comm_count": "254","pubdate": "2019-03-11 09:00:00","aut_name": "黑马先锋","is_top": 0,"cover": {"type": 3,"images": ["http://www.liulongbin.top:8000/resources/images/32.jpg","http://www.liulongbin.top:8000/resources/images/80.jpg","http://www.liulongbin.top:8000/resources/images/32.jpg"]}},{"art_id": "8089","title": "Typescript玩转设计模式 之 创建型模式","aut_id": "1111","comm_count": "24","pubdate": "2019-03-11 09:00:00","aut_name": "黑马先锋","is_top": 0,"cover": {"type": 1,"images": ["http://www.liulongbin.top:8000/resources/images/11.jpg"]}},{"art_id": "8145","title": "JAVA消息确认机制之ACK模式","aut_id": "1111","comm_count": "99","pubdate": "2019-03-11 09:00:00","aut_name": "黑马先锋","is_top": 0,"cover": {"type": 0}}
]
返回参数说明
参数名类型说明
art_idstring文章 id
titlestring文章标题
aut_idstring作者的 id
comm_countstring评论数
pubdatestring发布日期
aut_namestring作者名字
|- coverobject文章封面
|---- typenumber封面的数量,可选值:0、1、3
|---- imagesarray文章封面图片的 URL 数组

7. 封装utils目录下的request模块

安装axios
npm i axios -S
封装axios的原理

在这里插入图片描述

创建src/utils/request.js
import axios from 'axios'const request = axios.create({// 指定请求的根路径baseURL: 'https://www.escook.cn'
})export default request

8.在Home组件中封装initArticleList方法

一进入Home组件就要发请求,来拿第一页数据,一般来说是在created里面来调函数,发起请求。

但是,我们先不要写created,先封装一个methods来调接口拿数据:


// 导入 request.js
import request from '@/utils/request.js'
export default {name: 'Home',data () {return {// 页码值page: 1,// 每页显示多少条数据limit: 10}},methods: {// 封装获取文章列表数据的方法async initArticleList () {// 发起 GET请求,获取文章的列表数据const { data: res } = await request.get('/articles', {// 请求参数params: {_page: this.page,_limit: this.limit}})console.log(res)}},created () {this.initArticleList()}
}

获取到了数据:
在这里插入图片描述

9. 封装 articleAPI 模块

现有这样一个需求:我希望一进入User组件时,也会发起axios请求来获取图书列表,但我希望一次只请求5条数据,即把limit改成5即可

  • 一般方法的话,就是在User.vue中写和之前Home.vue大体一样的代码。
  • 那如果还有一个页面也要调这个接口呢?
  • 可以会发现代码冗余,因此要把代码复用起来
思路

在这里插入图片描述

开始封装
  1. 创建src/api 文件夹,里面存着所有的api接口,有一个文件是articleAPI.js文章相关的API都封装到这个模块中
// 文章相关的 API 接口,都封装到这个模块中
import request from '@/utils/request.js'
// 向外按需导出一个 API 函数
export const getArticleListAPI = function (_page, _limit) {return request.get('/articles', {// 请求参数params: {_page,_limit}})
}
  1. 在Home组件中调用这个api接口,User组件同理
// 按需导入 API 接口
import { getArticleListAPI } from '@/api/articleAPI.js'export default {name: 'Home',data () {return {// 页码值page: 1,// 每页显示多少条数据limit: 10}},methods: {async initArticleList () {const { data: res } = await getArticleListAPI(this.page, this.limit)console.log(res)}},created () {this.initArticleList()}
}
总结:

今后,如果需要调接口来获取用户相关的信息,则在src/api文件夹下新建一个模块专门来定义用户的api如userAPI.js

在这里插入图片描述

10. 封装 ArticleInfo 组件

ArticleInfo组件是可复用的组件,放在components文件夹中

请求回来的数据转存到了data()里面,供我们渲染页面时去使用在这里插入图片描述
渲染页面
<!-- 导入,注册,并使用 ArticleInfo 组件 --><ArticleInfo v-for="item in artlist" :key="item.id"></ArticleInfo>
为ArticleInfo 组件封装 props 属性
  1. 使用 ArticleInfo 组件
<!-- 导入,注册,并使用 ArticleInfo 组件 --><!-- 在使用自组件的时候,如果某个属性名是“小驼峰”形式,则绑定属性的时候建议改写成"连字符"格式 --><!-- 如 cmtCount 建议写成 cmt-count --><ArticleInfo v-for="item in artlist" :key="item.id" :title="item.title" :author="item.aut_name":cmt-count="item.comm_count" :time="item.pubdate"></ArticleInfo>
  1. ArticleInfo.vue 中:
export default {name: 'ArticleInfo',// 自定义属性props: {// 标题title: {type: String,default: null},// 作者名字author: {type: String,default: null},// 评论数cmtCount: {// 通过数组形式, 为当前属性定义多个可能的类型type: [Number, String],default: 0},time: {type: String,default: null}}
}
为ArticleInfo 组件封装 cover 属性
        <!-- 单张图片 --><img :src="cover.images[0]" alt="" class="thumb" v-if="cover.type === 1"></div><!-- 三张图片 --><div class="thumb-box" v-if="cover.type === 3" ><img :src="item" alt="" class="thumb"v-for="(item,i) in cover.images" :key="i"></div>
 // 封面的信息对象cover: {type: Object,// 通过default函数返回cover属性的默认值default: function () {return { type: 0 }}}

11. 实现上拉加载更多

需要用到 Vant 提供的组件 — List

List 组件通过 loading 和 finished 两个变量控制加载状态,当组件滚动到底部时,会触发 load 事件并将 loading 设置成 true。此时可以发起异步操作并更新数据,数据更新完毕后,将 loading 设置成 false 即可。若数据已全部加载完毕,则直接将 finished 设置成 true 即可。

export default {name: 'Home',components: {ArticleInfo},data () {return {// 页码值page: 1,// 每页显示多少条数据limit: 10,// 文章列表数组artlist: [],// 是否正在下一页数据,如果loading为true,则不会反复触发onload事件// 每当下一页数据请求回来之后,千万要记得 ,把loading 从 true 改为 falseloading: true,// 所有数据是否加载完毕,如果没有更多数据了,要把finished改成truefinished: false}},methods: {async initArticleList () {// 返回值 res 就是一个数组const { data: res } = await getArticleListAPI(this.page, this.limit)// 如果是上拉加载更多,那么应该是:// this.artlist=[旧数据在前,新数据在后]this.artlist = [...this.artlist, ...res]// 当第一页数据请求回来之后把 loading 改为 falsethis.loading = falseif (res.length === 0) {// 证明没有下一页数据了,直接把 finished 改为true,表示数据加载完了!this.finished = true}},// 只要onload 被调用,就应该请求下一页数据onLoad () {// 1.让页码值 +1this.page++// 2. 重新请求接口获取数据this.initArticleList()}},created () {this.initArticleList()}
}

12. 实现下拉刷新功能

下拉刷新时会触发 refresh 事件,在事件的回调函数中可以进行同步或异步操作,操作完成后将 v-model 设置为 false,表示加载完成。

export default {name: 'Home',components: {ArticleInfo},data () {return {// 页码值page: 1,// 每页显示多少条数据limit: 10,// 文章列表数组artlist: [],// 是否正在下一页数据,如果loading为true,则不会反复触发load事件// 每当下一页数据请求回来之后,千万要记得 ,把loading 从 true 改为 falseloading: true,// 所有数据是否加载完毕,如果没有更多数据了,要把finished改成truefinished: false,// 是否正在下拉刷新isLoading: false}},created () {this.initArticleList()},methods: {async initArticleList (isRefresh) {// 返回值 res 就是一个数组const { data: res } = await getArticleListAPI(this.page, this.limit)if (isRefresh) {// 下拉刷新: 新数据在前,新数据在后this.artlist = [...res, ...this.artlist]this.isLoading = false// 当} else {// 上拉加载更多:旧数据在前,新数据在后this.artlist = [...this.artlist, ...res]// 当第一页数据请求回来之后把 loading 改为 falsethis.loading = false}if (res.length === 0) {// 证明没有下一页数据了,直接把 finished 改为true,表示数据加载完了!this.finished = true}},// 只要onload 被调用,就应该请求下一页数据onLoad () {// 1.让页码值 +1this.page++// 2. 重新请求接口获取数据this.initArticleList()},// 下拉刷新的处理函数onRefresh () {// 1. 要页码值 +1this.page++// 2. 重新请求接口,获取数据this.initArticleList(true)}}
}

13. 定制主题

Vant定制主题的核心原理

该项目的标题“黑马头条" 默认是白色背景,我们是通过 /deep/ 深度选择器再结合审查元素找到了类名进行覆盖

这个方法有一个缺点:如果另一个页面,如用户页面,也有这个标题,那么需要重复这种方法,不然样式仍然是默认的。

因此我们使用 定制主题 这个方法

  1. 引入样式源文件,在main.js 中进行如下修改:

在这里插入图片描述

  1. 如果 vue-cli 搭建的项目,可以在 vue.config.js 中进行配置:
// 这个文件是 vue-cli 创建出来的 项目的 配置文件
// 在 vue.config.js 这个配置文件中,可以对整个项目的打包、构建进行全局性的配置
// webpack 在进行打包的时候,底层用到的是 node.js
// 因此,在 vue.config.js 配置文件中,可以导入并使用 node.js 中的核心模块
const path = require('path')
const themePath = path.join(__dirname, './src/theme.less')
module.exports = {css: {loaderOptions: {less: {// 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。modifyVars: {// 可以通过 less 文件覆盖(文件路径为绝对路径)// 从 盘符 开始的路径叫做绝对路径hack: `true; @import "${themePath}";`}}}}
}

在这里插入图片描述
4.上面的配置文件中的less变量在Vant 官网看:

在这里插入图片描述

14. 打包

下面介绍打包完成后能双击 dist/index.html 来打开项目,需要配置 vue.config.js:
在这里插入图片描述

然后在终端运行:

npm run build

这篇关于vue2案例--类似今日头条新闻浏览的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/282167

相关文章

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

Python get()函数用法案例详解

《Pythonget()函数用法案例详解》在Python中,get()是字典(dict)类型的内置方法,用于安全地获取字典中指定键对应的值,它的核心作用是避免因访问不存在的键而引发KeyError错... 目录简介基本语法一、用法二、案例:安全访问未知键三、案例:配置参数默认值简介python是一种高级编

MySQL中的索引结构和分类实战案例详解

《MySQL中的索引结构和分类实战案例详解》本文详解MySQL索引结构与分类,涵盖B树、B+树、哈希及全文索引,分析其原理与优劣势,并结合实战案例探讨创建、管理及优化技巧,助力提升查询性能,感兴趣的朋... 目录一、索引概述1.1 索引的定义与作用1.2 索引的基本原理二、索引结构详解2.1 B树索引2.2

前端如何通过nginx访问本地端口

《前端如何通过nginx访问本地端口》:本文主要介绍前端如何通过nginx访问本地端口的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、nginx安装1、下载(1)下载地址(2)系统选择(3)版本选择2、安装部署(1)解压(2)配置文件修改(3)启动(4)

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(

Java Web实现类似Excel表格锁定功能实战教程

《JavaWeb实现类似Excel表格锁定功能实战教程》本文将详细介绍通过创建特定div元素并利用CSS布局和JavaScript事件监听来实现类似Excel的锁定行和列效果的方法,感兴趣的朋友跟随... 目录1. 模拟Excel表格锁定功能2. 创建3个div元素实现表格锁定2.1 div元素布局设计2.

HTML中meta标签的常见使用案例(示例详解)

《HTML中meta标签的常见使用案例(示例详解)》HTMLmeta标签用于提供文档元数据,涵盖字符编码、SEO优化、社交媒体集成、移动设备适配、浏览器控制及安全隐私设置,优化页面显示与搜索引擎索引... 目录html中meta标签的常见使用案例一、基础功能二、搜索引擎优化(seo)三、社交媒体集成四、移动

HTML input 标签示例详解

《HTMLinput标签示例详解》input标签主要用于接收用户的输入,随type属性值的不同,变换其具体功能,本文通过实例图文并茂的形式给大家介绍HTMLinput标签,感兴趣的朋友一... 目录通用属性输入框单行文本输入框 text密码输入框 password数字输入框 number电子邮件输入编程框