五、第五部分


25、Vuex

<body>
  <script>
    // Vuex
    // 1、先看下Vuex的图
    // 思考一下:Actions是不是很无聊,很多余,Actions内部不直接执行方法,而是利用commit
    // 让方法在Mutations里面执行,到底多不多余呢
    // 你想想,你去找actions执行事件,结果他来一句,你要干这个事,我和mutations说了,你去找他吧
    // 那为什么不直接去找mutations呢

    // 这个时候你好好看下图,actions链接了一个backend API,也就是后端接口
    // 当你需要的值需要从后端取的时候,这个时候actions就起作用了,他支持异步,可以发ajax请求
    // 他会把异步的结果返回给你然后再commit找mutations
    // mutations才是真正管理state状态的人

    // 2、安装Vuex
    // 注意vue2只能装vuex的3版本
    // vue3才能用vuex的4版本
    // 如果vue2安装vuex的3版本的话,会报错,包冲突
    // npm i vuex@3

    // 3、使用Vuex
    // 有一个注意点:脚手架里面写import的时候,比如在main.js里面
    // 脚手架是先把所有import语句执行完之后再执行内部其他的语句的
    // 所以我们不在main.js里Vue.use(Vuex),而是像下面这么做
    // 在src文件下创建一个store文件夹,里面创建一个index.js文件
    // 在文件里写这些
    // **************************************************

    import Vue from 'vue'
    // 引入Vuex
    import Vuex from 'vuex'
    //准备actions:用于相应组件中的动作
    const actions = {
      jia(context, value) {
        // 观察一下这两个参数是分别是什么
        // params context: 一个上下文对象,先不要理解了,知道他又commit方法就行
        // params value: 在组件里dispatch调用时传入的值
        context.commit('JIA', value);
      },

      // 还可以做判断,当sum的值是奇数再加
      // actions之所以支持异步,发送ajax请求,是因为
      jiaOdd(context, value) {
        // 也就是或这里面是可以执行很多逻辑的
        // 执行完最后再去调用commit
        if(context.state.sum % 2) {
          context.commit('JIA', value);
        }
      }
    }

    //准备mutations:用于操作state中的数据
    const mutations = {
      JIA(state, value) {
        state.sum += value;
      }
    }

    //准备state:用于管理所有数据的
    const state = {
      sum: 0,

    }
    Vue.use(Vuex);
    // 创建并暴露store
    /* export default new Vuex.Store(
      {
        actions,
        mutations,
        state
      }
    ) */

    // **************************************************

    // 在main.js里引入store并使用
    import Vue from 'vue'
    import App from './App.vue'
    // 引入写好的store
    import store from './store/index'
    Vue.config.productionTip = false
    new Vue({
      render: h => h(App),
      store
    }).$mount('#app');



  </script>

  <script>
    // 4、在组件中使用
    /* <h2>{{$store.state.sum}}</h2> */
    // 在方法里怎么用
    increment() {
      this.$store.dispatch('jia', 2);
    }
    // 或者直接走commit,记住要写大写了,mutations里是大写
    increment() {
      this.$store.commit('JIA', 2);
    }
  </script>

  <script>
    // 5、Vuex的模块化写法
    const countOptions = {
      actions: {
        jia(context, value) {
          context.commit('JIA', value);
        },
      },
      mutations: {
        JIA(state, value) {
          state.sum += value;
        }
      },
      state: {
        sum: 1
      }
    }

    const peopleOptions = {
      namespaced: true,
      actions: {},
      mutations: {},
      state: {
        people: 'jjwu27'
      }
    }

    export default new Vuex.store(
      {
        modules: {
          countOptions,
          peopleOptions
        }
      }
    )

    // 6、在组件中使用
    // 两种情况是否开启了namespaced: true,
    // 开没开启namespaced,访问state中的变量都是一样的
    /* <h2>{{$store.state.countOptions.sum}}</h2>
    <h2>{{$store.state.peopleOptions.sum}}</h2> */


    // 但是方法就不一样了,没开启namespaced: true,
    increment() {
      this.$store.dispatch('jia', 2);
    }
    // 或者直接走commit,记住要写大写了,mutations里是大写
    increment() {
      this.$store.commit('JIA', 2);
    }

    // 开启了namespaced: true之后,需要拼接路径
    increment() {
      this.$store.dispatch('countOptions/jia', 2);
    }
    // 或者直接走commit,记住要写大写了,mutations里是大写
    increment() {
      this.$store.commit('countOptions/JIA', 2);
    }


  </script>

  <script>
    // 7、actions中支持异步,我们写个请求接口的案例
    // ********************************************
    const actions = {
      // 这里这个value其实用不上,我们要用的是请求过来的值,当然这只是一个例子
      // 不是说这个value就用不上,要学会举一反三
      addPersonServer(context,value) {
        axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
          response => {
            context.commit('JIA', {name: response.data})
          },
          error => {

          }
        )
      }
    }

    // ********************************************

  </script>

  <script>

    // 需要注意的点:

    // 有没有发现在我的项目里都是直接在组件里调用的this.$store.commit,没有走this.$store.dispatch
    // 这就是我们可以不找actions,可以直接找mutations


    /* 项目里监听Vuex里的数据
    @Watch('$store.state.common.delKlbResource', {
      deep: true,
      immediate: true
    })
    public watchDelKlbResource(newValue) {

    } */
  </script>
</body>

26、路由

<script>
  // 路由

  // 1、安装vue-router
  // 也要注意vue-router4版本只能在vue3中用,所以我们要装vue-router3版本
  // npm i vue-router@3

  // 2、创建文件
  // src下创建一个router文件夹,里面创建一个index.js文件
  // 编写文件内容
  // **********************************
  import VueRouter from 'vue-router'

  // 创建并暴露一个路由器
  export default new VueRouter({
    routes: [
      {
        path: '/father',
        component: () => import('../components/Father.vue')
      },
      {
        path: '/home',
        component: () => import('../components/Uncle.vue')
      }
    ]
  })

  // **********************************

  // 3、引入并使用
  // 在main.js中引入并使用
  import Vue from 'vue'
  import App from './App.vue'
  import VueRouter from 'vue-router'
  import router from './router/index'

  Vue.config.productionTip = false
  Vue.use(VueRouter);

  new Vue({
    render: h => h(App),
    store,
    router
  }).$mount('#app')

  // 4、App中使用
  /* <template>
    <div id="app">
      <router-link to="/father">Father</router-link>
      <router-link to="/home">Uncle</router-link>
      <router-view></router-view>
    </div>
  </template> */


  // 需要注意的是每个组件都会有$route和$router, 每个组件的$route都是不一样的
  // 但是他们呢的$router是一样的,因为这是一个总的路由器,整个应用只有一个router,通过$router获取
  // 每个组件都有自己的$route属性,里面存储的是自己的路由信息
</script>

<script>
  // 2、多级路由
  // 在配置文件中写

  import VueRouter from 'vue-router'
  // 注意子路由不需要加斜杠/
  export default new VueRouter({
    routes: [
      {
        path: '/father',
        component: () => import('../components/Father.vue'),
        children: [
          {
            path: 'brother',
            component: () => import('../components/Brother.vue')
          },
          {
            path: 'sister',
            component: () => import('../components/Sister.vue')
          }
        ]
      },
      {
        path: '/uncle',
        component: () => import('../components/Uncle.vue'),
        children: [
          {
            path: 'brother',
            component: () => import('../components/Brother.vue')
          },
          {
            path: 'sister',
            component: () => import('../components/Sister.vue')
          }
        ]
      }
    ]
  })

  // 在组件里这么写
  /* <template>
    <div class="father">
      <h2>我是爸爸</h2>
      <router-link to="/father/brother">Father/Brother</router-link>
      <br>
      <router-link to="/father/sister">Father/Sister</router-link>
      <router-view></router-view>
    </div>
  </template> */
</script>

<script>
  // 3、路由传参
  // 两种形式
  // 第一种query形式的第一种写法
  // 在router-link里这样写:用?和&符号连接参数
  // <router-link to="/father/brother?id=123&name=jjwu27">Father/Brother</router-link>
  // 路由组件里接收:this.$route.query

  // 第一种query形式的第二种写法
  // to绑定对象形式
  // <router-link :to="{path: '/father/sister', query: {id: 12345, name:'hahahah'}}">Father/Sister</router-link>
  // 接收是一样的

  // 第二种params形式的写法
  // 先改配置,给路由path后面追加占位符然后写上属性名,代表参数
  export default new VueRouter({
    routes: [
      {
        path: '/father',
        component: () => import('../components/Father.vue'),
        children: [
          {
            path: 'brother',
            component: () => import('../components/Brother.vue')
          },
          {
            path: 'sister',
            component: () => import('../components/Sister.vue')
          }
        ]
      },
      {
        path: '/uncle',
        component: () => import('../components/Uncle.vue'),
        children: [
          {
            name: 'brother',
            path: 'brother/:id/:title',
            component: () => import('../components/Brother.vue')
          },
          {
            name: 'sister',
            path: 'sister/:params',
            component: () => import('../components/Sister.vue')
          }
        ]
      }
    ]
  })

  // 在router-link里这样写,router会识别出来从哪里开始是参数
  // <router-link to="/father/brother/123/加油">Father/Brother</router-link>
  // 路由组件里接收:this.$route.params

  // 第二种形式的第二种写法
  // 注意的是:当使用这种写法时,不可以配置path,而是必须写name的写法
  // <router-link :to="{name: 'sister', params: {id: 12345, name:'hahahah'}}">Father/Sister</router-link>
  

  // 路由路径的简写形式
  // 首先配置路由的时候给到name属性
  // **********************************
  // 创建并暴露一个路由器
  /* export default new VueRouter({
    routes: [
      {
        path: '/father',
        component: () => import('../components/Father.vue'),
        children: [
          {
            path: 'brother',
            component: () => import('../components/Brother.vue')
          },
          {
            path: 'sister',
            component: () => import('../components/Sister.vue')
          }
        ]
      },
      {
        path: '/uncle',
        component: () => import('../components/Uncle.vue'),
        children: [
          {
            name: 'brother',
            path: 'brother',
            component: () => import('../components/Brother.vue')
          },
          {
            name: 'sister',
            path: 'sister',
            component: () => import('../components/Sister.vue')
          }
        ]
      }
    ]
  }) */

  // router-link里这么写就好了
  // <router-link :to="{name: 'brother'}">Father/Brother</router-link>
  // <router-link :to="{name: 'sister', query: {id: 12345, name:'hahahah'}}">Father/Sister</router-link>

  // 注意以及路由不许这样写,只有多级路由才可以简化
</script>

<script>
  // 4、浏览器的历史记录(这块具体可以看尚硅谷125集)
  // 路由支持浏览器的前进后退,采用的是push模式,压栈和出栈的模式
  // 这样就有了前进和后退就是路由的压栈出栈


  // replace模式,给router-link标签添加replace,这个是替换当前记录,这个就没有前进后退模式
  // <router-link replace to="/father">Father</router-link>

  // 注意:路由跳转默认采用的是push模式

  // 一般我们搭配使用,大部分路由支持前进后退,有的你不想支持前进后退就给router-link开启replace属性
</script>

<script>
  // 5、编程式路由导航
  // 不用router-link,通过点击事件跳转路由
  /* <button @click="jump"></button> */
  // 注意这里用的是$router,配置项可以写name也可以写path
  jump() {
    this.$router.push({
      name: 'sisiter',
      query: {
        id: 123,
        name: 'jjwu27'
      }
    })
  }

  // 前进写法:
  forward() {
    this.$router.forward();
  }

  // 后退写法
  back() {
    this.$router.back();
  }

  // go的作用

  go() {
    this.$router.go(-2);// 后退两步
    this.$router.go(-2);// 前进两步
  }

</script>

<script>
  // 6、缓存路由组件
  // 用keep-alive组件包裹,包裹的所有内容支持保持原状态
  // 当然也可以选择保留那些组件的状态,用include
  // 这里的News、Message是组件名!组件名!组件名!!!,代表只保留News、Message组件的状态
  /* <keep-alive :include="['News', 'Message']">
    <router-view></router-view>
  </keep-alive> */

  // 7、路由组件独有的两个声明周期钩子
  // 激活
  activated() {
    //路由组件被激活也就是出现时调的钩子
  }

  // 失活
  deactivated() {
    // 路由组件消失的时候调用的钩子,注意这里用的是消失,不是销毁
    // 其实这两个钩子在路由组件里可以用来代替mounted和beforeDestroy
    // 应用场景就是我们上面说的那个缓存路由组件的时候,组件没有被销毁,
    // 组件消失是不会调用beforeDestroy钩子的,下一次打开也不会调用
    // munted钩子,这个时候activated和deactivated钩子就会起到作用
  }

</script>

<script>
  // 7、路由守卫:很重要(路由的权限问题)
  // 7.1、进入路由前的校验:前置路由守卫
  // 想做校验,不能直接创建路由配置了,要这样写
  // 我们在创建好一个router对象的时候不直接暴露
  const router = new VueRouter({
    routes: [
      {
        name: 'father',
        path: '/father',
        component: () => import('../components/Father.vue'),
        children: [],
        meta: { // 路由元信息,程序员自定义的信息
          isAuth: true, //我在这里配置了一个isAuth字段,用于鉴别这个路由是否开启访问权限
          title: '父亲'
        }
      },
      {
        name: 'uncle',
        path: '/uncle',
        component: () => import('../components/Uncle.vue'),
        children: [],
        meta: {
          isAuth: true,
          title: '叔叔'
        }
      }
    ]
  })

  //然后做全局前置路由守卫: 初始化的时候调用以及每次路由切换前被调用
  router.beforeEach((to, from, next) => {
    console.log(to,from);
    next() //next是放行,你必须写这个它才会继续走,不然代码会被打断
  })

  // 有了next我们就可以做守卫了呀
  router.beforeEach((to, from, next) => {
    if (to.path === '/home/news') {
      if (localStorage.getItem('name') === 'jjwu27') {
        next(); // 这样就只有jjwu27可以进入到home下的news啦
      } else {
        alert('您没有权限进入哦!')
      }
    } else {
      next();
    }
  })

  // 搭配我们写的isAuth字段使用,一种规范的写法
  router.beforeEach((to, from, next) => {
    if (to.meta.isAuth) {
      if (localStorage.getItem('name') === 'jjwu27') {
        next(); // 这样就只有jjwu27可以进入到father路由哦
      } else {
        alert('您没有权限进入哦!')
      }
    } else {
      next();
    }
  })

  // 7.2、后置路由守卫:初始化的时候被调用,每次切换路由后被调用
  router.afteEach((to, from) => {
    // 这里的to和from和前置是一样的都是从哪到哪
    // 后置路由守卫到底守卫什么呢
    // 有这么一个效果document.title可以改变页面的标题信息
    // 那我们呢就是让每次跳转到那个页面就把标题改为这个页面
    // 这个用前置守卫怎么实现都不完美,但是后置路由就很完美
    document.title = to.meta.title || '没有值就显示我'
  })

  // 7.3、独享路由守卫:写在路由的配置文件里
  // 独享路由守卫只有前置守卫
  // 前置路由守卫和独享路由守卫是可以搭配使用的
  const router2 = new VueRouter({
    routes: [
      {
        name: 'father',
        path: '/father',
        component: () => import('../components/Father.vue'),
        children: [],
        meta: {
          isAuth: true, //我在这里配置了一个isAuth字段,用于鉴别这个路由是否开启访问权限
          title: '父亲'
        }
      },
      {
        name: 'uncle',
        path: '/uncle',
        component: () => import('../components/Uncle.vue'),
        children: [],
        meta: {
          isAuth: true,
          title: '叔叔'
        }
      },
      {
        name: 'message',
        path: '/message',
        component: () => import('../components/Message.vue'),
        children: [],
        meta: { // 路由元信息,程序员自定义的信息
          isAuth: true,
          title: '私密信息'
        },
        beforeEnter: (to, from, next) => {
          if (to.meta.isAuth) {
            if (localStorage.getItem('name') === 'jjwu27') {
              next();
            } else {
              alert('您没有权限进入哦!')
            }
          } else {
            next();
          }
        }
      }
    ]
  })
  

  // 7.4、组件内路由守卫
  // 这个要进入到组件里面,前提是你的组件是配置过的路由组件
  // 组件里这么写
  // ****************************************************
  <template>
    <h2>我是路由组件哦</h2>
  </template>

  <script>
    export default {
      name: 'App',
      mounted() {

      },
      // 通过路由规则,什么叫通过路由规则进入呢,就是走router-view进入该组件时被调用,普通的组件注册调用是不起作用的
      /* beforeRouteEnter(to, from, next) {
        if (to.meta.isAuth) {
          if (localStorage.getItem('name') === 'jjwu27') {
            next(); // 这样就只有jjwu27可以进入到father路由哦
          } else {
            alert('您没有权限进入哦!')
          }
        } else {
          next();
        }
      }, */

      // 通过路由规则,离开该组件时被调用
      beforeRouteLeave(to, from, next) {

      }
    }
  </script>
  // ****************************************************

  // 总结!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  // 路由守卫的执行顺序:beforeEach => beforeEnter => beforeRouteEnter => afterEach
</script>

27、路由的两种工作模式hash和history

<script>
  // 路由的两种工作模式
  // 1、默认开启的是hash模式:标志是#
  // 2、第二种是history模式

  // 怎么修改配置呢??,配置文件里改
  const router = new VueRouter({
    mode: 'history',
    routes: [
      {

      }
    ]
  })
  // 什么是hash值:#及后面的内容就是hash值
  // hash值不会包含在HTTP请求中,即hash不会带给服务器

  // 对比一下
  // hash的兼容性略好点; hash的路径里有#符号,不是很美观
  // hash模式不会把#后面的内容当作请求路径,但是history会,history会根据的你网址路径去找对应路径的文件
  // 由于history的路径会参与http请求,所以用history的时候,部署上线的时候需要后端人员支持,解决刷新页面服务端404的问题
</script>

28、Promise

  <script>
    // Promise
    // 什么时候用到:一般是有异步操作时,用promise对异步操作做封装

    // 1、认识promise
    new Promise((resolve, reject) => {
      // 这里假设定时器是异步请求,假设网络请求成功了,res是返回数据,拿到数据后
      // 我们调用成功的回调,resolve参数,他也是个函数,他会携带res直接跑到then方法里

      // 如果失败了,就调用reject,然后携带错误信息跳转到catch方法里

      // 模拟这是成功的回调
      setTimeout(res => {
        resolve()
      }, 1000)

      // 模拟这是失败的回调
      setTimeout(err => {
        reject(err)
      }, 1000)

    }).then(res => {

    }).catch(arr => {

    })

    // 另一种写法,没有catch,而是then方法里有两个参数
    new Promise((resolve, reject) => {

      setTimeout(res => {
        resolve()
      }, 1000)

      setTimeout(err => {
        reject(err)
      }, 1000)

    }).then(res => {

    }, err => {

    })

    // 2、promise的三种状态
    // 首先要触发,怎么触发,当我们开发中有异步操作的时候,就可以给异步操作包装一个Promise
    // 异步操作后又三种状态:
    // pending:等待状态,比如正在进行网络请求,或者定时器没有到事件,创建promise对象,并且没有调用resolve和reject的时候
    // fulfill:满足状态,当我们回调了resolve时,切换到该状态,并且会回调then()
    // reject: 拒绝状态,当我们回调了reject时,切换到该状态,并且会回调catch()

    // 3、promise的链式调用
    // 为什么promise可以链式调用
    // 因为then和catch方法的返回值都是promise对象呀!!!!
    // 链式调用的步骤如下 

    new Promise((resolve, reject) => {

      setTimeout(res => {
        resolve(res)
      }, 1000)

      setTimeout(err => {
        reject(err)
      }, 1000)

    }).then(res => {
      // 处理代码
      return new Promise((resolve, reject) => {
        setTimeout(ans => {
          resolve(ans)
        }, 1000)
      })
    }).then(ans => {
      // 处理代码
    })

    // 上面的代码还可以简写哦
    new Promise((resolve, reject) => {

      setTimeout(res => {
        resolve(res)
      }, 1000)

      setTimeout(err => {
        reject(err)
      }, 1000)

    }).then(res => {
      // 处理代码
      // 可以直接用Promsie点resolve这个方法,也会跳转到then方法里
      return Promise.resolve(res + '111')
    }).then(res => {
      // 这里的res就是上面的res+111
      // 处理代码
    })

   // 上面的方法还能继续简写哦
  new Promise((resolve, reject) => {

    setTimeout(res => {
      resolve(res)
    }, 1000)

    setTimeout(err => {
      reject(err)
    }, 1000)

  }).then(res => {
    // 处理代码
    // 可以直接返回结果,因为底层会为你自动包装一层Promsie
    return res + '111'
  }).then(res => {
    // 这里的res就是上面的res+111
    // 处理代码
  })

  // 注意!!!!!!!!!!!!!!!!!!!!
  // 我们可以链式无限调用.then方法
  // 会直接穿透到最后的catch方法里

  // 4、Promise.all,同时处理多个请求结果
  // 比如一个功能依赖两个请求
  Promise.all([
    new Promise((resolve,reject) => {
      setTimeout((res1) => {
        // 假装请求
        resolve(res1)
      }, 1000)
    }),

    new Promise((resolve,reject) => {
      setTimeout((res2) => {
        // 假装请求
        resolve(res2)
      }, 1000)
    }),
  ]).then(results => {
    // 这里的results就是一个数组
    console.log(results[0]); // 第一个返回结果
    console.log(results[0]); // 第二个返回结果
  })

  </script>

// 看一个案例:来自项目,只看promise就好了
public async addWordFromLeftBar(id) {
    const currentContent = this.getCurrentInfo[0]
    if (currentContent) {
      const resource = currentContent?.properties?.find(i => i.name === 'resourceStatus')
      if (resource && ['processing', 'init'].includes(resource.value)) {
        await this.autoTempSave(deepClone(currentContent), this.getRealCurrentIndex())
      }
    }
    const defaultProperties = JSON.parse(JSON.stringify(this.stbProperties));
    delete defaultProperties.identifier;
    delete defaultProperties.taskStatus;
    delete defaultProperties.quantityCompleted;
    delete defaultProperties.quantity;
    delete defaultProperties.extendedInformation;
    delete defaultProperties.completeTheResource;
    const wordObj = deepClone(defaultProperties)
    // 单词状态添加的默认为初始化待制作,不能继承
    wordObj.resourceStatus = 'init'
    delete wordObj.semester
    delete wordObj.quantity
    // 请求之前需要把年份的时间格式转换回来
    wordObj.year = (new Date(wordObj.year)).getTime();
    defaultProperties.year = (new Date(defaultProperties.year)).getTime();
    const params = {
      id: this.id,
      label: 'package',
      identifier: (this.stbProperties as any).identifier,
      properties: defaultProperties,
      imageVertexEntitys: [{
        edgeLabel: 'produceWords',
        generateQuantity: 1,
        vertexEntity: {
          label: 'dcsy',
          properties: {
            ...wordObj,
            name: ' '
          }
        }
      }
      ]
    }
    this.$store.commit('setAppSpinShow', true);
    addDcEntity(params).then(res => {
      this.$Message.success('添加单词成功')
    }).catch(() => {
      this.$Message.error('添加单词失败')
    }).finally(() => {
      this.$store.commit('setAppSpinShow', false);
    })
  }

29、axios

<script>
  // axios

  // 1、简单写法:基本使用
  // 如果不写method,那么axios默认是get请求
  axios({
    url: 'http://baidu.com',
    method: 'post'
  }).then(res => {
    console.log(res);
  })

  // 也可以这样写:axios有很多内置的方法,每一种请求方式都可以直接点
  // 具体配置怎么写自己可以在用的时候查看一下
  axios.get(url).then(res => {})

  // 2、axios处理多个请求
  axios.all([
    axios({
      url: 'http://baidu.com',
      method: 'post'
    }),
    axios({
      url: 'http://baidu.com',
      method: 'post'
    })
  ]).then(results => {
    // 这里的results就是一个数组
    // 数组的每一项就是请求结果
  })

  // 注意axios为我们提供了一个展开数组结果的方法哦
  axios.all([
    axios({
      baseURL: 'http://baidu.com',
      timeout: 5,
      url: '/home',
      method: 'post'
    }),
    axios({
      baseURL: 'http://baidu.com',
      timeout: 5,
      url: '/family',
      method: 'post'
    })
  ]).then(axios.spread((res1, res2) => {
    console.log(res1),
    console.log(res2)
  }))
  //当然我觉得用数组的解构更方便


  // 3、全局配置
  // 对比一下上面的baseURL和 timeout我们就可以写成全局配置

  axios.defaults.baseURL = 'http://baidu.com';
  axios.defaults.timeout = 5000;
  axios.all([
    axios({
      url: '/home',
      method: 'post'
    }),
    axios({
      url: '/family',
      method: 'post'
    })
  ]).then(([res1, res2]) => {
    console.log(res1, res2)
  })

  // 4、axios的实例
  // 这样每一个实例对象都可以写自己的默认配置
  const instance1 = axios.create({
    baseURL: 'http://baidu.com',
    timeout: 5000
  })

  instance1({
    url: '/home'
  }).then(res => {

  })

  instance1({
    url: '/family'
  }).then(res => {

  })
  // 再创建一个实例
  const instance2 = axios.create({
    baseURL: 'http://junjie.fun',
    timeout: 5000
  })

  instance2({
    url: '/home'
  }).then(res => {

  })

  instance2({
    url: '/family'
  }).then(res => {

  })

  // 5、封装axios用于项目
  export function request(config) {

    // 第一种写法
    /* return new Promsie((resolve, reject) => {
      // 创建axios实例
      const instance = axios.create({
        baseURL: 'http://junjie.fun',
        timeout: 5000
      })
      // 发送网络请求
      instance(config)
      .then(res => {
        resolve(res);
      })
      .catch(err => {
        reject(err);
      })
    }) */


    // 第二种写法
    // axios创建的实例本身就是Promise对象,可以直接返回
    const instance = axios.create({
      baseURL: 'http://junjie.fun',
      timeout: 5000
    })
    // 发送网络请求
    return instance(config);
  }

  // 引入封装好的请求
  import { request} from './jjwu27/request';

  // 使用它
  request({
    url: '/home',
    method: 'post'
  }).then(res => {

  }).catch(res => {

  })

  // 6、搭配拦截器使用

  export function request(config) {

    const instance = axios.create({
      baseURL: 'http://junjie.fun',
      timeout: 5000
    })

    // 添加拦截器
    // 请求拦截器:两个回调,成功回调和失败回调
    instance.interceptors.request.use(config => {
      // 这里是请求成功触发的响应拦截

      // 请求拦截主体(作用)

      // ************************************************
      // 比如处理config中的一些不符合要求的信息
      // 处理请求头等信息

      // 高频用法:发送网络请求的时候做遮罩层效果

      // 登录失效提示:可以在这里做token信息的校验,如果没有的话,提示用户重新登录

      // ************************************************

      // 必须返回config
      return config;
    },
    err => {
      // 这里是请求失败触发
    })


    // 响应拦截器
    // 两个回调和请求拦截一样
    instance.interceptors.response.use(res => {

      // 1、关闭遮罩层等

      // 响应拦截后必须把值返回,否则接口的结果会被拦截
      return res
    },
    err => {

    })


    // 发送网络请求
    return instance(config);

  }

  // 引入封装好的请求
  import { request } from './jjwu27/request';


  // 使用它
  request({
    url: '/home',
    method: 'post'
  }).then(res => {
  }).catch(res => {
  })

  

</script>

文章作者: 吴俊杰
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 吴俊杰 !
  目录