前置需安装 vue脚手架 (如果你还没有安装 VueCLI,请执行下面的命令安装或是升级)
npm install --global @vue/cli
黑马头条接口文档下载
在命令行中输入以下命令创建 Vue 项目
vue create toutiao-m
进行流程安装
# 选择Vue脚手架版本 - 手动选择特性,支持更多自定义选项
? Please pick a preset:
Default ([Vue 2] babel, eslint)
Default (Vue 3 Preview) ([Vue 3] babel, eslint)
> Manually select features
# 选择需要安装的插件 - 勾选 (*) 项目需要安装的插件
# |Babel:es6 转 es5
# |Router:路由
# |Vuex:数据容器,存储共享数据
# |CSS Pre-processors:CSS 预处理器,后面会提示你选择 less、sass、stylus 等
# |Linter / Formatter:代码格式校验
? Please pick a preset: Manually select features
? Check the features needed for your project:
(*) Babel
( ) TypeScript
( ) Progressive Web App (PWA) Support
(*) Router
(*) Vuex
(*) CSS Pre-processors
>(*) Linter / Formatter
( ) Unit Testing
( ) E2E Testing
# 是否使用 history 路由模式(兼容差) n 不使用
? Use history mode for router?
(Requires proper server setup for index fallback in production) (Y/n) n
# 选择 CSS 预处理器,这里选择 Less
? Pick a CSS pre-processor
(PostCSS, Autoprefixer and CSS Modules are supported by default):
Sass/SCSS (with dart-sass)
Sass/SCSS (with node-sass)
> Less
# 选择校验工具,这里选择 ESLint + [Standard config](https://standardjs.com/)
? Pick a linter / formatter config:
ESLint with error prevention only
ESLint + Airbnb config
> ESLint + Standard config
ESLint + Prettier
# 选择在什么时机下触发代码格式校验:
# Lint on save:每当保存文件的时候
# Lint and fix on commit:每当执行 `git commit` 提交的时候
? Pick additional lint features:
(*) Lint on save
>(*) Lint and fix on commit
# Babel、ESLint 等工具会有一些额外的配置文件,询问将配置文件写入的位置:
? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
> In dedicated config files
In package.json
# 是否需要将刚才选择的一系列配置保存 选择 n
? Save this as a preset for future projects? (y/N) N
输入上述操作安装完成后,运行项目,环境安装完成
# 进入你的项目目录
cd toutiao-webapp
# 启动开发服务
npm run serve
制作项目一开始时,通常建议对项目的改动进行备份。git 就适合对代码的版本进行管理。
如若需要进行多人协作,就需要创建远程仓库进行托管。
创建远程仓库
前置需要安装 git管理工具,并绑定远程仓库账号
- 以GitHub为例,创建关于本项目的区域
- 添加新项目仓库
- 配置项目名称、项目描述等
本地 Git仓库 上传到 远程仓库
Vue脚手架默认给我们部署了Git仓库,并预先做了一次提交,因此 git init 操作可以忽略
# 创建本地仓库
git init
# 将文件添加到暂存区
git add 文件
# 提交历史记录
git commit -m "提交日志"
# 添加远端仓库地址
git remote add origin 你的远程仓库地址
# 重命名当前默认的 master 分支为 main
git branch -M main
# 推送提交 上传代码到该仓库节点 -u 是保存上传目标信息
git push -u origin main
# 再次提交 [需要有上述的 -u 参数]
git push
效果展示
默认生成的目录不满足我们的开发需求,需要进行一些自定义操作
- 删除部分初始化默认文件
- 新增需要的目录结构
修改 App.vue 文件
<template>
<div id="app">
<h1>黑马头条</h1>
<router-view />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
修改 router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
]
const router = new VueRouter({
routes
})
export default router
删除文件
- src/views/About.vue
- src/views/Home.vue
- src/components/HelloWorld.vue
- src/assets/logo.png
创建以下几个目录
- src/api 目录
- 存储接口封装
- src/utils 目录
- 存储一些工具模块
- src/styles 目录
- index.less 文件,存储全局样式
- 在
main.js
中加载全局样式import './styles/index.less'
完成后的目录结构为
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
└── src
├── api
├── App.vue
├── assets
├── components
├── main.js
├── router
├── utils
├── styles
├── store
└── views
上传图标
通过将素材中的svg图标上传至阿里图标库,得到了图标CSS样式文件
素材下载
导入配置
完成上传后,配置项目文件;
- 在src/styles 下创建 icon.less 文件 (将阿里云图标库得到的 css 样式粘贴到此处)
- 在 src/styles 下创建 index.less 文件
在 mian.js 中引入 less入口文件 (index.less)
// 加载全局样式
import './styles/index.less'
在 index.less 文件中 引入 icon.less
// 加载图标库 图标样式
@import './icon.less';
替换 vue默认图标
vue的 项目图标在根目录的 public 文件夹内,同名文件直接覆盖即可。其他图片素材放置在 src\assets 下
素材下载
完成效果如下
Vant 是一个轻量、可靠的移动端 Vue组件库,开箱即用
支持移动项目中大多数使用场景的 Vue组件库,包含了组件所需的 js 和 css
相关文档:https://www.w3cschool.cn/vantlesson/
Vant组件库:gitee地址
特点
- 提供60多个高质量组件,覆盖移动端各类场景
- 性能极佳,组件平均体积不到1kb
- 完善的中英文文档示例
- 支持 Vue2 & Vue3
- 支持按需引入和主题定制
安装
下载包
# yarn 安装 vue2 版本的 vant
yarn add vant@latest-v2
# npm 安装 vue2 版本的 vant
npm install vant@latest-v2
全部导入
import Vue from 'vue';
// 引入 vant 所有组件
import Vant from 'vant';
import 'vant/lib/index.css';
// 全局注册 vant组件
Vue.use(Vant);
移动端REM适配
如果需要使用 rem 单位进行适配,推荐使用以下两个工具:
- postcss-pxtorem 是一款 PostCSS 插件,用于将 px 单位转化为 rem 单位
- lib-flexible 用于设置 rem 基准值
安装 lib-flexible
下载 lib-flexible 包
# yarn安装
yarn add amfe-flexible
# npm安装
npm i amfe-flexible
在 mian.js 中加载执行该模块
import 'amfe-flexible'
安装 postcss、postcss-pxtorem
下载包
# 下载 postcss postcss-pxtorem
yarn add postcss postcss-pxtorem@5.1.1
创建 postcss.config.js 文件到根目录 并写入以下参数
module.exports = {
plugins: {
// 能够把所有元素的 px 转换成 rem
// rootValue 转换的基准值 (例如一个元素宽是75px 则转换成 rem 为 2rem)
'postcss-pxtorem': {
// lib-flexible 的 REM 适配方案为界面分成十份
// 所以 rootValue 设置为设计稿的十分之一 (vant基于375写的)
// rootValue 除了可以传递传入数值,还可以传入函数,并动态改变
rootValue: 37.5,
// 配置要转换的 CSS属性 (* 为所有,其他则表示只转该属性)
propList: ['*'],
}
}
}
传入的vant样式默认是基于375的尺寸,因此 用户自定义样式的 px 尺寸 会与设计稿的 px 尺寸有所不同。
如若需要让 postcss-pxtorem 进行一个判断。可采用下方代码:
它使得 用户 自定义CSS样式 与 vant组件样式 进行了一个区分。
当使用 vant 组件样式时使用 37.5 数值,使用自定义样式 75 来转换
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue({ file }) {
return file.indexOf('vant') !== -1 ? 37.5 : 75
},
propList: ['*'],
},
},
};
使用上方策略,让 vant 灵活分配 rem 的比例。方便后续写 用户自定义样式 时,可以直接填入设计稿对应 px 数值。
<template>
<div id="app">
<!-- 路由的出口 -->
<router-view />
<h1>黑马头条</h1>
<div>
<!-- 粘贴字体图标 -->
<i class="toutiao toutiao-shanchu"></i>
</div>
<van-button type="primary">主要按钮</van-button>
<van-button type="success">成功按钮</van-button>
<van-button type="default">默认按钮</van-button>
<van-button type="warning">警告按钮</van-button>
<van-button type="danger">危险按钮</van-button>
<van-cell-group>
<van-cell title="单元格" value="内容" />
<van-cell title="单元格" value="内容" label="描述信息" />
</van-cell-group>
<div class="box">helloword</div>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style lang="less">
.box{
width: 555px;
height: 64px;
padding: 20px;
background-color: red;
}
</style>
效果展示
iPhone 12机型尺寸
安装
# npm 下载
npm i axios
# yarn 下载
yarn add axios
配置
项目根目录中创建 utils 文件夹,并在该文件夹中创建 request.js
import axios from 'axios';
const request = axios.create({
// 创建基础路径
baseURL: 'http://toutiao.itheima.net'
})
// 请求拦截器 暂无
// 响应拦截器 暂无
// 导出模块
export default request;
挂载
- 方式1:(简单方便、但是不利于接口维护)
我们可以把请求对象挂载到 Vue.prototype 原型对象中,然后再组件中通过 this.xxx 直接访问
- 方式2: (推荐)
我们把每一个请求都封装成每一个独立的功能函数,在需要的适合加载调用,这种做法更便于接口的管理和维护
完成登录项目的功能,包括样式布局、接口请求、短信验证等功能
在 src/views 文件夹中创建 login 文件夹,并在文件夹中创建 index.vue 文件
<template>
<div class="login-container">登录页面</div>
</template>
<script>
export default {
name: 'LoginIndex',
components: {},
props: {},
}
</script>
<style></style>
修改 src/router 文件夹中 index.js 的路由配置,使用懒加载方式加载 login组件
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
// 路由表
const routes = [
{
path: '/login',
name: 'login',
// [懒加载] vue 会自动加载 views/login 下的 index.vue
component: () => import('@/views/login')
}
]
const router = new VueRouter({
routes
})
export default router
效果展示
通过 /#/login 路由路径成功访问
使用 vant 组件 实现登录界面的铺设
基础铺设
配置并调整 vant 组件中的 From表单 组件样式
<template>
<div class="login-container">
<!-- 导航栏 -->
<van-nav-bar title="登录" />
<!-- 登录表单 -->
<van-form @submit="onSubmit">
<van-field
name="用户名"
placeholder="请输入手机号" />
<van-field
type="text"
name="密码"
placeholder="请输入验证码" />
<div style="margin: 16px;">
<van-button
block
type="info"
native-type="submit">登录</van-button>
</div>
</van-form>
</div>
</template>
<script>
export default {
name: "LoginIndex",
components: {},
props: {},
methods: {
onSubmit(values) {
console.log("submit", values);
}
}
};
</script>
<style scoped lang="less"></style>
效果展示
自定义化样式 – 全局样式
vant组件的基础配置不满足设计稿的需求,因此需要去 index.less 全局样式中覆写对应类的样式
* 通过 F12 审查元素,找到 vant组件 中对应组件的类名,并在 index.less 替换样式 *
1. 在全局样式中设置类名,并覆写vant组件中类的样式
[公共样式将作用于全局]
// ...
body {
background-color: #f5f7f9;
}
.page-nav-bar {
background-color: #3296fa;
.van-nav-bar__title {
color: #fff;
}
}
2. 在vant对应组件中添加该类,不破坏原样式情况下达到覆写样式效果
<template>
<div class="login-container">
<!-- 导航栏 添加类名 -->
<van-nav-bar class="page-nav-bar" title="登录" />
...
</div>
</template>
效果展示
修改自定义样式 – 自定义图标等
完善缺失的内容:icon图标、右侧按钮;使用 less 修改一些默认样式,方便达成设计稿的样式
1. vant输入框组件中 提供了图标属性 left-icon 并内置了 icon图标库,
如若仍不满足业务需要,可使用 组件提供的 具名插槽 left-icon 插入标签
2. 右侧 “发送验证码” 按钮采用 button插槽 给输入框尾部插入按钮。
并在当前组件的局部样式 <style> 中使用 less 做需求样式调整
3. 调整 登录按钮 的颜色和外边距等,方便达到设计稿需求
<template>
<div class="login-container">
<!-- 导航栏 -->
<van-nav-bar class="page-nav-bar" title="登录" />
<!-- 登录表单 -->
<van-form @submit="onSubmit">
<van-field
name="用户名"
placeholder="请输入手机号">
<i slot="left-icon" class="toutiao toutiao-shouji"></i>
</van-field>
<van-field
name="验证码"
placeholder="请输入验证码" >
<i slot="left-icon" class="toutiao toutiao-yanzhengma"></i>
<template #button>
<van-button class="send-sms-btn" round size="small" type="default">
发送验证码
</van-button>
</template>
</van-field>
<div class="login-btn-wrap">
<van-button class="login-btn" block type="info" native-type="submit">
登录
</van-button>
</div>
</van-form>
</div>
</template>
<script>
export default {
name: "LoginIndex",
...
};
</script>
<style scoped lang="less">
.login-container{
.toutiao{
font-size: 37px;
}
.send-sms-btn{
font-size: 22px;
color: #666;
width: 152px;
height: 46px;
background-color: #ededed;
}
.login-btn-wrap{
padding: 53px 33px;
.login-btn{
background-color: #6db4fb;
border: none;
}
}
}
</style>
效果展示
完成用户在界面中输入账号后,发起 ajax请求,并从接口返回成功或失败的信息。
步骤
- 获取表单数据
- 表单验证
- 提交表单请求登录,使用 try{}catch(err){} 捕获错误
- 根据请求响应结果处理后续操作
实际操作
1. 在 data 中定义并使用 v-mode 绑定手机号、验证码数据
<template>
...
<!-- 登录表单 -->
...
<van-field
v-model="user.mobile"
name="手机号"
placeholder="请输入手机号">
...
</van-field>
<van-field
v-model="user.code"
name="验证码"
placeholder="请输入验证码" >
...
</van-field>
...
</div>
</template>
<script>
export default {
data(){
return{
user:{
mobile:'', // 手机号
code:'' // 验证码
}
}
},
...
};
</script>
2. 在 src/user 中创建 user.js 文件,作为登录接口文件,写入接口请求
// 引用公共接口
import request from '@/utils/request';
export const login = data => {
return request({
method: 'POST',
url: '/v1_0/authorizations',
data
})
}
3. 引入登录请求文件,并使用绑定数据发起请求
使用接口测试账号[13911111111] 验证码 [246810]
// ...
import { login } from "@/api/user.js";
export default {
// ...
data() {
return {
user: {
mobile: "", // 手机号
code: "" // 验证码
}
};
},
methods: {
// 登录按钮单击事件
async onSubmit() {
const user = this.user;
// 尝试捕获错误
try {
// 等待接收请求数据
const res = await login(user);
// 完成登录
console.log("登录成功", res);
} catch (err) {
if (err.response.status === 400) {
// 捕获失败结果 返回失败信息
console.log("手机号或验证码错误", err);
} else {
console.log("登录失败,请稍后再试", err);
}
}
}
}
};
效果展示
F12 控制台提示登录成功
使用vant组件中 轻提示 方式在前端页面中提示用户请求登录后返回的 登录的状态
属性介绍
特性
- 使用 Toast.loading 方法展示加载提示,通过 forbidClick 属性可以禁用背景点击
- Toast 默认采用单例模式,即同一时间只会存在一个 Toast
- Toast 轻提示中目前使用有 loading [加载提示] => success [成功提示] || fail [失败提示]
API介绍
方法名 | 说明 | 参数 | 返回值 |
---|---|---|---|
Toast | 展示提示 | options | message |
toast 实例 |
Toast.loading | 展示加载提示 | options | message |
toast 实例 |
Toast.success | 展示成功提示 | options | message |
toast 实例 |
Toast.fail | 展示失败提示 | options | message |
toast 实例 |
Toast.clear | 关闭提示 | clearAll: boolean |
void |
Toast.allowMultiple | 允许同时存在多个 Toast | – | void |
Toast.setDefaultOptions | 修改默认配置,对所有 Toast 生效。 传入 type 可以修改指定类型的默认配置 |
type | options |
void |
Toast.resetDefaultOptions | 重置默认配置,对所有 Toast 生效。 传入 type 可以重置指定类型的默认配置 |
type |
void |
实际操作
1. 引入 vant轻提示 函数,通过 this.$toast.loading({}) 调用提示
[如若输入 0 ,则 loading 状态持续,并加载提示动画持续展示]
methods: {
// 登录按钮单击事件
async onSubmit() {
// ...
// 轻提示
this.$toast.loading({
// 提示内容
message: "加载中...",
// 禁用背景点击
forbidClick: true,
// 持续实际 默认为 2000 毫秒
// 如果该值为 0 则持续展示
duration: 2000
});
// ...
}
}
2. 通过 this.$toast.success() 返回调用成功提示,会结束之前 toast 提示
[任何一个新的 toast提示 被调用,都会结束上一个 任何的 toast提示]
methods: {
// 登录按钮单击事件
async onSubmit() {
const user = this.user;
// 轻提示
this.$toast.loading({
// 提示内容
message: "加载中...",
// 禁用背景点击
forbidClick: true,
// 持续实际 默认为 2000 毫秒
// 如果该值为 0 则持续展示
duration: 2000
});
// 尝试捕获错误
try {
// 等待接收请求数据
const res = await login(user);
// 完成登录
this.$toast.success("登录成功");
} catch (err) {
if (err.response.status === 400) {
// 捕获失败结果 返回失败信息
this.$toast.fail("手机号或验证码错误");
} else {
this.$toast.fail("登录失败,请稍后再试");
}
}
}
}
效果展示
使用 vant-from 中自带是表单验证属性来验证用户的输入的错误内容,并作出操作
属性介绍
:rules=”[{ pattern, message: ‘请输入正确内容’ }]”
vant-from 中的 rules 属性可以实现验证的操作,可在它数组参数中传入验证规则等配置对象,
当配置多个验证对象,rules 会从上到下方式依次尝试完成验证。
[它自动配置了拦截,当表单验证通过时才会触发 submit 事件,如果验证失败不会触发 submit 事件]
rules 属性值
键名 | 说明 | 类型 |
---|---|---|
required | 是否为必选字段,当值为空值时(空字符串、空数组、false 、undefined 、null ),校验不通过 |
boolean |
message | 错误提示文案,可以设置为一个函数来返回动态的文案内容 | string | (value, rule) => string |
validator | 通过函数进行校验,可以返回一个 Promise 来进行异步校验 | (value, rule) => boolean | string | Promise |
pattern | 通过正则表达式进行校验,正则无法匹配表示校验不通过 | RegExp |
trigger | 设置本项规则的触发时机,优先级高于 Form 组件设置的 validate-trigger 属性,可选值为
onChange 、onBlur 、onSubmit
|
string | string[] |
formatter | 格式化函数,将表单项的值转换后进行校验 | (value, rule) => any |
validateEmpty v3.6.0 |
设置 validator 和 pattern 是否要对空值进行校验,默认值为 true ,可以设置为
false 来禁用该行为
|
boolean |
实际操作
1. 为 vant-from 中的 van-field 标签添加 rules 验证属性,配置验证规则
[在 data 中创建验证对象,并引用在 van-field 的 rules 验证规则参数中]
<template>
// ...
<van-form @submit="onSubmit">
<van-field
// ...
:rules="userFromRules.mobile"
type="number"
maxlength="11"
>
// ...
</van-field>
<van-field
// ...
:rules="userFromRules.code"
type="number"
maxlength="6"
// ...
</van-field>
// ...
</van-form>
</div>
</template>
data() {
//...
userFromRules: {
mobile: [
{
required: true,
message: "手机号不能为空"
},
{
pattern: /^1[3|5|7|8]\d{9}$/,
message: "手机号格式错误"
}
],
code: [
{
required: true,
message: "验证码不能为空"
},
{
pattern: /^\d{6}$/,
message: "验证码格式错误"
}
]
}
};
效果展示