heima头条项目【一】

一、前提

1.项目初始化

在这里插入图片描述

Babel 把js语法进行翻译降级
TypeSCript 基于JavaScript封装的一个超类,js是弱类型语言,ts是强类型语言
PWA脱机应用
Router路由
后面两个是测试用需要的

2.常见错误

在这里插入图片描述
这种一般是Eslint错误

规范文档:🔗

规范文档2:🔗

规范文档3:🔗

ESLint在哪里生效? webpack开发服务器+ESLint配置检查

3.eslint配置

// 目标1: 有2处在检查我的代码
// vscode+eslint插件+工作区根目录下.eslinrc.js配置, 在保存时, 检查代码
// 如果在写代码过程中用插件解决了问题, webpack里就不会报错了
// webpack开发服务器(在下面终端中)+eslit插件, 在保存时, 检查代码

4.Git配置

git remote add origin git@gitee.com:jcicy/toutiao.git
git push -u origin "master"

在这里插入图片描述

5.下载vant

yarn add van@2.12.34

二、统一管理请求的接口

1.封装axios函数

之前的方法

import theAxios from 'axios'

// 基于axios封装网络请求
// 每个程序员的想法都不一样, 封装的地方和名字都不一样, 但是思想相同

const axios = theAxios.create({
  baseURL: 'http://geek.itheima.net',
  timeout: 20000 // 20秒超时时间(请求20秒无响应直接判定超时)
})

export default axios

// 但是上面有局限性
// 导出的axios方法在使用时
/*
// 我在逻辑页面调用时, 传入的这5个配置名字
    axios({
        url: '请求地址',
        method: '请求方式',
        params: {},
        data: {},
        headers: {}
    })
*/
// 问题来了, 万一将来我要更新request.js里封装网络请求的工具
// 把axios换成jquery的$.ajax
// import $ from 'jquery'
// export default $.ajax
/*
 $.ajax({
    url: '请求地址',
    type: '请求方式',
    data: {}, // 没有params
    headers: {}
 })
*/

jquery中文文档🔗

解决方案:一摸一样的控制面板、高级的设置模式

以后换库, 只需要改这里, 逻辑页面不用动, 保证代码的复用性和独立性(高内聚低耦合)

//导出自定义函数, 参数对象解构赋值
export default ({
  url,
  method = 'GET',
  params = {},
  data = {},
  headers = {}
}) => {
  return axios({
    url,
    method,
    params,
    data,
    headers
  })
}
export default ({
  url,
  method = 'GET',
  params = {},
  data = {},
  headers = {}
}) => {
//以后换库, 只需要改这里, 逻辑页面不用动, 保证代码的复用性和独立性(高内聚低耦合)
  return new Promise((resolve, reject) => {
    $.ajax({
      url,
      data,
      headers,
      type: method,
    success: (res) => {
    resolve(res)
   },
	error: err => {
 reject(err)
 }
    })
  })
}

小结:
1.为什么要二次封装 axios函数
为了让代码更加灵活,统一管理
2.axios.create作用
创建返回一个新的axios函数对象

2.封装接口方法

// 统一封装接口方法
// 每个方法负责请求一个url地址
// 逻辑页面, 导入这个接口方法, 就能发请求咯
// 好处: 请求url路径, 可以在这里统一管理
import axios from '@/utils/request'

// 频道 - 获取所有频道
// export const getAllChannelsAPI = () => {
//   return axios({
//     url: '/v1_0/channels',
//     method: 'GET'
//   })
// }
// 方法在逻辑页面调用要记得return
// 这里可以简写为 箭头函数return 大括号可以省略
// 默认把结果返回到函数调用的方法
// 接口方法, 只负责调用一个接口, 返回一个Promise对象
export const getAllChannelsAPI = () =>
  axios({
    url: '/v1_0/channels',
    method: 'GET'
  })

测试这个方法
在app.vue中导入过来, 尝试发起一个请求

import { getAllChannelsAPI } from '@/api/index'
export default {
  async created() {
    const res = await getAllChannelsAPI()
    console.log(res)
  }
}

在这里插入图片描述

3.try和catch的使用

如何捕获await错误情况?

await用于取代then函数, 等待Promise成功结果提取在原地
await无法获取Promise失败的结果, 一旦失败Promise错误直接抛出到控制台

解决方案:使用JS里内置语法, try+catch

/*
try {
	// 可能会报错的代码(例如await)
} catch (err) {
//抛出错误
	// try里代码报错, 捕捉到这里执行
}
*/
 async created() {
    // try加catch捕获await同步代码的错误
    try {
      const res = await getAllChannelsAPI()
      console.log(res)
    } catch (err) {
      // err参数就是拿到的错误对象
      // 给用户来个弹窗提示-程序出错了
      // console.dir()详细打印
      console.dir(err)
    }
  }

在这里插入图片描述

5.登录页面-路由准备-页面文件创建

步骤:
1.src/views/Login/index.vue - 作为登录页面 - 先随意弄写标签显示

这里一般不是引入到app.vue 而是配置路由
2.src/router/index.js - 添加登录的路由规则

import Login from '@/views/Login'

{
    path: '/',
    redirect: '/login'
  },
  {
    path: '/login',
    component: Login
  }

3.路由给挂载点, 在App.vue中

<router-view></router-view>

4.打开页面测试下, 是否能显示登录页面

6.登录页面-头部导航-vant组件使用

// 目标2: 组件使用套路
// 1. 明确目标, 找到类似组件
// 2. 引入注册然后复制过来
// 3. 读和删没用的
// 4. 修改, 改成我们想要的样子
// 样式修改:
// (1): 找到类名, 自己写css覆盖掉它
// (2): 看文档, 是否支持自定义样式

找背景类名

.van-nav-bar{
   background: #007bff;
}

在这里插入图片描述
文字颜色
写了类名还是不行,因为加了scoped

/* /deep/ 就是把data-v-hash值选择器写到类名的前面 */
/deep/ .van-nav-bar__title{
	color: white;
}
<style scoped lang="less">
/* 此类名是van-nav-bar组件内根标签 */
// .van-nav-bar {
//   background-color: #007bff;
// }

/* 此选择器名字是van-nav-bar组件内标签
scoped尝试把此选择器后面加上属性选择器匹配当前页面标签 (选不中组件内部的) */
// lang="less" 当前style标签内是less语法
// 用/deep/就不会被vscode标记红线
// /deep/ 会把属性选择器加到前面 (用后代选择器的方式往里找匹配的类名)
// 结论: 要修改组件内样式, 如果你用了scoped, 就需要在选择器前/deep/即可
// /deep/ .van-nav-bar__title {
//   color: white;
// }
</style>

在这里插入图片描述
因为加了scoped 所以不会显示,这个标签没有加自定义属性。webpack打包时给加上自定义属性。

结论: 要修改组件内样式, 如果你用了scoped, 就需要在选择器前/deep/即可

7.vant组件自定义样式

配置完成后要重启服务器
方法二:

 console.log(__dirname) // 当前文件, 所在文件夹, 的绝对路径

因为eslint的存在,需要path.join拼接

// 不要手动写绝对路径, 用代码来动态获取, 绝对地址
const path = require('path')

 // 或者可以通过 less 文件覆盖(文件路径为绝对路径)
          hack: `true; @import "${path.join(__dirname, 'src/styles/cover.less')}";`

8.登陆表单_准备

1.输入框name 名称,提交表单的标识符,表单提交时,默认收集一个提交对象
2.rules 表单校验规则 :属性名=”表达式" 不加冒号是字符串
3. 属性后面无值, 默认值为true
block代表块级元素
type代表类型(有默认颜色)
native-type代表原生button的type属性
代表这个van-button组件渲染的原生button标签type是submit提交整个表单功能的按钮

9登陆表单-微调_完成页面铺设

name对应后台的参数名
label左侧文字

// 目标1: 实现顶部导航->自定义样式
// 目标2: 实现表单组件->读,改,加
// 目标3: 收集值以后, 调用接口->查看登录结果
// 目标4: 点击登录后给用户提示(正在登陆中~~~), 防止用户频繁的点击

 methods: {
    // {mobile: '13888888888', code: '246810'}
    onSubmit(values) {
      console.log('submit', values)
      console.log(this.user)
    }
  }
/^1[3-9]\d{9}$/
		第1位:只能是1
        第2位:[34578]

        第3位之后,必须是9位数字

10.登录接口调用

axios内部,会把参数对象转成json字符串格式发给后台

axios内部会自动携带请求参数headers里Content-type:‘application/json’帮你添加好

11.network

https://vant-contrib.gitee.io/vant/v2/#/zh-CN/notify

12.优化

async onSubmit(values) {
      // console.log('submit', values)
      // console.log(this.user)
      this.isLoading = true
      try {
        const res = await loginAPI(this.user)
        console.log(res)
        Notify({ type: 'success', message: '登陆成功!' })
      } catch (err) {
        Notify({ type: 'danger', message: '账号或者验证码输入错误' })
      }
      // 请求后 无论成功还是失败 把状态关掉
      this.isLoading = false
    }

13.token本地存储

// 此文件->封装3个方法->专门用于操作token的
// 封装点东西: 目的: 代码分层, 更方便清晰, 以后修改方便
// 本地存储存的是字符串  (JSON字符串是字符串的一种)
const key = 'geek-itheima'
// 设置
export const setToken = token => {
  localStorage.setItem(key, token)
}
// 获取
export const getToken = () => {
  localStorage.getItem(key)
}

// 删除
export const removeToken = () => {
  localStorage.removeItem(key)
}

setToken(res.data.data.token)

在这里插入图片描述

14.布局页面-登录跳转到这儿

 // 跳转一定要写在最后->尽量最后执行
 // location.href -> 当前浏览器地址和要跳转的地址一样(不包含#后面锚点信息) -> 不会刷新网页
 // 地址改变, 就会导致网页刷新
 // this.$router.push() 压栈(会产生历史记录, 可以回退), this.$router.replace() 替换(不会产生历史记录)
 this.$router.replace({
path: this.$route.query.path || '/layout/home' 
// 因为我们路由规则里/layout里没有重定向, 所以直接在这里写全
 })

小结:
1.router和route区别是?

$router下用于跳转路由

$route是路由信息对象

2.路由的push和replace方法区别?

push跳转后, 可以返回

replace跳转后, 无法返回

15.顶部导航插槽

使用插槽:占位+template

1.为何插槽看不见slot标签?

因为你用的vant组件, 组件内部写好了slot, 你只需要使用即可

2.JS里引入图片为何import

因为脚手架底层运作是webpack, 图片会认为是模块, 需要模块化导入

v-slot:可以简写为#

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值