vue-rounter路由

在這個世界上取得成就的人,都努力去尋找他們想要的機會,如果找不到機會,他們便自己創造機會。
你好,我是夢陽辰!期待與你相遇!


01.什麼是路由?

說起路由你想起了什麼?
路由是一個網絡工程裏面的術語。
路由( routing )就是通過互聯的網絡把信息從源地址傳輸到目的地址的活動.—維基百科

在生活中,我們有沒有聽說過路由的概念呢?
當然了,路由器嘛.路由器是做什麼的?你有想過嗎?
路由器提供了兩種機制:
路由和轉送.


√路由是決定數據包從來源到目的地的路徑.
√轉送將輸入端的數據轉移到合適的輸出端.

路由中有一個非常重要的概念叫路由表.
√路由表本質上就是一個映射表,決定了數據包的指向.

前端渲染和後端渲染

後端渲染:再後端寫前端代碼渲染(jsp)。

前端渲染:前端渲染後臺返回的數據。

後端路由

後端處理url和頁面之間的映射關係。

早期的網站開發整個HTML頁面是由服務器來渲染的.
服務器直接生產渲染好對應的HTML頁面,返回給客戶端進行展示.

但是,一個網站,這麼多頁面服務器如何處理呢?
一個頁面有自己對應的網址,也就是URL.
URL會發送到服務器,服務器會通過正則對該URL進行匹配,並且最後交給一個Controller進行處理.
Controller進行各種處理,最終生成HTML或者數據,返回給前端.
這就完成了一個IO操作.



上面的這種操作,就是後端路由.

當我們頁面中需要請求不同的路徑內容時,交給服務器來進行處理,服務器渲染好整個頁面,並且將頁面返回給客戶頓.這種情況下渲染好的頁面,不需要單獨加載任何的js和css,可以直接交給瀏覽器展示,這樣也有利於SEO的優化.

後端路由的缺點:
一種情況是整個頁面的模塊由後端人員來編寫和維護的.

另一種情況是前端開發人員如果要開發頁面,需要通過PHP和Java等語言來編寫頁面代碼.
加粗樣式
而且通常情況下HTML代碼和數據以及對應的邏輯會混在一起,編寫和維護都是非常糟糕的事情.

前後端分離階段

前端渲染後臺發送回來的數據,後端負責返回數據。

前後端分離階段︰
隨着Ajax的出現,有了前後端分離的開發模式.
後端只提供API來返回數據,前端通過Ajax獲取數據,並且可以通過JavaScript將數據渲染到頁面中.

這樣做最大的優點就是前後端責任的清晰,後端專注於數據上,前端專注於交互和可視化上.

並且當移動端(iOS/Android)出現後,後端不需要進行任何處理,依然使用之前的一套API即可.目前很多的網站依然採用這種模式開發.

前端路由階段(單頁面復應用階段)

單頁面復應用階段:
spa頁面
其實SPA最主要的特點就是在前後端分離的基礎上加了一層前端路由

也就是前端來維護一套路由規則

整個網頁只有一個html頁面。

前端路由主要是負責路由關係,即一個url對應一個組件,前端路由管理url對應的映射關係
在這裏插入圖片描述
前端路由的核心是什麼呢?
改變URL,但是頁面不進行整體的刷新。如何實現呢?


url的hash&html5的history

如何改變url但是頁面不刷新呢?

URL的hash
URL的hash也就是錨點(#),本質上是改變window.location的href屬性.

我們可以通過直接賦值location.hash來改變href,但是頁面不發生刷新
在這裏插入圖片描述
在html5的history模式:pushState
在這裏插入圖片描述
back()方法刪除棧頂。
在這裏插入圖片描述




replaceState()方法替換。
目前前端流行的三大框架,都有自己的路由實現:
Angular的ngRouter

React的ReactRouter

Vue的vue-router

vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,適合用於構建單頁面應用。

我們可以訪問其官方網站對其進行學習: https://router.vuejs.org/zh/

vue-router是基於路由和組件的

路由用於設定訪問路徑,將路徑和組件映射起來.

在vue-router的單頁面應用中,頁面的路徑的改變就是組件的切換.

安裝vue-router

cnpm install vue-router --save

或者在創建的時候可以選擇安裝路由。

步驟二:在模塊化工程中使用它(因爲是一個插件,所以可以通過Vue.use()來安裝路由功能)

在vue-cli2中
在vue-cli3/4中不需要以下配置。

≥第一步:導入路由對象,並且調用Vue.use(VueRouter)

第二步:創建路由實例,並且傳入路由映射配置

≥第三步:在Vue實例中掛載創建的路由實例

index.js

//配置路由相關的信息import vueRouter from 'vue-router'import vue from 'vue'//1.通過vue.use(插件),安裝插件vue.use(VueRouter)//2.創建vueRouter對象const routes =[]const router = new VueRouter({
  //配置路由和科組件之間的應用關係
  routes    })//3.將router對象傳入到vue實例export default router

main.js

import router from './router'new Vue({
    el:'#app',
    router,//掛載
    render:h=>h(App)})

render:h=>h(App)看不懂?

render (h){
    return h(App);}這下懂了把,箭頭函數

在vue-cli2中在vue-cli3/4中語法有所不同。

02.vue-router基本使用

使用vue-router的步驟:
第一步:創建路由組件

第二步:配置路由映射:組件和路徑映射關係

第三步:使用路由:通過<router-link>和<router-view>

<router-link>:該標籤是一個vue-router中已經內置的組件,它會被渲染成一個<a>標籤.

<router-view>:該標籤會根據當前的路徑,動態渲染出不同的組件.

網頁的其他內容,比如頂部的標題/導航,或者底部的一些版權信息等會和<router-view>處於同一個等級.

在路由切換時,切換的是<router-view>掛載的組件,其他內容不會發生改變.

<template>
  <div id="nav">
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link>
  </div>
  <router-view/></template>

注意,當a的目標路由匹配時,它<router-link>會自動獲取.router-link-active該類。

router-link屬性
在前面的<router-link>中,我們只是使用了一個屬性: to,用於指定跳轉的路徑.

<router-link>還有一些其他屬性:

<router-link to='/home' tag='li '>

tag: tag可以指定<router-link>之後渲染成什麼組件,比如上面的代碼會被渲染成一個<li>元素,而不是<a>

tag="button"

replace: replace不會留下history記錄,所以指定replace的情況下,後退鍵返回不能返回到上一個頁面中

active-class:當<router-link>對應的路由匹配成功時,會自動給當前元素設置一個router-link-active的class,設置active-class可以修改默認的名稱.

在進行高亮顯示的導航菜單或者底部tabbar時,會使用到該類.

但是通常不會修改類的屬性,會直接使用默認的router-link-active即可.

因此可以對router-link-active屬性添加樣式,達到點擊表達不同的效果。

除了<router-link>跳轉路徑,還可以通過代碼的方式修改路由

this.$router.push('/home')

戰略性總結:
render/use/mount函數

use函數用於安裝插件。

render函數的實質就是生成template模板;

mount函數就是掛載元素

動態路由的使用

根據用戶的名字,路徑也不同!
例如:
新建組件User.vue

<template>
   <div>
      <h3>用戶界面</h3>
      <h3>我是特定用戶的信息界面</h3>
      <h3>{{userName}}</h3>
   </div></template><script>
    export default {
        name: "User",
       computed:{
           userName(){
              //獲取處於活躍的路由
              return this.$route.params.userName;
           }
       }
    }</script><style scoped></style>

App.vue

<template>
  <div id="nav">
    <router-link to="/" tag="button">Home</router-link> |
    <router-link to="/about">About</router-link> |
    <router-link v-bind:to="'/user/'+userName">User</router-link>
    <br>
    <button @click="btn">點我也可以去關於(代碼跳轉)</button>
  </div>
  <router-view/></template><script>
  export default {//代碼的方式
    name:'App',
    data(){
      return{
        userName:"mengyangchen"
      }
    },
    methods:{
      btn(){
        // this.$router.push('/about')
        this.$router.replace('/about')
      }
    }
  }</script><style>#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;}#nav {
  padding: 30px;}#nav a {
  font-weight: bold;
  color: #2c3e50;}#nav a.router-link-exact-active {
  color: #42b983;}</style>

index.js

import { createRouter, createWebHistory } from 'vue-router'import Home from '../views/Home.vue'import User from '../components/User'const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {//動態路徑
    path: '/user/:userName',
    component: User
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }]const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),//history模式
  routes})export default router/*//配置路由相關的信息import vueRouter from 'vue-router'import vue from 'vue'//1.通過vue.use(插件),安裝插件vue.use(VueRouter)//2.創建vueRouter對象const routes =[]const router = new VueRouter({
  //配置路由和科組件之間的應用關係
  routes
    })//3.將router對象傳入到vue實例export default router*/

HelloWorld.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
    <h3>Installed CLI Plugins</h3>
    <ul>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
    </ul>
    <h3>Essential Links</h3>
    <ul>
      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
    </ul>
    <h3>Ecosystem</h3>
    <ul>
      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
    </ul>
  </div></template><script>export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }}</script><!-- Add "scoped" attribute to limit CSS to this component only --><style scoped>h3 {
  margin: 40px 0 0;}ul {
  list-style-type: none;
  padding: 0;}li {
  display: inline-block;
  margin: 0 10px;}a {
  color: #42b983;}</style>

main.js

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
    <h3>Installed CLI Plugins</h3>
    <ul>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
    </ul>
    <h3>Essential Links</h3>
    <ul>
      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
    </ul>
    <h3>Ecosystem</h3>
    <ul>
      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
    </ul>
  </div></template><script>export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }}</script><!-- Add "scoped" attribute to limit CSS to this component only --><style scoped>h3 {
  margin: 40px 0 0;}ul {
  list-style-type: none;
  padding: 0;}li {
  display: inline-block;
  margin: 0 10px;}a {
  color: #42b983;}</style>

Home.vue

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div></template><script>// @ is an alias to /srcimport HelloWorld from '@/components/HelloWorld.vue'export default {
  name: 'Home',
  components: {
    HelloWorld
  }}</script>

About.vue

<template>
  <div class="about">
    <h1>This is an about page</h1>
  </div></template>

路由懶加載

當打包構建應用時,Javascript包會變得非常大,影響頁面加載。

如果我們能把不同路由對應的組件分割成不同的代碼塊,然後當路由被訪問的時候才加載對應組件,這樣就更加高效了

用到時再加載。

首先,我們知道路由中通常會定義很多不同的頁面.
這個頁面最後被打包在哪裏呢?一般情況下,是放在一個js文件中.但是,頁面這麼多放在一個js文件中,必然會造成這個頁面非常的大.

如果我們一次性從服務器請求下來這個頁面,可能需要花費一定的時間,甚至用戶的電腦上還出現了短暫空白的情況.
如何避免這種情況呢?
使用路由懶加載就可以了.

路由懶加載的主要作用就是將路由對應的組件打包成一個個的js代碼塊.

只有在這個路由被訪問到的時候,才加載對應的組件

路由懶加載的效果:
在這裏插入圖片描述
路由懶加載的寫法:
在這裏插入圖片描述
將user組件改爲懶加載:



import { createRouter, createWebHistory } from 'vue-router'import Home from '../views/Home.vue'const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {//動態路徑
    path: '/user/:userName',
    name: 'User',
    component: ()=>import('../components/User')
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting  路由懶加載
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: ()=>import(/* webpackChunkName: "about" */ '../views/About.vue')
  }]const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),//history模式
  routes})export default router/*//配置路由相關的信息import vueRouter from 'vue-router'import vue from 'vue'//1.通過vue.use(插件),安裝插件vue.use(VueRouter)//2.創建vueRouter對象const routes =[]const router = new VueRouter({
  //配置路由和科組件之間的應用關係
  routes
    })//3.將router對象傳入到vue實例export default router*/

03.vue-router嵌套路由

嵌套路由是一個很常見的功能

比如在home頁面中,我們希望通過/home/news和/home/message訪問一些內容.

一個路徑映射一個組件,訪問這兩個路徑也會分別渲染兩個組件.
在這裏插入圖片描述
實現嵌套路由有兩個步驟:
創建對應的子組件,並且在路由映射中配置對應的子路由.


在組件內部使用<router-view>標籤.
home.vue

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
    <router-link to="/news">新聞</router-link> |
    <router-link to="/message">消息</router-link>
    <router-view/>
  </div></template><script>// @ is an alias to /srcimport HelloWorld from '@/components/HelloWorld.vue'export default {
  name: 'Home',
  components: {
    HelloWorld
  }}</script>

index.js

import { createRouter, createWebHistory } from 'vue-router'const routes = [
  {
    path: '/',
    name: 'Home',
    component: ()=>import('../views/Home.vue'),
    children:[
      {
        path:'news',
        name:'HomeNews',
        component:()=>import('../components/HomeNews.vue')
      },{
        path:'message',
        name:'HomeMessage',
        component:()=>import('../components/HomeMessage.vue')
      }
    ]
  },
  {//動態路徑
    path: '/user/:userName',
    name: 'User',
    component: ()=>import('../components/User.vue')
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting  路由懶加載
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: ()=>import(/* webpackChunkName: "about" */ '../views/About.vue')
  }]const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),//history模式
  routes})export default router/*//配置路由相關的信息import vueRouter from 'vue-router'import vue from 'vue'//1.通過vue.use(插件),安裝插件vue.use(VueRouter)//2.創建vueRouter對象const routes =[]const router = new VueRouter({
  //配置路由和科組件之間的應用關係
  routes
    })//3.將router對象傳入到vue實例export default router*/

在這裏插入圖片描述

04.vue-router參數傳遞

傳遞參數主要有兩種類型: params和query

params的類型:
配置路由格式: /router/:id

傳遞的方式:在path後面跟上對應的值

傳遞後形成的路徑: /router/123,/router/abc

這種方式前面已經講過。

query的類型:
配置路由格式 /router,也就是普通配置

傳遞的方式:對象中使用query的key作爲傳遞方式

傳遞後形成的路徑: /router?id=123,/router?id=abc

app.vue

<template>
  <div id="nav">
    <router-link to="/home" tag="button">Home</router-link> |
    <router-link to="/about">About</router-link> |
    <router-link v-bind:to="'/user/'+userName">User</router-link> |<!--    <router-link to="/profile">檔案</router-link>--><!--<router-link :to="{path:'/profile',query:{name:'mengyangchen',age:'20'}}">檔案</router-link>-->
    <button @click="btn1">profile</button>
    <br>
    <button @click="btn">點我也可以去關於(代碼跳轉)</button>
  </div>
  <router-view/></template><script>
  export default {//代碼的方式
    name:'App',
    data(){
      return{
        userName:"mengyangchen"
      }
    },
    methods:{
      btn(){
        // this.$router.push('/about')
        this.$router.replace('/about')
      },
      btn1(){
        this.$router.replace({
          path:'/profile',
          query:{
            name:'mengyangchen',
            age:'19'
          }
        })
      }
    }
  }</script><style>#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;}#nav {
  padding: 30px;}#nav a {
  font-weight: bold;
  color: #2c3e50;}#nav a.router-link-exact-active {
  color: #42b983;}</style>

profile.vue

<template>
    <div>
        <h3>我是Profile!</h3>
        <h3>{{$route.query.name}}</h3>
    </div></template><script>
    export default {
        name: "Profile"
    }</script><style scoped></style>

在這裏插入圖片描述
當有大量數據的時候用query。
router和route
$router爲VueRouter實例,想要導航到不同URL,則使用$router.push方法


$route爲當前router跳轉對象裏面可以獲取name、path、query.params等

所有的組件都繼承自vue類的原型

route表示當前活躍的路由。

05.vue-router全局導航守衛

正如其名,vue-router 提供的導航守衛主要用來通過跳轉或取消的方式守衛導航。有多種機會植入路由導航過程中:全局的, 單個路由獨享的, 或者組件級的。

我們來考慮一個需求:在一個SPA應用中,如何改變網頁的標題呢?

網頁標題是通過<title>來顯示的,但是SPA只有一個固定的HTML,切換不同的頁面時,標題並不會改變.但是我們可以通過JavaScript來修改<title>的內容.window.document.title = ‘新的標題’.

那麼在Vue項目中,在哪裏修改?
什麼時候修改比較合適呢?

生命週期的鉤子函數:

created(){}//組件創建完mounted(){}//掛載完成update(){}//界面更新完成

我們可以在created()函數完成。

import { createRouter, createWebHistory } from 'vue-router'const routes = [
  {
    path: '/',
    name: 'Home',
    component: ()=>import('../views/Home.vue'),
    children:[
      {//默認顯示news
        path: '',
        redirect:'news'
      },
      {
        path:'news',
        name:'HomeNews',
        component:()=>import('../components/HomeNews.vue')
      },{
        path:'message',
        name:'HomeMessage',
        component:()=>import('../components/HomeMessage.vue')
      }
    ],
    meta: {
      title: '首頁'
  }
  },
  {//動態路徑
    path: '/user/:userName',
    name: 'User',
    component: ()=>import('../components/User.vue'),
    meta:{
      title:'用戶'
    }
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting  路由懶加載
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: ()=>import(/* webpackChunkName: "about" */ '../views/About.vue'),
    meta: {
      title: '關於'
    }
  },{
    path: '/profile',
    name:'Profile',
    component:()=>import('../components/Profile.vue'),
    meta: {
      title: 'Profile'
    }
  }]const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),//history模式
  routes})router.beforeEach((to,from,next)=>{//全局守衛
  //從from 跳轉到to
  document.title = to.matched[0].meta.title
  console.log(to)
  next()});//export default router/*//配置路由相關的信息import vueRouter from 'vue-router'import vue from 'vue'//1.通過vue.use(插件),安裝插件vue.use(VueRouter)//2.創建vueRouter對象const routes =[]const router = new VueRouter({
  //配置路由和科組件之間的應用關係
  routes
    })//3.將router對象傳入到vue實例export default router*/

補充一:如果是後置鉤子,也就是afterEach,不需要主動調用next()函數.
然而和守衛不同的是,這些鉤子不會接受 next 函數也不會改變導航本身:

router.afterEach((to, from) => {
  // ...})

補充二:上面我們使用的導航守衛,被稱之爲全局守衛.

路由獨享的守衛.

組件內的守衛.

官網

爲什麼使用導航守衛?

06.keep-alive

保存組件的狀態。不讓組件銷燬。

keep-alive是Vue內置的一個組件,可以使被包含的組件保留狀態,或避免重新渲染。

它們有兩個非常重要的屬性:
include -字符串或正則表達,只有匹配的組件會被緩存
exclude -字符串或正則表達式,任何匹配的組件都不會被緩存

router-view也是一個組件,如果直接被包在keep-alive裏面,所有路徑匹配到的視圖組件都會被緩存∶

<keep-alive>
	<router-view/></keep-alive>

07.案例(TabBar)

實現思路:
1.如果在下方有一個單獨的TabBar組件,你如何封裝自定義TabBar組件,在APP中使用讓TabBar出於底部,並且設置相關的樣式

2.TabBar中顯示的內容由外界決定
定義插槽
flex佈局平分TabBar

3.自定義TabBarItem,可以傳入圖片和文字

定義TabBarItem,並且定義兩個插槽:圖片、文字。

給兩個插槽外層包裝div,用於設置樣式。

填充插槽,實現底部TabBar的效果

08.Promise(重點)

ES6中一個非常重要和好用的特性就是Promise

但是初次接觸Promise會一臉懵逼,這TM是什麼東西?

看看官方或者一些文章對它的介紹和用法,也是一頭霧水。Promise到底是做什麼的呢?

promise是異步編程的一種解決方案。
那什麼時候我們會來處理異步事件呢?

一種很常見的場景應該就是網絡請求了。
我們封裝一個網絡請求的函數,因爲不能立即拿到結果,所以不能像簡單的3+4=7一樣將結果返回。所以往往我們會傳入另外一個函數,在數據請求成功時,將數據通過傳入的函數回調出去。

如果只是一個簡單的網絡請求,那麼這種方案不會給我們帶來很大的麻煩。

但是,當網絡請求非常複雜時,就會出現回調地獄(例如求情的數據,作爲參數再次請求數據)。

Promise可以很好的解決這個問題。

我們先來看看Promise最基本的語法。
這裏,我們用一個定時器來模擬異步事件:
假設下面的data是從網絡上1秒後請求的數據console.log就是我們的處理方式。

這是我們過去的處理方式,我們將它換成Promise代碼這個例子會讓我們感覺***放屁,多此一舉
首先,下面的Promise代碼明顯比上面的代碼看起來還要複雜。
其次,下面的Promise代碼中包含的resolve、reject、then、catch都是些什麼東西?
我們先不管第一個複雜度的問題,因爲這樣的一個屁大點的程序根本看不出來Promise真正的作用。
在這裏插入圖片描述
首先,當我們開發中有異步操作時,就可以給異步操作包裝一個Promise




異步操作之後會有三種狀態我們一起來看一下這三種狀態:
pending:等待狀態,比如正在進行網絡請求,或者定時器沒有到時間。

fulfill:滿足狀態,當我們主動回調了resolve時,就處於該狀態,並且會回調.then()

reject :拒絕狀態,當我們主動回調了reject時,就處於該狀態,並且會回調.catch()

Promise 異步操作有三種狀態:pending(進行中)、fulfilled(已成功)和 rejected(已失敗)。除了異步操作的結果,任何其他操作都無法改變這個狀態。

如果不設置回調函數,Promise 內部拋出的錯誤,不會反應到外部。
在這裏插入圖片描述
對請求結果多次處理:
在這裏插入圖片描述


省略寫法:
在這裏插入圖片描述

代碼優雅而nice.

Promise的鏈式調用:
在這裏插入圖片描述

Promise的all方法:
在這裏插入圖片描述

在這裏插入圖片描述

All things come to those who wait.

在這裏插入圖片描述
在這裏插入圖片描述


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章