激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務(wù)器之家 - 編程語(yǔ)言 - JavaScript - Vue管理系統(tǒng)前端之組件拆分封裝詳解

Vue管理系統(tǒng)前端之組件拆分封裝詳解

2021-08-29 17:16Levy-偉 JavaScript

這篇文章主要給大家介紹了關(guān)于Vue管理系統(tǒng)前端之組件拆分封裝的相關(guān)資料,文中通過(guò)實(shí)例代碼結(jié)束的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

組件封裝

在上一篇記錄中,首頁(yè)中有太多的代碼,為了避免代碼的臃腫,需要對(duì)主要的功能模塊拆分,來(lái)讓代碼看起來(lái)更簡(jiǎn)潔,且能進(jìn)行復(fù)用。

拆分后還加了些小功能,加入了修改 title 的代碼,修改方式參考vue 動(dòng)態(tài)修改 title

還增加了當(dāng)前請(qǐng)求的頁(yè)面緩存,使用狀態(tài)管理器處理。監(jiān)聽(tīng)路由,保存到 state 中,來(lái)處理的。 如何監(jiān)聽(tīng)可參考vue 計(jì)算屬性和監(jiān)聽(tīng)屬性

完整效果圖如下:

Vue管理系統(tǒng)前端之組件拆分封裝詳解

首頁(yè)布局拆分后結(jié)構(gòu)

拆分后的,布局結(jié)構(gòu)圖:

Vue管理系統(tǒng)前端之組件拆分封裝詳解

拆分后代碼

布局最外層 index 代碼,使用頭部,側(cè)邊欄,主內(nèi)容欄組成,代碼如下:

  1. <!-- 布局的首頁(yè) -->
  2. <template>
  3. <div>
  4. <l-header></l-header>
  5. <l-aside></l-aside>
  6. <l-main></l-main>
  7. </div>
  8. </template>
  9. <script>
  10. import LHeader from './components/header'
  11. import LAside from './components/aside'
  12. import LMain from './components/main'
  13. export default {
  14. data() {
  15. return {}
  16. },
  17. //引入組件
  18. components: {
  19. LHeader,
  20. LAside,
  21. LMain,
  22. },
  23. }
  24. </script>
  25. <style lang="scss" scoped></style>

頭部 index.vue 代碼:

  1. <!-- 頭部文件 -->
  2. <template>
  3. <div class="header">
  4. <!-- logo -->
  5. <logo></logo>
  6. <!-- 折疊按鈕 -->
  7. <hamburger></hamburger>
  8. <!-- 頭部導(dǎo)航欄 -->
  9. <div class="heardNavBar">
  10. <el-menu default-active="1" class="el-menu-demo" background-color="#4b5f6e" text-color="#fff" active-text-color="#ffd04b" mode="horizontal">
  11. <el-menu-item index="1" @click="$router.push('/')">首頁(yè)</el-menu-item>
  12. <el-menu-item index="2" @click="openUrl('#')">使用文檔</el-menu-item>
  13. <el-menu-item index="3" @click="openUrl('https://github.com/levy-w-wang/lion-ui')">GitHub</el-menu-item>
  14. </el-menu>
  15. </div>
  16. <!-- 右側(cè)信息 -->
  17. <div style="float:right">
  18. <!-- 全屏 -->
  19. <div style="float:left;line-height: 60px; padding: 0 10px;">
  20. <i class="el-icon-full-screen" @click="toggleFull"></i>
  21. </div>
  22. <!-- 個(gè)人信息 -->
  23. <div class="userinfo">
  24. <el-dropdown trigger="hover">
  25. <span class="el-dropdown-link userinfo-inner">
  26. <img src="@assets/img/user.jpg" />
  27. {{ $store.getters.userInfo.username }}<i class="el-icon-caret-bottom"></i>
  28. </span>
  29. <el-dropdown-menu slot="dropdown">
  30. <el-dropdown-item>
  31. <router-link to="/"><i class="el-icon-s-home"></i>首頁(yè)</router-link>
  32. </el-dropdown-item>
  33. <el-dropdown-item>
  34. <router-link to="/"><i class="el-icon-s-custom"></i>我的主頁(yè)</router-link>
  35. </el-dropdown-item>
  36. <el-dropdown-item divided>
  37. <a @click="loginOut()"><i class="el-icon-switch-button"></i>登出</a>
  38. </el-dropdown-item>
  39. </el-dropdown-menu>
  40. </el-dropdown>
  41. </div>
  42. </div>
  43. </div>
  44. </template>
  45.  
  46. <script>
  47. import screenfull from 'screenfull'
  48. import hamburger from './hamburger'
  49. import logo from './logo'
  50. // import { mapState } from 'vuex'
  51. export default {
  52. data() {
  53. return {}
  54. },
  55. computed: {
  56. // ...mapState({
  57. // isCollapse: (state) => state.app.isCollapse,
  58. // }),
  59. },
  60. //引入組件
  61. components: {
  62. hamburger,
  63. logo,
  64. },
  65. // 方法
  66. methods: {
  67. openUrl(url) {
  68. window.open(url)
  69. },
  70. loginOut() {
  71. this.$confirm('確認(rèn)退出嗎?', '提示', {
  72. type: 'warning',
  73. })
  74. .then(() => {
  75. this.$store.commit('logout')
  76. })
  77. .catch(() => {})
  78. },
  79. toggleFull() {
  80. if (!screenfull.isEnabled) {
  81. this.$message({
  82. type: 'warning',
  83. message: 'you browser can not work',
  84. })
  85. return false
  86. }
  87. screenfull.toggle()
  88. },
  89. },
  90. //未掛載DOM,不能訪問(wèn)ref為空數(shù)組
  91. //可在這結(jié)束loading,還做一些初始化,實(shí)現(xiàn)函數(shù)自執(zhí)行,
  92. //可以對(duì)data數(shù)據(jù)進(jìn)行操作,可進(jìn)行一些請(qǐng)求,請(qǐng)求不易過(guò)多,避免白屏?xí)r間太長(zhǎng)。
  93. created() {},
  94. //可在這發(fā)起后端請(qǐng)求,拿回?cái)?shù)據(jù),配合路由鉤子做一些事情;可對(duì)DOM 進(jìn)行操作
  95. mounted() {},
  96. }
  97. </script>
  98.  
  99. <style lang="scss" scoped>
  100. .header {
  101. padding-left: 0px !important;
  102. height: 60px;
  103. line-height: 60px;
  104. width: 100%;
  105. background: #4b5f6e;
  106. color: #fff;
  107.  
  108. .heardNavBar {
  109. float: left;
  110. background: #4b5f6e;
  111. padding: 0px 0px;
  112. height: 60px;
  113. line-height: 60px;
  114. font-size: 28px;
  115. cursor: pointer;
  116. }
  117.  
  118. .userinfo {
  119. text-align: right;
  120. padding-right: 24px;
  121. float: right;
  122. padding: 0 10px;
  123. .userinfo-inner {
  124. font-size: 20px;
  125. cursor: pointer;
  126. color: #fff;
  127. img {
  128. width: 40px;
  129. height: 40px;
  130. border-radius: 10px;
  131. margin: 10px 0px 10px 10px;
  132. float: right;
  133. }
  134. }
  135. }
  136. }
  137. </style>

頭部中引用的相關(guān)組件代碼如下

折疊導(dǎo)航欄 hamburger 下的 index.vue 代碼:

  1. <template>
  2. <div @click="toggleCollapse">
  3. <svg :class="{ 'is-active': !isCollapse }" class="hamburger" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="64" height="64">
  4. <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
  5. </svg>
  6. </div>
  7. </template>
  8.  
  9. <script>
  10. import { mapState } from 'vuex'
  11. export default {
  12. name: 'Hamburger',
  13. computed: {
  14. ...mapState({
  15. isCollapse: (state) => state.app.isCollapse,
  16. }),
  17. },
  18. methods: {
  19. //折疊導(dǎo)航欄
  20. toggleCollapse: function () {
  21. this.$store.commit('toggleCollapse')
  22. },
  23. },
  24. }
  25. </script>
  26.  
  27. <style scoped>
  28. .hamburger {
  29. padding-left: 13px;
  30. padding-right: 13px;
  31. text-align: center;
  32. width: 34px;
  33. height: 60px;
  34. line-height: 60px;
  35. float: left;
  36. cursor: pointer;
  37. }
  38.  
  39. .is-active {
  40. transform: rotate(180deg);
  41. }
  42. </style>

折疊導(dǎo)航欄 logo 下的 index.vue 代碼:

  1. <!-- -->
  2. <template>
  3. <div class="logo" :class="isCollapse ? 'logo-collapse-width' : 'logo-width'">
  4. <img v-if="isCollapse" src="@assets/logo6065.png" @click="$router.push('/')" />
  5. <img v-else src="@assets/logo.png" @click="$router.push('/')" />
  6. </div>
  7. </template>
  8.  
  9. <script>
  10. import { mapState } from 'vuex'
  11. export default {
  12. data() {
  13. return {}
  14. },
  15. computed: {
  16. ...mapState({
  17. isCollapse: (state) => state.app.isCollapse,
  18. }),
  19. },
  20. }
  21. </script>
  22. <style lang="scss" scoped>
  23. .logo {
  24. float: left;
  25. height: 60px;
  26. padding: 0;
  27. margin: 0;
  28. }
  29. .logo-width {
  30. width: 230px;
  31. }
  32. .logo-collapse-width {
  33. width: 65px;
  34. }
  35. </style>

側(cè)邊欄下的 index.vue代碼:

  1. <!-- aside -->
  2. <template>
  3. <div class="aside-container" :class="isCollapse ? 'aside-collapse-width' : 'aside-width'">
  4. <!--導(dǎo)航菜單 default-active="1-1"-->
  5. <el-menu class="el-menu-vertical-demo" :class="isCollapse ? 'aside-collapse-width' : 'aside-width'" :collapse-transition="false" :unique-opened="true" :collapse="isCollapse">
  6. <el-submenu index="1">
  7. <template slot="title">
  8. <i class="el-icon-setting"></i>
  9. <span slot="title">系統(tǒng)管理</span>
  10. </template>
  11. <el-menu-item index="1-1" @click="$router.push('usermanage')">用戶管理</el-menu-item>
  12. <el-menu-item index="1-2" @click="$router.push('menumanage')">菜單管理</el-menu-item>
  13. </el-submenu>
  14. <el-menu-item index="2" disabled>
  15. <i class="el-icon-magic-stick"></i>
  16. <span slot="title">導(dǎo)航一</span>
  17. </el-menu-item>
  18. <el-menu-item index="3" disabled>
  19. <i class="el-icon-reading"></i>
  20. <span slot="title">導(dǎo)航二</span>
  21. </el-menu-item>
  22. </el-menu>
  23. </div>
  24. </template>
  25.  
  26. <script>
  27. import { mapState } from 'vuex'
  28. export default {
  29. data() {
  30. return {}
  31. },
  32. //$store.getters.isCollapse
  33. computed: {
  34. ...mapState({
  35. isCollapse: (state) => state.app.isCollapse,
  36. }),
  37. mainTabs: {
  38. get() {
  39. return this.$store.state.app.mainTabs
  40. },
  41. set(val) {
  42. this.$store.commit('updateMainTabs', val)
  43. },
  44. },
  45. mainTabsActiveName: {
  46. get() {
  47. return this.$store.state.app.mainTabsActiveName
  48. },
  49. set(val) {
  50. this.$store.commit('updateMainTabsActiveName', val)
  51. },
  52. },
  53. },
  54. watch: {
  55. $route: 'handleRoute',
  56. },
  57. created() {
  58. console.log(this.$route)
  59. this.handleRoute(this.$route)
  60. },
  61. methods: {
  62. // 路由操作處理
  63. handleRoute(route) {
  64. // tab標(biāo)簽頁(yè)選中, 如果不存在則先添加
  65. var tab = this.mainTabs.filter((item) => item.name === route.name)[0]
  66. if (!tab) {
  67. tab = {
  68. name: route.name,
  69. title: route.meta.title,
  70. icon: route.meta.icon,
  71. }
  72. this.mainTabs = this.mainTabs.concat(tab)
  73. }
  74. this.mainTabsActiveName = tab.name
  75. },
  76. },
  77. }
  78. </script>
  79. <style lang="scss" scoped>
  80. .aside-container {
  81. position: fixed;
  82. top: 0px;
  83. left: 0;
  84. bottom: 0;
  85. z-index: 1020;
  86. .el-menu {
  87. position: absolute;
  88. top: 60px;
  89. bottom: 0px;
  90. text-align: left;
  91. }
  92. }
  93. .aside-width {
  94. width: 230px;
  95. }
  96. .aside-collapse-width {
  97. width: 65px;
  98. }
  99. </style>

內(nèi)容模塊下的 index.vue代碼:

  1. <!-- -->
  2. <template>
  3. <div class="main-container clear" :class="isCollapse ? 'position-collapse-left' : 'position-left'">
  4. <!-- 標(biāo)簽頁(yè) -->
  5. <el-tabs class="tabs" :class="isCollapse ? 'position-collapse-left' : 'position-left'" v-model="mainTabsActiveName" :closable="true" type="card" @tab-click="selectedTabHandle" @tab-remove="removeTabHandle">
  6. <el-dropdown class="tabs-tools" :show-timeout="0" trigger="hover">
  7. <div style="font-size:20px;width:50px;">
  8. <i class="el-icon-arrow-down"></i>
  9. </div>
  10. <el-dropdown-menu slot="dropdown">
  11. <el-dropdown-item @click.native="tabsCloseCurrentHandle">關(guān)閉當(dāng)前標(biāo)簽</el-dropdown-item>
  12. <el-dropdown-item @click.native="tabsCloseOtherHandle">關(guān)閉其它標(biāo)簽</el-dropdown-item>
  13. <el-dropdown-item @click.native="tabsCloseAllHandle">關(guān)閉全部標(biāo)簽</el-dropdown-item>
  14. <el-dropdown-item @click.native="tabsRefreshCurrentHandle">刷新當(dāng)前標(biāo)簽</el-dropdown-item>
  15. </el-dropdown-menu>
  16. </el-dropdown>
  17. <el-tab-pane v-for="item in mainTabs" :key="item.name" :label="item.title" :name="item.name">
  18. <span slot="label"> <i :class="item.icon"></i> {{ item.title }} </span>
  19. </el-tab-pane>
  20. </el-tabs>
  21.  
  22. <!-- 主內(nèi)容區(qū)域 -->
  23. <div class="main-content">
  24. <keep-alive>
  25. <transition name="fade" mode="out-in">
  26. <router-view></router-view>
  27. </transition>
  28. </keep-alive>
  29. </div>
  30. </div>
  31. </template>
  32.  
  33. <script>
  34. import { mapState } from 'vuex'
  35. export default {
  36. data() {
  37. return {}
  38. },
  39. computed: {
  40. ...mapState({
  41. isCollapse: (state) => state.app.isCollapse,
  42. }),
  43. mainTabs: {
  44. get() {
  45. return this.$store.state.app.mainTabs
  46. },
  47. set(val) {
  48. this.$store.commit('updateMainTabs', val)
  49. },
  50. },
  51. mainTabsActiveName: {
  52. get() {
  53. return this.$store.state.app.mainTabsActiveName
  54. },
  55. set(val) {
  56. this.$store.commit('updateMainTabsActiveName', val)
  57. },
  58. },
  59. },
  60. methods: {
  61. // tabs, 選中tab
  62. selectedTabHandle(tab) {
  63. tab = this.mainTabs.filter((item) => item.name === tab.name)
  64. if (tab.length >= 1) {
  65. this.$router.push({ name: tab[0].name })
  66. }
  67. },
  68. // tabs, 刪除tab
  69. removeTabHandle(tabName) {
  70. // 當(dāng)只有首頁(yè)時(shí),不允許關(guān)掉。 若是其它頁(yè)面可關(guān)掉后,push 首頁(yè)進(jìn)去
  71. if (this.mainTabs.length == 1 && this.mainTabs[0].name == 'index') {
  72. return
  73. }
  74. this.mainTabs = this.mainTabs.filter((item) => item.name !== tabName)
  75. if (this.mainTabs.length >= 1) {
  76. // 當(dāng)前選中tab被刪除
  77. if (tabName === this.mainTabsActiveName) {
  78. this.$router.push({ name: this.mainTabs[this.mainTabs.length - 1].name }, () => {
  79. this.mainTabsActiveName = this.$route.name
  80. })
  81. }
  82. } else {
  83. this.$router.push('/')
  84. }
  85. },
  86. // tabs, 關(guān)閉當(dāng)前
  87. tabsCloseCurrentHandle() {
  88. this.removeTabHandle(this.mainTabsActiveName)
  89. },
  90. // tabs, 關(guān)閉其它
  91. tabsCloseOtherHandle() {
  92. this.mainTabs = this.mainTabs.filter((item) => item.name === this.mainTabsActiveName)
  93. },
  94. // tabs, 關(guān)閉全部
  95. tabsCloseAllHandle() {
  96. this.mainTabs = []
  97. this.$router.push('/')
  98. },
  99. // tabs, 刷新當(dāng)前
  100. tabsRefreshCurrentHandle() {
  101. var tempTabName = this.mainTabsActiveName
  102. this.removeTabHandle(tempTabName)
  103. this.$nextTick(() => {
  104. this.$router.push({ name: tempTabName })
  105. })
  106. },
  107. },
  108. }
  109. </script>
  110. <style lang="scss" scoped>
  111. .main-container {
  112. padding: 0 5px 5px;
  113. position: absolute;
  114. top: 60px;
  115. left: 1px;
  116. right: 1px;
  117. bottom: 0px;
  118. .tabs {
  119. position: fixed;
  120. top: 60px;
  121. right: 50px;
  122. padding-left: 0px;
  123. padding-right: 2px;
  124. z-index: 1020;
  125. height: 40px;
  126. line-height: 40px;
  127. font-size: 14px;
  128. background: rgb(255, 253, 255);
  129. border-color: rgba(200, 206, 206, 0.5);
  130. // border-left-width: 1px;
  131. // border-left-style: solid;
  132. border-bottom-width: 1px;
  133. border-bottom-style: solid;
  134. }
  135. .tabs-tools {
  136. position: fixed;
  137. top: 60px;
  138. right: 0;
  139. z-index: 1020;
  140. height: 40px;
  141. // padding: 0 10px;
  142. font-size: 14px;
  143. line-height: 40px;
  144. cursor: pointer;
  145. border-color: rgba(200, 206, 206, 0.5);
  146. border-left-width: 1px;
  147. border-left-style: solid;
  148. border-bottom-width: 1px;
  149. border-bottom-style: solid;
  150. background: rgba(255, 255, 255, 1);
  151. }
  152. .tabs-tools:hover {
  153. background: rgba(200, 206, 206, 1);
  154. }
  155. .main-content {
  156. position: absolute;
  157. top: 45px;
  158. left: 5px;
  159. right: 5px;
  160. bottom: 5px;
  161. padding: 5px;
  162. // background: rgba(209, 212, 212, 0.5);
  163. }
  164. }
  165. .position-left {
  166. left: 230px;
  167. }
  168. .position-collapse-left {
  169. left: 65px;
  170. }
  171. </style>

狀態(tài)管理中添加 app 模塊

代碼如下:

  1. export default {
  2. state: {
  3. // 是否折疊導(dǎo)航欄
  4. isCollapse: false,
  5. // 訪問(wèn)頁(yè)集合
  6. mainTabs: [],
  7. // 當(dāng)前訪問(wèn)頁(yè)名
  8. mainTabsActiveName: '',
  9. },
  10. getters: {
  11. isCollapse: (state) => {
  12. return state.isCollapse
  13. },
  14. },
  15. mutations: {
  16. toggleCollapse(state) {
  17. state.isCollapse = !state.isCollapse
  18. },
  19. updateMainTabs(state, tabs) {
  20. state.mainTabs = tabs
  21. },
  22. updateMainTabsActiveName(state, name) {
  23. state.mainTabsActiveName = name
  24. },
  25. },
  26. actions: {},
  27. }

當(dāng)然還有一些小的調(diào)整點(diǎn),可參考 git 上的提交版本 首頁(yè)組件拆分

總結(jié)

到此這篇關(guān)于Vue管理系統(tǒng)前端之組件拆分封裝的文章就介紹到這了,更多相關(guān)Vue組件拆分封裝內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://www.cnblogs.com/levywang/p/13543734.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美特黄一级高清免费的香蕉 | 最新中文字幕日本 | 男女生羞羞视频网站在线观看 | 日韩一级毛毛片 | 亚洲欧洲日产v特级毛片 | 青青操精品 | 亚洲精品v天堂中文字幕 | 午夜色视频在线观看 | asian超清日本肉体pics | 久久久一区二区三区精品 | 国产亚洲精品久久久久久久久久 | 九九热视频在线免费观看 | 日本在线看 | av免费在线免费观看 | 午夜a狂野欧美一区二区 | 新久草在线视频 | 美国黄色毛片女人性生活片 | 99精彩视频在线观看 | 羞羞的视频在线免费观看 | 中文字幕一区久久 | 姑娘第5集高清在线观看 | 男女做性免费网站 | 日本免费大片免费视频 | 99成人在线 | 91成人影库 | av色偷偷 | 免费看日韩av| 极色品影院 | 成人国产精品齐天大性 | 国产一区精品在线观看 | 国产免费久久久久 | 久久精品亚洲精品国产欧美kt∨ | 国产视频99 | 久久福利电影网 | 国产一区亚洲 | 欧美成人小视频 | 国产精品99久久免费观看 | 免费看污视频在线观看 | 成人国产在线看 | 香蕉视频网站在线观看 | 国产中文一区 |