管理系統內 Tag 功能的實現

圖片描述

愈發純熟的業務代碼——開始作菜

原文地址vue

1.背景 && 需求分析

1.1 背景

某日,被後臺拿着一個別人實現好的管理系統說道了一頓,說須要實現得比某框架更好react

地址:pig4cloudgit

1.2 需求分析

需求:管理系統內實現瀏覽器 Tag 標籤的功能github

分析:vue-router

  1. 切換 Tag 不主動更新頁面(重點)
  2. 關閉活動中的 Tag 切換至後一個
  3. 若關閉 Tag 爲最後一個,切換至前一個

2. 實現邏輯

技術棧:react + react-router + react-redux + react-sagavuex

重點:組件更新,頁面不變redux

上 demo :Edit react-tag-demo數組

2.1 內存邏輯

思路:卻分活動狀態內的存,和在打開過的內存,兩個內存同事更新,切換 Tag 從打開過的數組內調取數據,有數據使用該數據,無數據則發起請求瀏覽器

  • tagList 側欄點擊過的 Tag 數組
  • activeTag 活動狀態的 Tag

操做同歸在 Reduce 內,方便後續 Tag 內外部交互session

/*.
目錄:/src/store/index.js
*/
const appReducer ={
  tabListStatus: (state = { tabList: [], activeTab: null }, action) => {
    switch (action.type) {
      case 'tabListChange':
          //
      case 'tabListAdd':
          //
      case 'tabListRemove':
          //
      case 'tabListClear':
          //
      default:
        return state
    }
  },
  // ...
}

全部內存初始狀態,都在 App.js->componentDidUpdate 生命週期內存操做

/*
目錄:/src/App.js
 */

componentDidUpdate(prevProps, prevState) {
  if (this.props.tabListStatus !== prevProps.tabListStatus) {
    const { tabList, activeTab } = this.props.tabListStatus
    sessionStorage.setItem('tabList', JSON.stringify(tabList))
    sessionStorage.setItem('activeTab', JSON.stringify(activeTab))
    this.setState({
      tabList,
      activeTab: activeTab !== null ? activeTab.key : '/'
    })
  }
}

2.2 外部交互邏輯

  1. 側欄邏輯,新增
  2. 點擊邏輯,切換 Tag
  3. 關閉 Tag
class App extends Component {
  // 點擊側欄
  handleOnMenuItem = param => {
    const { tabListAdd, tabListStatus } = this.props
    const { tabList } = tabListStatus
    const userMenu = menuDataSource
    const menu = this.menuItemFilter(userMenu, `/nav_${param.key}`)

    let paramTab = {
      title: menu.name,
      key: menu.path,
      queryParam: {},
      dataSource: {}
    }

    //判斷是否爲新增
    let pushBol = true
    tabList.map(tab => {
      if (tab.key === paramTab.key) {
        pushBol = false
        paramTab = Object.assign({},paramTab,tab)
      }
      return tab
    })

    if (pushBol) {
      tabList.push(paramTab)
    }

    tabListAdd({
      tabList,
      activeTab: paramTab
    })

    this.toPath(`nav_${param.key}`)
  }
  // 點擊 Tag
  onChange = activeKey => {
    // console.log('....', activeKey)
    const { tabListStatus, tabListAdd } = this.props
    const { tabList } = tabListStatus
    const userMenu = tabList
    const menu = this.menuChangeFilter(userMenu, activeKey)

    const paramTab = {
      ...menu
    }

    tabListAdd({
      tabList,
      activeTab: paramTab
    })

    this.toPath(activeKey)
  }
  // 關閉邏輯
  remove = targetKey => {
    let activeKey = this.state.activeTab
    let panes = this.state.tabList
    let lastIndex
    panes.forEach((pane, i) => {
      if (pane.key === targetKey) {
        lastIndex = panes.length - 1 === i ? i - 1 : i
      }
    })
    const panesFilter = panes.filter(pane => pane.key !== targetKey)

    if (panesFilter.length && activeKey === targetKey) {
      if (lastIndex >= 0) {
        activeKey = panesFilter[lastIndex]
      } else {
        activeKey = panesFilter[0]
      }
    } else {
      activeKey = null
    }

    this.props.tabListAdd({
      tabList: panesFilter,
      activeTab: activeKey
    })

    this.toPath(activeKey !== null ? activeKey.key : '/')
  }

  // ...
}

2.3 內部交互邏輯

  • 判斷是否新增
  • 操做更新 onChange, onClear, onSubmit

使用標記符號,或者直接判斷一個 key 值是否存在值,來發送請求,demo 內使用 dataSource 是否存在爲空來判斷是否須要發送請求

componentDidMount() {
  const { tabListStatus, musicList_query_param, musicList } = this.props
  const { dataSource } = tabListStatus.activeTab

  if (!Object.keys(dataSource).length) {
    musicList(musicList_query_param)
  }
}

操做更新 onChange, onClear, onSubmit 除了這一些之外還會存在不一樣的操做,demo 大體分了這幾個操做,均使用 reducer 操做,App.js 內監聽操做,更改內存,模塊內不參與內存更改

onChange = (tabList, e) => {
  e.persist()
  if (!e || !e.target) {
    return
  }
  const { target } = e
  const operateParam = operateQuery(tabList, {
    [target.id]: target.type === 'checkbox' ? target.checked : target.value
  })

  this.props.tabListChange(operateParam)
}

3. 對比

3.1 Vue 的實現

  • 技術棧:vue + vue-router + vuex
  • UI 框架:ant-design

關鍵:keep-alive

Edit vue-tag-demo

3.2 React 的實現

  • 技術棧:react + react-router + redux
  • UI 框架:ant-design

關鍵:redux 與內存處理

Edit react-tag-demo

4. 總結

實現上面確定是 Vue 更快實現的,但對使用 React 內存的控制也是一件很是好玩的事情,若是項目大了,就更好玩了

實際上這種實現有點雞肋,由於用戶一個不留意,關了頁面,這些 Tag 就不存在了,不管是那種管理系統,這個實現若是配合到後臺,可能就更好玩了

感謝 @白白,感謝 @同事,都提供了很不錯的思路

感謝閱讀,代碼很爛,請輕噴

相關文章
相關標籤/搜索