Vue黑马头条移动端-Day1-源码分析

------------恢复内容开始------------

1、任何放置在 public 文件夹的静态资源都会被简单的复制,而不经过 webpack。

===所以在public下的文件其实可以直接通过比如 html/index.html直接访问,不用再通过复杂的相对定位这些东西来搞的

2、App.vue 根组件,最终被替换渲染到 index.html 页面中 #app 入口节点

3、main.js 整个项目的启动入口模块

 

移动端 REM 适配

 

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

 

  • postcss-pxtorem 是一款 postcss 插件,用于将 px 单位转化为 rem

 

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

 

4、

然后在 src/styles/index.less 中加载 icon.less

 

/**
 * 全局样式
 */

@import "./icon.less";


英语index。less已经引入了main.js。所以icon。less直接引入index。less中即可了


最后就是如何使用:使用 i 标签,给两个类名,一个是字体类名 toutiao,一个是图标类名 toutiao-xxx

 

<!-- 手机图标 -->
<i class="toutiao toutiao-shouji"></i>

<!-- 收藏图标 -->
<i class="toutiao toutiao-shoucang"></i>

==也就是iconfont主要用到的标签可以是i标签这样的

而vant中图标的使用的话

使用 Vant 中的图标

 

Vant 组件库内置了一套非常精致的字体图标,除基本功能之外还支持徽标提示等功能。

 

<!-- 基本展示 -->
<van-icon name="chat-o" />

<!-- 设置dot属性后,会在图标右上角展示一个小红点 -->
<van-icon name="chat-o" dot />

<!-- 设置badge属性后,会在图标右上角展示相应的徽标 -->
<van-icon name="chat-o" badge="9" />

也就是说一个是通过class文件来搞的,一个就是通过在van-icon中通过name来搞的

 

 也就是

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

// 路由表
const routes = [
  {
    path: '/login',
    name: 'login',
    component: () => import('@/views/login/')
  },
  {
    path: '/',
    component: () => import('@/views/layout/'),
    children: [
      {
        path: '', // 默认子路由
        name: 'home',
        component: () => import('@/views/home/')
      },
      {
        path: '/qa',
        name: 'qa',
        component: () => import('@/views/qa/')
      },
      {
        path: '/video',
        name: 'video',
        component: () => import('@/views/video/')
      },
      {
        path: '/my',
        name: 'my',
        component: () => import('@/views/my/')
      }
    ]
  }
]

const router = new VueRouter({
  routes
})

export default router

也就是说tabbar页面都是布局组件的子组件,作为默认子路由就直接path:' '直接为空就行了

 

拓展:vuerouter

路由中有三个基本的概念 route, routes, router。

    1, route,它是一条路由,由这个英文单词也可以看出来,它是单数, Home按钮  => home内容, 这是一条route,  about按钮 => about 内容, 这是另一条路由。

    2, routes 是一组路由,把上面的每一条路由组合起来,形成一个数组。[{home 按钮 =>home内容 }, { about按钮 => about 内容}]

    3, router 是一个机制,相当于一个管理者,它来管理路由。因为routes 只是定义了一组路由,它放在哪里是静止的,当真正来了请求,怎么办? 就是当用户点击home 按钮的时候,怎么办?这时router 就起作用了,它到routes 中去查找,去找到对应的 home 内容,所以页面中就显示了 home 内容。

    4,客户端中的路由,实际上就是dom 元素的显示和隐藏。当页面中显示home 内容的时候,about 中的内容全部隐藏,反之也是一样。客户端路由有两种实现方式:基于hash 和基于html5 history api.

 

 1, 页面实现(html模版中)

    在vue-router中, 我们看到它定义了两个标签<router-link> 和<router-view>来对应点击和显示部分。<router-link> 就是定义页面中点击的部分,<router-view> 定义显示部分,就是点击后,区配的内容显示在什么地方。所以 <router-link> 还有一个非常重要的属性 to,定义点击之后,要到哪里去, 如:<router-link  to="/home">Home</router-link>

  2, js 中配置路由

 

 

结:也就是根组件App.vue。通过在 App.vue中 定义<router-link > 和 </router-view>  ,如何通过src-》router文件来配置路由,在router中把router export出来,如何在App。vue中展现

就可以把各个页面都在APP.vue里面呈现了,然后把App。vue的东西直接挂载到public中的index。html中即可

 

封装请求模块

 

和之前项目一样,这里我们还是使用 axios 作为我们项目中的请求库,为了方便使用,我们把它封装为一个请求模块,在需要的时候直接加载即可。

 

安装 axios:

 

npm i axios

 

创建 src/utils/request.js

 

/**
 * 封装 axios 请求模块
 */
import axios from "axios"

const request = axios.create({
  baseURL: "http://ttapi.research.itcast.cn/" // 基础路径
})

export default request

这里就是通过baseurl把我们要请求接口的根目录赋值为了request,什么时候想要调用里面的接口的话就可以直接通过request来搞了


哪里使用,哪里加载:

 

import request from '@/utils/request'

request({
  method: 'xxx',
  url: 'xxx',
  ...
})




二、登陆注册
①顶部标题栏,设置title和左箭头来实现返回到上一页面中去
  <van-nav-bar
      title="登录"
      left-arrow
      @click-left="$router.back()"
    />

②登陆的整体表单外面需要通过一个van-cell-group,可以使得内部是有序的排列的(由于我们这个登陆页面的nav-bar写完之后,可以不配置样式,会直接使用全局中队nav-bar配置的样式的

注意:van-cell-group 仅仅是提供了一个上下外边框,能看到包裹的区域

 <van-cell-group>
      <van-field
        v-model="user.mobile"    //这里就是输入的东西了通过v-model,v-model里面的东西都要在下面的return data数据域里面进行定义的
        left-icon="smile-o"      //这里就是左边的图标
        placeholder="请输入手机号"
      />
      <van-field
        v-model="user.code"
        clearable                //是否是否启用清除图标,点击清除图标后会清空输入框      
     left
-icon="music-o" placeholder="请输入验证码" > <template #button> //在这个van-field中再嵌套一个button按钮来“发送验证码”,也就是可以通过这样的格式 template #button 这里#后面是slot插槽的类别 <van-button size="small" round >发送验证码</van-button> </template> </van-field> </van-cell-group>

 

 

 

##拓展:

写样式的原理:将公共样式写到全局(src/styles/index.less),将局部样式写到组件内部。

然后再把全局的演示index。less导入到main。js里面,就可以给作为各个页面的公共样式了

/**
 * 全局样式
 */
@import "./icon.less";

body {
  background-color: #f5f7f9;
}

.app-nav-bar {
  background-color: #3296fa !important;
  .van-nav-bar__title {
    color: #fff;
  }
  .van-icon {
    color: #fff !important;
  }
}

这里就是把iconfont里面的引入到全局了,然后把顶部van-nav-bar的样式和整个body的背景颜色都定义了

 

③实现基本登陆功能

思路:

  • 注册登录按钮点击事件
  • 获取表单数据(根据接口要求使用 v-model 绑定)
  • 表单验证
  • 请求提交
  • 处理响应结果

一般我们会根据接口传入数据类型的要求,会直接提前在return data数据域中把这个数据类型就定义好了

比如‘:

...
data () {
  return {
    user: {
      mobile: '',
      code: ''
    }
  }
}

 

请求登录

 

创建 src/api/user.js 模块,封装登录请求方法:

 

/**
 * 用户相关的请求模块
 */
import request from "@/utils/request"

/**
 * 用户登录
 */
export const login = data => {
  return request({
    method: 'POST',
    url: '/app/v1_0/authorizations',
    data
  })
}

 

给登录按钮注册点击事件。==也就是我们的button添加上一个点击事件即可了

 

登录处理函数如下。

 

import { login } from '@/api/user'

async onLogin () {
  try {
    const res = await login(this.user)
    console.log('登录成功', res)
  } catch (err) {
    if (err.response.status === 400) {
        console.log('登录失败', err)
    }
  }
}
这里通过try catch 异步的来调用接口获取到数据

登录状态提示

 

Vant 中内置了Toast 轻提示组件,可以实现移动端常见的提示效果。

 

===提示:在组件中可以直接通过 this.$toast 调用。

 

==为我们的登陆功能增加弹窗提醒的功能

async onLogin () {
  // 开始转圈圈
  this.$toast.loading({
    duration: 0, // 持续时间,0表示持续展示不停止
    forbidClick: true, // 是否禁止背景点击
    message: '登录中...' // 提示消息
  })

  try {
    const res = await request({
      method: 'POST',
      url: '/app/v1_0/authorizations',
      data: this.user
    })
    console.log('登录成功', res)
    // 提示 success 或者 fail 的时候,会先把其它的 toast 先清除
    this.$toast.success('登录成功')
  } catch (err) {
    console.log('登录失败', err)
    this.$toast.fail('登录失败,手机号或验证码错误')
  }
}

===如果想要进行测试的话:如果请求非常快的话就看不到 loading 效果了,这里可以在调试工具中将网络设置为慢速模式模拟低速网络。测试结束,再把网络设置恢复为 Online 正常网络。

 

表单验证   

1)基本使用

 

  • 使用 van-form 组件包裹所有的表单项 van-field
  • 监听 form 的 submit 事件
    • 当表单提交的时候会触发 submit 事件
    • 只有表单验证通过,它才会被触发调用
  • 使用 Field 的 rules 属性定义校验规则

===field中rules一般都是定义这个输入框一定要填写上东西

<van-form @submit="onSubmit">
  <van-field
    v-model="username"
    name="用户名"
    label="用户名"
    placeholder="用户名"
    :rules="[{ required: true, message: '请填写用户名' }]"
  />
  <van-field
    v-model="password"
    type="password"
    name="密码"
    label="密码"
    placeholder="密码"
    :rules="[{ required: true, message: '请填写密码' }]"
  />
  <div style="margin: 16px;">
    <van-button round block type="info" native-type="submit">
      提交
    </van-button>
  </div>
</van-form>
export default {
  data() {
    return {
      username: '',
      password: '',
    };
  },
  methods: {
    onSubmit(values) {
      console.log('submit', values);
    },
  },
};

这里的form通过@submit绑定了监听事件,也就是监听submit函数的触发,所以我们就可以把下面的button定义为一个submit上交的按钮类型

====校验规则

 

并且就可以想到我们通过每一个field都会进行校验,那么如果校验错误了要怎么提醒用户了,就可以使用外层的form来监听这个错误的事件

 

在vue里面很多组件都是这样的,都是通过布尔来控制提示的文字要不要发,然后通过一个String来定义提示的内容,然后通过@来监听某一个事件并且定义事件监听触发函数

这里就是通过show-error来判断要不要提示,通过show-error-message来说明提示什么文字,然后监听failed事件,定义onfailed函数

这个onfailed是可以直接拿到错误error并且作为参数值的

 

验证码处理

在验证码处理之前,也就是把这个验证码发送给用户之前的话,要对用户输入的手机号进行验证才行的,所以就是要验证手机号而不用验证整个表单

这个时候就用部了form的failed事件监听了

 通过查阅文档可以看到 Form 组件的实例方法 validate 可以用来手动触发表单验证,并且支持传入 name 来验证单个表单项。

 

  • 给 Form 添加 ref 属性用来获取组件实例

 

  • 给 Field 添加 name 属性用来验证单个表单项

 

  • 监听发送按钮的点击事件

 

    • 由于 Form 中的任何按钮点击都会触发表单的默认提交行为,所以这里使用 .prevent 修饰符阻止默认行为

这里获取单个元素的话可以类比我们写css那种,id用#,class用。但是如果要在js里面访问元素dom节点的把,可能会想到通过getclassby这种函数

但是vue组件里面就提供了一个更加方便的,通过ref来先找到我们的form表单结构,然后就可以指定表单内部的某一个name属性的dom节点了

 

async onSendSms () {
  try {
    // 校验手机号码
    await this.$refs['login-form'].validate('mobile')
        // 验证通过 -> 请求发送验证码 -> 用户接收短信 -> 输入验证码 -> 请求登录
    // 请求发送验证码 -> 隐藏发送按钮,显示倒计时
    // 倒计时结束 -> 隐藏倒计时,显示发送按钮
  } catch (err) {
    this.$toast({
      message: err.message,
      position: 'top'
    })
  }
}

 

请求发送短信

/**
 * 发送短信验证码
 */
export const sendSms = mobile => {
  return request({
    method: 'GET',
    url: `/app/v1_0/sms/codes/${mobile}`
  })
}

就是加入要在请求接口中url里面要添加上我们的数据的话,外层就要通过   ` `   来保住,然后后面通过${   }把我们的数据拼接到url链接的后面即可了

async onSendSms () {
  try {
    // 校验手机号码
    await this.$refs['login-form'].validate('mobile')
    // 验证通过,请求发送验证码
    await sendSms(this.user.mobile)
  } catch (err) {
    // try 里面任何代码的错误都会进入 catch
    // 不同的错误需要有不同的提示,那就需要判断了
    let message = ''
    if (err && err.response && err.response.status === 429) {
      // 发送短信失败的错误提示
      message = '发送太频繁了,请稍后重试'
    } else if (err.name === 'mobile') {
      // 表单验证失败的错误提示
      message = err.message
    } else {
      // 未知错误
      message = '发送失败,请稍后重试'
    }

    // 提示用户
    this.$toast({
      message,
      position: 'top'
    })
  }
}

如果是把验证手机号还有发送验证码到用户写在一起的把,通过try catch,catch中进入的错误可能是不同的

所以就可以定义一个message来分不同情况下,赋值不同的值,然后在最后的时候就可以通过this.$toast提示给用户l

await this.$refs['login-form'].validate('mobile')

 可见通过这种方法获取到DOM节点的话也是要使用await异步来实现的

async onSendSms () {
  try {
    // 校验手机号码
    await this.$refs['login-form'].validate('mobile')
    // 验证通过,请求发送验证码
    await sendSms(this.user.mobile)
  } catch (err) {
    // try 里面任何代码的错误都会进入 catch
    // 不同的错误需要有不同的提示,那就需要判断了
    let message = ''
    if (err && err.response && err.response.status === 429) {
      // 发送短信失败的错误提示
      message = '发送太频繁了,请稍后重试'
    } else if (err.name === 'mobile') {
      // 表单验证失败的错误提示
      message = err.message
    } else {
      // 未知错误
      message = '发送失败,请稍后重试'
    }

    // 提示用户
    this.$toast({
      message,
      position: 'top'
    })
  }
}

也就是说如果是未知错误的话,就可以直接不负责任的“发送失败,重试就行”

 

请求期间禁用按钮点击

记住一个原则:任何和网络交互有关的视图都应该在网络请求期间禁用,防止请求过慢导致多次触发请求行为。

 

拓展:click.prevent

@click.prevent="onSendSms"

这个放在van-button上面的话,其实就是因为form表单框架一个,只要有一个button点击了就会立马执行他的submit触发事件

就会验证整个表单输入数据了,但是我们不希望是这样的,就要阻止form这种静默的行为,这个代码的意思就是,阻止form触发submit只运行onSendSms这个函数

async onSendSms () {
  try {
    // 校验手机号码
    await this.$refs['login-form'].validate('mobile')

    // 验证通过,请求发送验证码
+    this.isSendSmsLoading = true // 展示按钮的 loading 状态,防止网络慢用户多次点击触发发送行为
    await sendSms(this.user.mobile)

    // 短信发出去了,隐藏发送按钮,显示倒计时

    // 倒计时结束 -> 隐藏倒计时,显示发送按钮(监视倒计时的 finish 事件处理)
  } catch (err) {
    // try 里面任何代码的错误都会进入 catch
    // 不同的错误需要有不同的提示,那就需要判断了
    let message = ''
    if (err && err.response && err.response.status === 429) {
      // 发送短信失败的错误提示
      message = '发送太频繁了,请稍后重试'
    } else if (err.name === 'mobile') {
      // 表单验证失败的错误提示
      message = err.message
    } else {
      // 未知错误
      message = '发送失败,请稍后重试'
    }

    // 提示用户
    this.$toast({
      message,
      position: 'top'
    })
  }

  // 无论发送验证码成功还是失败,最后都要关闭发送按钮的 loading 状态
+  this.isSendSmsLoading = false
}

 

处理倒计时

我们可以使用 Vant 中的 CountDown 倒计时 轻松的实现这个功能。下面是具体的处理流程。

 

在 data 中添加数据用来控制倒计时的显示和隐藏:

 

这里的time是通过毫秒来算的,这里的1000其实就是1秒,再乘以60的话,其实就是进行了60秒的倒计时了

format="ss s"这种形式的话,其实就是因为从0到60的话,如果是从0到9的话,就是通过format“s“这个个位数的格式了

如果是从10开始一直到60的话就是通过format("ss”)这种格式了

 

async onSendSms () {
  try {
    // 校验手机号码
    await this.$refs['login-form'].validate('mobile')

    // 验证通过,请求发送验证码
    this.isSendSmsLoading = true // 展示按钮的 loading 状态,防止网络慢用户多次点击触发发送行为
    await sendSms(this.user.mobile)

    // 短信发出去了,显示倒计时,关闭发送按钮
+    this.isCountDownShow = true

    // 倒计时结束 -> 隐藏倒计时,显示发送按钮(监视倒计时的 finish 事件处理)
  } catch (err) {
    // try 里面任何代码的错误都会进入 catch
    // 不同的错误需要有不同的提示,那就需要判断了
    let message = ''
    if (err && err.response && err.response.status === 429) {
      // 发送短信失败的错误提示
      message = '发送太频繁了,请稍后重试'
    } else if (err.name === 'mobile') {
      // 表单验证失败的错误提示
      message = err.message
    } else {
      // 未知错误
      message = '发送失败,请稍后重试'
    }

    // 提示用户
    this.$toast({
      message,
      position: 'top'
    })
  }

  // 无论发送验证码成功还是失败,最后都要关闭发送按钮的 loading 状态
  this.isSendSmsLoading = false
  
  // 发送失败,显示发送按钮,关闭倒计时
+  this.isCountDownShow = false
}

 

用户如果成功的登陆之后,接口会返回一个token值,这个值就是进入到小程序的一个令牌了

但是我们只有在第一次用户登录成功之后才能拿到 Token。

 

所以为了能在其它模块中获取到 Token 数据,我们需要把它存储到一个公共的位置,方便随时取用。

 

往哪儿存?

 

  • 本地存储(不推荐)
    • 获取麻烦
    • 数据不是响应式
  • Vuex 容器(推荐)
    • 获取方便
    • 响应式的

 

使用容器存储 Token 的思路:

  • 登录成功,将 Token 存储到 Vuex 容器中
    • 获取方便
    • 响应式
  • 为了持久化,还需要把 Token 放到本地存储
    • 持久化
async onLogin () {
  // Toast.loading({
  this.$toast.loading({
    message: '登录中...', // 提示文本
    forbidClick: true, // 禁止背景点击
    duration: 0 // 展示时长(ms),值为 0 时,toast 不会消失
  })
  // 1. 找到数据接口
  // 2. 封装请求方法
  // 3. 请求调用登录
  try {
    const { data } = await login(this.user)

    // 4. 处理响应结果
    this.$toast.success('登录成功')

    // 将后端返回的用户登录状态(token等数据)放到 Vuex 容器中
+    this.$store.commit('setUser', data.data)
  } catch (err) {
    console.log(err)
    this.$toast.fail('登录失败,手机号或验证码错误')
  }
},

这里的

  this.$store.commit('setUser', data.data)
因为此时的this表示的是src这个目录
store是src目录下的一个子目录,可以就进入到这个文件里面,请求调用setUser这个函数

import Vue from 'vue'
import Vuex from 'vuex'
import { getItem, setItem } from '@/utils/storage'

Vue.use(Vuex)

// 这样做的目的可以避免访问和获取数据的名字不一致导致的问题
const USER_KEY = 'TOUTIAO_USER'

export default new Vuex.Store({
  state: {
    user: getItem(USER_KEY) // 当前登录用户的登录状态(token等数据)
    // user: JSON.parse(window.localStorage.getItem('user')) // 当前登录用户的登录状态(token等数据)
  },
  mutations: {
    setUser (state, data) {
      state.user = data

      // 为了防止页面刷新数据丢失,我们还需要把数据放到本地存储中,这里仅仅是为了持久化数据
      setItem(USER_KEY, state.user)
      // window.localStorage.setItem('user', JSON.stringify(state.user))
    }
  },
  actions: {
  },
  modules: {
  }
})

mutations里面的state参数其实是上面的那个state他表示一种全局的状态

 

关于 Token 过期问题

登录成功之后后端会返回两个 Token:

 

  • token:访问令牌,有效期2小时
  • refresh_token:刷新令牌,有效期14天,用于访问令牌过期之后重新获取新的访问令牌

 

我们的项目接口中设定的 Token 有效期是 2 小时,超过有效期服务端会返回 401 表示 Token 无效或过期了。

 

为什么过期时间这么短?

 

  • 为了安全,例如 Token 被别人盗用

 

过期了怎么办?

 

  • 让用户重新登录,用户体验太差了
  • 使用 refresh_token 解决 token 过期

 

如何使用 refresh_token 解决 token 过期?

 

到课程的后面我们开发的业务功能丰富起来之后,再给大家讲解 Token 过期处理。

大家需要注意的是在学习测试的时候如果收到 401 响应码,请重新登录再测试

 

概述:服务器生成token的过程中,会有两个时间,一个是token失效时间,一个是token刷新时间,刷新时间肯定比失效时间长,当用户的 token 过期时,你可以拿着过期的token去换取新的token,来保持用户的登陆状态,当然你这个过期token的过期时间必须在刷新时间之内,如果超出了刷新时间,那么返回的依旧是 401。

 

处理流程:

 

  1. 在axios的拦截器中加入token刷新逻辑
  1. 当用户token过期时,去向服务器请求新的 token
  1. 把旧的token替换为新的token
  1. 然后继续用户当前的请求

 

在请求的响应拦截器中统一处理 token 过期:

 

 

/**
 * 封装 axios 请求模块
 */
import axios from "axios";
import jsonBig from "json-bigint";
import store from "@/store";
import router from "@/router";

// axios.create 方法:复制一个 axios
const request = axios.create({
  baseURL: "http://ttapi.research.itcast.cn/" // 基础路径
});

/**
 * 配置处理后端返回数据中超出 js 安全整数范围问题
 */
request.defaults.transformResponse = [
  function(data) {
    try {
      return jsonBig.parse(data);
    } catch (err) {
      return {};
    }
  }
];

// 请求拦截器
request.interceptors.request.use(
  function(config) {
    const user = store.state.user;
    if (user) {
      config.headers.Authorization = `Bearer ${user.token}`;
    }
    // Do something before request is sent
    return config;
  },
  function(error) {
    // Do something with request error
    return Promise.reject(error);
  }
);

// 响应拦截器
request.interceptors.response.use(
  // 响应成功进入第1个函数
  // 该函数的参数是响应对象
  function(response) {
    // Any status code that lie within the range of 2xx cause this function to trigger
    // Do something with response data
    return response;
  },
  // 响应失败进入第2个函数,该函数的参数是错误对象
  async function(error) {
    // Any status codes that falls outside the range of 2xx cause this function to trigger
    // Do something with response error
    // 如果响应码是 401 ,则请求获取新的 token

    // 响应拦截器中的 error 就是那个响应的错误对象
    console.dir(error);
    if (error.response && error.response.status === 401) {
      // 校验是否有 refresh_token
      const user = store.state.user;

      if (!user || !user.refresh_token) {
        router.push("/login");

        // 代码不要往后执行了
        return;
      }

      // 如果有refresh_token,则请求获取新的 token
      try {
        const res = await axios({
          method: "PUT",
          url: "http://ttapi.research.itcast.cn/app/v1_0/authorizations",
          headers: {
            Authorization: `Bearer ${user.refresh_token}`
          }
        });

        // 如果获取成功,则把新的 token 更新到容器中
        console.log("刷新 token  成功", res);
        store.commit("setUser", {
          token: res.data.data.token, // 最新获取的可用 token
          refresh_token: user.refresh_token // 还是原来的 refresh_token
        });

        // 把之前失败的用户请求继续发出去
        // config 是一个对象,其中包含本次失败请求相关的那些配置信息,例如 url、method 都有
        // return 把 request 的请求结果继续返回给发请求的具体位置
        return request(error.config);
      } catch (err) {
        // 如果获取失败,直接跳转 登录页
        console.log("请求刷线 token 失败", err);
        router.push("/login");
      }
    }

    return Promise.reject(error);
  }
);

export default request;

①这里面导入了router的原因就是,因为如果是token和刷新token都失效的话,只要让用户跳转到登陆页面中去的,这个时候就要路由导航了

②导入的store就是为了获取vuex中存放的token数据

request.defaults.transformResponse的意思:

配置的默认值/defaults

你可以指定将被用在各个请求的配置默认值

这里的transformresponse的意思就是,改变后端返回数据

配置处理后端返回数据中超出 js 安全整数范围问题

 

 

posted @ 2020-11-29 15:24  SCAU-gogocj  阅读(679)  评论(0编辑  收藏  举报