黑马头条(学习笔记)

黑马头条(学习笔记)_第1张图片

目录

一. 项目概述

二、项目初始化

 移动端 REM 适配:

关于 PostCSS 配置文件:

Autoprefixer 插件的配置 :

postcss-pxtorem 插件的配置:

 关于字体图标:

 配置路由:

 封装请求模块:

三:登录注册: 

存储用户 Token:

关于 Token 过期问题:

四:个人中心

五、首页—文章列表:

关于第三方图片资源403问题:

处理时间:

六、首页—频道编辑:

频道数据持久化:

正确的获取首页频道列表数据图:

七、文章搜索

八、文章详情

关于后端返回数据中的大数字问题:

关于文章正文的样式:

九、文章评论

十、 编辑资料

图片裁切:

方式一:结合服务器方式

 方式二:纯客户端方式

十一.  小智同学

WebSocket:

使用原生 WebSocket(了解):

Socket.IO(了解体验):

十二: 功能优化

组件缓存:

响应拦截器:


一. 项目概述

1.   有哪些业务:

本项目涵盖了新闻资讯类 App 的重点核心功能,其中包括:用户登录 / 注册、文章列表、文章详情、文章评论、个人资料、用户中心、频道管理、文章搜索、用户收藏 / 历史 / 作品,以及机器人聊天等功能。

2. 用的什么技术栈?

本项目采用完全前后端分离的开发模式,使用 Vue.js 技术栈(全家桶)构建的移动端 SPA 单页面应用程序。 

黑马头条(学习笔记)_第2张图片

3. 业务功能:

本项目的目标是完成一个新闻资讯类 App 的核心功能,但项目中所覆盖的核心业务却非常具有普适性,在众多 App 中都有体现,诸如:

     基于 Token 的验证方案处理用户登录

     移动端表单验证方案及交互提示

     短信验证码的发送与验证

     用户中心、个人资料展示

     对文章内容的收藏、点赞和分享

     编辑用户资料,其中包括基本信息修改及头像裁切上传等功能

     列表类页面的加载、缓存及优化

     列表类页面的下拉刷新和上拉加载更多

     资讯类文章详情展示和文章评论

     完整的搜索业务:输入联想建议、搜索关键词高亮、搜索历史记录、搜索结果列表等

     即时通信核心业务及基于 WebSocket 的数据通信

4. 本项目采用了以下项技术解决方案:

      基于 Vue.js 的前端框架

      基于 webpack 工程化开发解决方案

      基于 Vant 的前端 UI 组件库,开发效率更高

      基于 axios 的请求库,功能强大性能高效

      基于 RESTful 风格的数据 API 解决方案(90% 的后端均采用这种风格提供数据 API,全        栈级能力,升职加薪不在话下)

      基于 JWT 的 Token 状态维持解决方案(能够强化更多服务器知识)

      基于 Vue Router 的路由管理方案

      基于 Vuex 的状态共享方案

      基于 Vue CLI 的脚手架工具,快速创建项目快速开发

      基于 Socket.IO 的实时通信解决方案

      基于 PostCSS 的移动端 REM 适配解决方案

      基于 DCloud 平台的移动 App 开发解决方案


二、项目初始化

删除初始化的默认文件

新增调整我们需要的目录结构,下载vuex,router路由,less,vant组件库,axios

├── src                
│   ├── api            存储 API 请求模块
│   ├── router         Vue Router 路由模块
│   ├── store          Vuex 容器模块
│   ├── styles         存储全局样式资源目录,在main.js中引入
│   ├── utils          存储工具模块
│   ├── views          存储视图组件
│   ├── App.vue        根组件
│   └── main.js        入口模块

 移动端 REM 适配:

Vant 中的样式默认使用 px 作为单位,如果需要使用 rem 单位,推荐使用以下两个工具:

  • postcss-pxtorem 是一款 postcss 插件,用于将 px 单位转化为 rem
  • lib-flexible 用于设置 rem 基准值

下面我们分别将这两个工具配置到项目中完成 REM 适配。

1. 使用 lib-flexible 动态设置 REM 基准值(html 标签的字体大小)

安装依赖:

# yarn add amfe-flexible           npm i amfe-flexible

然后在 main.js 中加载执行该模块:

import 'amfe-flexible'

最后测试:在浏览器中切换不同的手机设备尺寸,观察 html 标签 font-size 的变化。

2. 使用 postcss-pxtorempx 转为 rem

安装依赖:

# yarn add -D postcss-pxtorem
# -D 是 --save-dev 的简写
npm install postcss-pxtorem -D

然后在项目根目录中创建 postcss.config.js 文件:

module.exports = {
  plugins: {
    'autoprefixer': {
      browsers: ['Android >= 4.0', 'iOS >= 8']
    },
    'postcss-pxtorem': {
      rootValue: 37.5,
      propList: ['*']
    }
  }
}

配置完毕,重新启动服务。

最后测试:刷新页面,审查元素样式查看是否已将 px 转换为 rem

需要注意的是:

  • 该插件不能转换行内样式中的 px,例如

关于 PostCSS 配置文件:

postcss.config.js 是 PostCSS 的配置文件。

PostCSS 是一个处理 CSS 的处理工具,本身功能比较单一,它主要负责解析 CSS 代码,再交由插件来进行处理,它的插件体系非常强大,所能进行的操作是多种多样的,例如:

  • Autoprefixer 插件可以实现自动添加浏览器相关的声明前缀
  • PostCSS Preset Env 插件可以让你使用更新的 CSS 语法特性并实现向下兼容
  • postcss-pxtorem 可以实现将 px 转换为 rem
  • ...

目前 PostCSS 已经有 200 多个功能各异的插件。开发人员也可以根据项目的需要,开发出自己的 PostCSS 插件。

PostCSS 一般不单独使用,而是与已有的构建工具进行集成。


Vue CLI 默认集成了 PostCSS,并且默认开启了 autoprefixer 插件。

Vue CLI 内部使用了 PostCSS。

可以通过 .postcssrc 或任何 postcss-load-config 支持的配置源来配置 PostCSS。也可以通过 vue.config.js 中的 css.loaderOptions.postcss 配置 postcss-loader。

我们默认开启了 autoprefixer。如果要配置目标浏览器,可使用 package.json 的 browserslist 字段。

Autoprefixer 插件的配置 :

黑马头条(学习笔记)_第3张图片

autoprefixer 是一个自动添加浏览器前缀的 PostCss 插件,browsers 用来配置兼容的浏览器版本信息,但是写在这里的话会引起以下编译器警告:

Replace Autoprefixer browsers option to Browserslist config.
Use browserslist key in package.json or .browserslistrc file.

Using browsers option can cause errors. Browserslist config
can be used for Babel, Autoprefixer, postcss-normalize and other tools.

If you really need to use option, rename it to overrideBrowserslist.

Learn more at:
https://github.com/browserslist/browserslist#readme
https://twitter.com/browserslist

 警告意思就是说应该将 browsers 选项写到 package.json.browserlistrc 文件中。

 package.json 文件里的 browserslist 字段 (或一个单独的 .browserslistrc 文件),指定了项目的目标浏览器的范围。这个值会被 @babel/preset-env 和 Autoprefixer 用来确定需要转译的 JavaScript 特性和需要添加的 CSS 浏览器前缀。

参考官方文档中的语法,我们将package.json 文件里的 browserslist 字段 (或一个单独的 .browserslistrc 文件) 修改如下:

"browserslist": [
  "Android >= 4.0", 
  "iOS >= 8"
]
或
Android >= 4.0
iOS >= 8

并将postcss.config.js中的此代码删掉

'autoprefixer': {
     browsers: ['Android >= 4.0', 'iOS >= 8']
},

保存之后就不报错了

postcss-pxtorem 插件的配置:

黑马头条(学习笔记)_第4张图片

rootValue:表示根元素字体大小,它会根据根元素大小进行单位转换

propList 用来设定可以从 px 转为 rem 的属性

               例如 * 就是所有属性都要转换,width 就是仅转换 width 属性

 rootValue 应该如何设置呢?

如果使用的是基于lib-flexable的REM适配方案,则应该设置为你的设计稿的十分之一。
例如设计稿是 750 宽,则应该设置为 75。

大多数设计稿的原型都是以 iPhone 6 为原型,iPhone 6 设备的宽是 750,我们的设计稿也是这样。

但是 Vant 建议设置为 37.5,为什么呢?

因为 Vant 是基于逻辑像素 375 写的,所以如果你设置为 75 的话,Vant 的样式就小了一半。

所以如果设置为 37.5 的话,Vant 的样式是没有问题的,但是我们在测量设计稿的时候都必须除2才能使用,否则就会变得很大。

有没有更好的办法不用除以2呢?

1.  不用写代码的方式(1)

在 Photoshop 中打开单位与标尺设置面板:菜单栏 -> 编辑 -> 首选项 -> 单位与标尺。

将单位中的标尺和文字的单位修改为

黑马头条(学习笔记)_第5张图片

打开设置图像大小面板:

菜单栏 -> 图像 -> 图像大小        快捷键:Alt + Ctrl + I

关闭重新采样

将宽度单位设置为

将高度单位设置为

将宽度修改为 375,高度不用动(它会适应宽度自动调整)

点击确定完成修改。

黑马头条(学习笔记)_第6张图片

调整之后,我们可以看到图像的大小变成了 375 点 x 667 点(144 ppi)。

在 iPhone 6/7/8 设备下,1个点 = 2个物理像素,所以导出的图片还是原来的二倍图。

不用写代码的方式(2)

使用像素大厨的二倍图功能 

2. 写代码的方式:

通过查阅文档可以看到 rootValue 支持两种参数类型:

数字:固定值

函数:动态计算返回

           有一个默认参数:一个对象,其中包含一个 file 属性(编译的文件路径)

所以我们可以这样来处理它:

module.exports = {
  plugins: {
    'postcss-pxtorem': {
      rootValue ({ file }) {
        // 如果是 Vant 的样式就按照 37.5 处理转换
        // 如果是我们自己的样式就按照 75 处理转换
        return file.indexOf('vant') !== -1 ? 37.5 : 75
      },
      propList: ['*']
    }
  }
}

这种方式不方便调试。因为在调试面板中看到的都是逻辑像素大小,它和 750 物理像素设计稿不一致,无法很好的利用调试工具。

 关于字体图标:

使用 iconfont 制作字体图标:

登录 iconfont

创建项目

上传图标到项目中   图标下载

去除颜色并提交

点击生成代码

将css代码引入public/index.html中就可直接使用

或在项目中创建 src/styles/icon.less 并写入上面css中复制到的代码,并引入main.js

注意:

@import用于在css中引入css文件 

 配置路由:

黑马头条(学习笔记)_第7张图片

 封装请求模块:

创建 src/utils/request.js

/**
 * 封装 axios 请求模块
 */
import axios from "axios"
const request = axios.create({
  baseURL: "http://ttapi.research.itcast.cn/" // 基础路径
})
export default request

哪里使用,哪里加载:

import request from '@/utils/request'
request({
  method: 'xxx',
  url: 'xxx',
  ...
})

三:登录注册: 

存储用户 Token:

登陆成功后后台为了区分用户是谁,服务器会下发token(令牌:唯一标识)

我们需要把它存储到一个公共的位置,方便随时取用

往哪儿存?

  • 本地存储

    • 获取麻烦

    • 数据不是响应式

  • Vuex 容器(推荐)

    • 获取方便

    • 响应式的

使用容器存储 Token 的思路:

  • 登录成功,将 Token 存储到 Vuex 容器中

    • 获取方便

    • 响应式

  • 为了持久化,还需要把 Token 放到本地存储

    • 持久化

黑马头条(学习笔记)_第8张图片

关于 Token 过期问题:

见最后


四:个人中心

项目中的接口除了登录之外大多数都需要提供 token 才有访问权限。

后端接口要求我们将 token 放到请求头中发送

方式一:在每次请求的时候手动添加(麻烦)

axios({
  method: "",
  url: "",
  headers: {
    Authorization(后端与前端商量好的字段): "Bearer token"
  }
})

方式二:使用请求拦截器统一添加(推荐,更方便)

黑马头条(学习笔记)_第9张图片

import axios from "axios";           引入axios
import store from "@/store/index";    引入store
const request = axios.create({              创建axios实例对象
  baseURL: "http://toutiao.itheima.net",
});
request.interceptors.request.use((config) => {  请求拦截器
  let token = store.state.mytoken;
  if (token) {  如果用户已登录,统一给接口设置 token 信息
    config.headers.Authorization = `Bearer ${token.token}`;
  }
  return config;   处理完之后一定要把 config 返回,否则请求就会停在这里
});
export default request;  导出


 

五、首页—文章列表:

记住列表的滚动位置:

问题:

假如把a列表的滚动条滚动到10的位置,然后切换到b列表并把滚动条滚动到20的位置,再次切换到a列表发现滚动条也在20的位置

为什么列表滚动会相互影响?

因为它们并不是在自己内部滚动,而是整个body页面在滚动。无论你是在a频道还是在b频道,其实滚动的都是body 元素。

怎么解决:

让每一个标签内容文章列表产生自己的滚动容器,这样就不会相互影响了。

如何让标签内容文章列表产生自己的滚动容器?

单独给每个列表设置
固定高度:height:xxx;

溢出滚动:overflow-y:auto;

如果设置高100%的话没有作用,为什么?
因为百分比是相对于父元素,如果审查元素发现它所有的父元素都没有高,那肯定没有作用了。

也可以用vw或vh

关于第三方图片资源403问题:

为什么文章列表数据中的好多图片资源请求失败返回 403?

这是因为我们项目的接口数据是后端通过爬虫抓取的第三方平台内容,而第三方平台对图片资源做了防盗链保护处理。

第三方平台怎么处理图片资源保护的?

服务端一般使用 Referer 请求头识别访问来源,然后处理资源访问。

黑马头条(学习笔记)_第10张图片

Referer 是什么东西? 

扩展参考:HTTP Referer 教程 - 阮一峰的网络日志
Referer 是 HTTP 请求头的一部分,当浏览器向 Web 服务器发送请求的时候,一般会带上 Referer,它包含了当前请求资源的来源页面的地址。服务端一般使用 Referer 请求头识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。

需要注意的是 referer 实际上是 "referrer" 误拼写。参见 HTTP referer on Wikipedia (HTTP referer 在维基百科上的条目)来获取更详细的信息。

怎么解决?

不要发送 referrer ,对方服务端就不知道你从哪来的了,姑且认为是你是自己人吧。 

如何设置不发送 referrer?

1.     用