設計模式在vue中的應用(二)

前言

目錄整理:
設計模式在vue中的應用(一)
設計模式在vue中的應用(二)
設計模式在vue中的應用(三)
設計模式在vue中的應用(四)
設計模式在vue中的應用(五)
設計模式在vue中的應用(六)
設計模式在vue中的應用(七)vue

爲何要寫這些文章呢。正如設計模式(Design Pattern)是一套被反覆使用、多數人知曉的、通過分類的、代碼設計經驗的總結(來自百度百科)同樣,也是想經過分享一些工做中的積累與你們探討設計模式的魅力所在。
在這個系列文章中爲了輔助說明引入的應用場景都是工做中真實的應用場景,固然沒法覆蓋全面,但以此類推也覆蓋到了常見的業務場景react



這篇內容比較簡單隻涉及到一個設計模式——狀態模式。設計模式

一,需求

圖片來自iView文檔截圖 緩存

在服務端輸出頁面的開發模式下每完成一步常規作法是跳轉一個新頁面到下一步,固然在SPA的開發模式下大多場景也是經過路由處理每一步的邏輯。

如今的需求是:這整個過程是連續的,除非整個過程處理完成,不然無論進行到哪一步當刷新頁面都要從第一步從新開始,也就是在同一個路由下處理這四步操做bash

二,分析

在文章開頭咱們提到了狀態模式,經過上面的需求咱們很容易聯想:網絡

  • 第一步操做完成改變狀態到第二步
  • 第二步操做完成改變狀態到第三步
  • 第三步操做完成改變狀態到第四步

三,設計

先看狀態模式的介紹

一下內容來自網絡post

1,首先須要一個context環境角色
// context.vue
<template>
  <div>
    <Steps :current="status">
      <Step title="已完成" content="這裏是第一步"></Step>
      <Step title="進行中" content="這裏是第二步"></Step>
      <Step title="待進行" content="這裏是第三步"></Step>
      <Step title="待進行" content="這裏是第四步"></Step>
    </Steps>
    <!-- 動態渲染當前狀態組件 -->
    <component :is="statusCom" @onChangeStatus="changeStatus" />
  </div>
</template>
<script>
  // 引入各狀態組件
  import Step1 from './Step1'
  import Step2 from './Step2'
  import Step3 from './Step3'
  import Step4 from './Step4'
  
  export default {
    data() {
      return {
        status: 1
      }  
    },
    computed: {
      // 具體狀態角色
      statusCom() {
        const statusMap = {
          1: Step1,
          2: Step2,
          3: Step3,
          4: Step4,
        } 
        return statusMap[this.status]
      }    
    },
    methods: {
      // 表明每一步的狀態組件都有改變status的能力
      changeStatus(val) {
        this.status = val
      }    
    }  
  }
</script>
複製代碼
2,實現State抽象狀態角色
// Step1.vue
<template>
  <div>
    <!-- do something -->
    <button @click="handleClick">完成</button>
  </div>
</template>
<script>
  export default {
    methods: {
      handleClick() {
        // 第一步完成,將狀態變爲狀態2
        // context角色接受狀態改變更態渲染Step2.vue的操做
        this.$emit('onChangeStatus', 2)
      }
    }  
  }
</script>
複製代碼
Step2.vue
Step3.vue
Step4.vue
同Step1.vue
複製代碼
3,總結
  • context角色只負責具體狀態的切換——渲染哪一步的組件
  • state角色負責處理當前狀態的實現和切換下一個狀態——每一步邏輯的具體實現

四,優化

經過上面的實現,咱們發現整個狀態的改變都交給了各狀態組件,若是這時我操做到了第3步想回退到第2步怎麼辦?優化

給每一個狀態組件加一個回退到上一個狀態的功能?
在咱們這個需求中狀態從1->2->3->4是單向的,這個方式或許能行,假設在一個比較複雜的狀態場景下,各狀態的改變毫無章法很難肯定當前狀態的上一個狀態是什麼ui

解決辦法:爲每一次狀態改變作一次緩存this

// 優化後的context.vue
<template>
  <div>
    <Steps :current="status">
      <Step title="已完成" content="這裏是第一步"></Step>
      <Step title="進行中" content="這裏是第二步"></Step>
      <Step title="待進行" content="這裏是第三步"></Step>
      <Step title="待進行" content="這裏是第四步"></Step>
    </Steps>
    <!-- 返回上一步 -->
    <button v-if="canGoBack" @click="goBack">返回上一步</button>
    <!-- 動態渲染當前狀態組件 -->
    <component :is="statusCom" @onChangeStatus="changeStatus" />
  </div>
</template>
<script>
  // 引入各狀態組件
  import Step1 from './Step1'
  import Step2 from './Step2'
  import Step3 from './Step3'
  import Step4 from './Step4'
  
  const DEFAULT_STATUS = 1
  
  export default {
    data() {
      return {
        status: DEFAULT_STATUS,
        cache: [] // 緩存狀態
      }  
    },
    computed: {
      // 具體狀態角色
      statusCom() {
        const statusMap = {
          1: Step1,
          2: Step2,
          3: Step3,
          4: Step4,
        } 
        return statusMap[this.status]
      },
      canGoBack() {
        return this.cache.length > 0
      }
    },
    methods: {
      // 表明每一步的狀態組件都有改變status的能力
      changeStatus(val) {
        // 緩存每一次的狀態變化
        this.cache.push(val)
        this.status = val
      },
      goBack() {
        // 彈出當前狀態
        this.cache.pop()
        // 改變狀態爲上一個狀態
        this.status = this.cache[this.cache.length - 1] || DEFAULT_STATUS
      }
    }  
  }
</script>
複製代碼

總結

經過工做中的一個功能設計爲你們介紹了狀態模式。或許有的同窗會說我經過if else不也能作嗎,固然隨着需求不斷的變動你的if else最終只有你本身看的懂,慢慢的bug出現的概率也越高,狀態模式正是用來解決這種問題的


本文實現一樣適用於react,爲何文章以vue作題?vue的template讓咱們在理解一些概念的時候可能會有點不適應,而react的jsx能夠看作就是在寫JavaScript對各類概念實現更靈活 友情提示:設計模式在vue中的應用應該會寫一個系列,喜歡的同窗記得關注下

相關文章
相關標籤/搜索