The main functions to be implemented are as follows:

Information list, TAB page switch, article report, channel management, article details, reading memory, focus on function, like function, comment function, reply to comment, search function, login function, personal center, edit information, xiaozhi students…

The above implementation of the login function, below we specifically to achieve the token processing

1 Basic Token usage process

1) The user logs in and obtains the token;

2) Save the token locally.

3) Initiate other requests with token (access without token will cause 401 error)

1.1 In API /user.js, according to the requirements of the interface documentation, add a getInfo function, which is used to call the interface

/ / export const getProfile = () => {return request({method: 'GET', url: 'v1_0/user/profile'})}Copy the code

1.2 in the SRC/views/login/login. Vue this component to call getInfo function, to take the user’s information

Import {getProfile} from '@/ API /user' async doLogin () {// try calling getProfile() //.... }Copy the code

Testing to retrieve user information now returns an error because there is no token in the data passed

1.3 We manually added the token to test the acquisition, found the token in the data returned by the previous login and copied it

inuser/profileTo add their own copy of the token format refer to the following

/** * export const getProfile = () => {return ajax({method: 'GET', url: '/v1_0/user/profile', headers: {// Authorization: 'Bearer token values' with Spaces between Authorization: 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1OTM4NTIyMjgsInVzZXJfaWQiOjExMDI0OTA1MjI4Mjk3MTc1MDQsInJlZnJlc2giOmZhbHN lfQ.gR880MifO8GIFG6PNh9eOZGGpfcwNRkK6MpI1upN93w' } }) }Copy the code

1.4 After testing, we found that the request with token can be used normally

Token is a special string returned by the back end after a successful login. For some interfaces that require permissions, we need to supplement tokens when calling the interface according to the requirements of the interface documentation.

2 Tokens — Save tokens in VUex

2.1 instore/index.jsChinese: Add the three parts of actions, mutations and state

XML mutations import {login} from '@/ API /user.js' // public data state: {tokenInfo: {}}, // define mutations to modify data mutations: { mSetTokenInfo (state, initTokenInfo) { state.tokenInfo = initTokenInfo } }, actions: {async userLogin (context, userInfo) {try {//第 2 const {data: {data}} = await login(userInfo) // context.com MIT ('mSetTokenInfo', context.com data) } catch (err) { // console.log(err) throw new Error(err) } } },Copy the code

If you do not write throw new Error(err) to throw an Error, the code will be out of order: the login is successful if no data is obtained

We can throw a new Error(err), we can throw a try catch; We default to the first method

2.2 Calling action to Save token Information

In login/login.vue, change the code for doLogin to submit actions for successful validation

Async doLogin () {try {this.$toast.loading({duration: 0, // keep displaying toast, never close overlay: true, // Add a message mask to the whole thing: 'Logging in... '}) // await this.$store. Dispatch ('userLogin', This. User) //第 4 this.$toast.success(' login succeeded ')} Catch (err) {console.log(err) this.$toast.fail(' login failed ')}}Copy the code

The correct execution sequence of the preceding two steps is ①=>④

Throw new Error(err) is not written in the order of ①, ②, ④, and ③. Instead, the Error is not thrown but is executed by its own catch. As a result, the subsequent code considers that there is no Error and finally executes the login successfully

2.3 Check whether the tokenInfo defined by VUex contains the token value

Axios – Request interceptor

3.1 Format of interceptor

/ / request interceptor instance. Interceptors. Request. Use (function (config) {the console. The log (' config 'config) return the config}, Error () {return promise.reject (error)})Copy the code

3.2 Adding tokens to the AXIos request interceptor

insrc\utils\request.jsAdd the following code to

/ / request interceptor request. Interceptors. Request. Use (function (config) {/ / how to remove the vuex saved data? / / 1. Vue components: enclosing $store. State. TokenInfo. The token / / 2. In a normal.js file: import store from '@/store/index.js' console.log(' How to retrieve data saved in vuex? ', store) const token = store.state.tokenInfo.token if (token) { config.headers.Authorization = `Bearer ${token}` } Console. log('config request interceptor 2', config) return config}, function (error) {return promise.reject (error)})Copy the code

4 Save user information to vuex

Since user information also needs to be shared between different components, it is also stored in VUEX,

4.1 Adding a Modulestore/modules/user.jsAnd set namespaced to true

import { getProfile } from '@/api/user.js'
export default {
  namespaced: true,
  state: {
    userInfo: {}
  },
  mutations: {
    mSetUserInfo (state, newUserInfo) {
      state.userInfo = newUserInfo
    }
  },
  actions: {
    async getProfile (context) {
      try {
        const res = await getProfile()
        console.log('modules, getProfile', res)
        context.commit('mSetUserInfo', res.data.data)
      } catch (err) {
        console.log(err)
        throw new Error(err)
      }
    }
  }
}
Copy the code

4.2 In the main modulestore/index.js Referenced in the

// omit other... Import user from './modules/user.js' export default new vuex.store ({// omit other... modules: { user } })Copy the code

4.3 Invoking the Action in Login. vue

Async doLogin () {this.$toast({duration: 0, // keep displaying toast, never close overlay: true, // Add a mask to the whole message: 'Loading... '}) // Make the specific Ajax commit action try {// call action console.log(1) // get the token and save it in vuex to await this.$store.dispatch('userLogin', This.user) // Call action +++++ await this.$store.dispatch('user/getProfile') console.log(4) This.$toast.success(' login succeeded ')} Catch (err) {console.log(err) this.$toast.fail(' login failed ')}},Copy the code

4.4 If the vuEX Debugging Tool displays the following information, the vuEX debugging tool succeeds

So much for today’s main implementation!

5. Next, set up the layout framework to prepare for tomorrow’s project

5.1 establish file: SRC/view/layout/layout. Vue, content is as follows:

<template> <div class="container"> <! 1. Top navigation --> <div> logo + button </div> <! -- 2. The body area will load four child pages --> <! -- <router-view></router-view> --> <! </div> </div> </template>Copy the code

5.2 Route Configuration

Add a route configuration to SRC /router/index.js

{ path: '/', name: 'layout', component: () => import('.. /views/layout/layout.vue') },Copy the code

5.3 insrc/view/layout/layout.vueMiddle completion code:

<template> <div class="container"> <! -- Top navigation --> <! -- Logo Navigation logo + button --> <! -- Header: logo+ search --> <van-nav-bar> <! <template #left> #left ="left" It does not generate the corresponding DOM --> <template slot="left"> <div class="logo"></div> </template> <template slot="right"> <van-button round Icon ="search" size="small" type="primary" > </van-button > </template> </van-nav-bar> <! <router-view></router-view> <! -- Tabbar --> <van-tabbar route> <van-tabbar-item icon="home-o" to="/"> home </van-tabbar-item> <van-tabbar-item </van-tabbar-item ="video-o" to="/video"> </van-tabbar-item> < van - tabbar item icon = "setting - o" to = "/ setting" > not login | I < / van - tabbar - item > < / van - tabbar > < / div > < / template > < script > export default { } </script> <style lang="less" scoped> .logo { background: url(".. /.. /assets/logo.png") no-repeat; background-size: cover; width: 100px; height: 30px; } .van-nav-bar .van-icon { color: #fff; } </style>Copy the code
  • #left is short for slot=”left”
  • The route attribute of van-tabber enables the routing mode. To specifies the route address to jump to.

5.4 Realizing the Function of going to the Home page after login

In the SRC/views/login/login. Vue add one line of code:

Async doLogin () {this.$toast({message: 'Loading... ', forbidClick: true, loadingType: 'spinner'}) // To commit a specific action try {// because there are asynchronous actions in actions, we add await // const {data: { data } } = await login(this.user) // console.log(data) // localStorage.setItem('token', 'Bearer '+ data.token) // console.log(1) // Retrieve token and store in vuex await this.$store.dispatch('setToken', This.user) // Call the modules of the namespace to store user information await this.$store.dispatch('user/getProfile') // console.log(4) +++++ this.$router.push('/')} catch (err) {console.log(err) This.$toast.fail(' login failed ')}},Copy the code

5.5 The final functions are as follows: