您好,登錄后才能下訂單哦!
這篇文章運用簡單易懂的例子給大家介紹利用Vue如何實現組件封裝,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
組件封裝
完整效果圖如下:
首頁布局拆分后結構
拆分后的,布局結構圖:
拆分后代碼
布局最外層 index 代碼,使用頭部,側邊欄,主內容欄組成,代碼如下:
<!-- 布局的首頁 --> <template> <div> <l-header></l-header> <l-aside></l-aside> <l-main></l-main> </div> </template> <script> import LHeader from './components/header' import LAside from './components/aside' import LMain from './components/main' export default { data() { return {} }, //引入組件 components: { LHeader, LAside, LMain, }, } </script> <style lang="scss" scoped></style>
頭部 index.vue 代碼:
<!-- 頭部文件 --> <template> <div class="header"> <!-- logo --> <logo></logo> <!-- 折疊按鈕 --> <hamburger></hamburger> <!-- 頭部導航欄 --> <div class="heardNavBar"> <el-menu default-active="1" class="el-menu-demo" background-color="#4b5f6e" text-color="#fff" active-text-color="#ffd04b" mode="horizontal"> <el-menu-item index="1" @click="$router.push('/')">首頁</el-menu-item> <el-menu-item index="2" @click="openUrl('#')">使用文檔</el-menu-item> <el-menu-item index="3" @click="openUrl('https://github.com/levy-w-wang/lion-ui')">GitHub</el-menu-item> </el-menu> </div> <!-- 右側信息 --> <div > <!-- 全屏 --> <div > <i class="el-icon-full-screen" @click="toggleFull"></i> </div> <!-- 個人信息 --> <div class="userinfo"> <el-dropdown trigger="hover"> <span class="el-dropdown-link userinfo-inner"> <img src="@assets/img/user.jpg" /> {{ $store.getters.userInfo.username }}<i class="el-icon-caret-bottom"></i> </span> <el-dropdown-menu slot="dropdown"> <el-dropdown-item> <router-link to="/"><i class="el-icon-s-home"></i>首頁</router-link> </el-dropdown-item> <el-dropdown-item> <router-link to="/"><i class="el-icon-s-custom"></i>我的主頁</router-link> </el-dropdown-item> <el-dropdown-item divided> <a @click="loginOut()"><i class="el-icon-switch-button"></i>登出</a> </el-dropdown-item> </el-dropdown-menu> </el-dropdown> </div> </div> </div> </template> <script> import screenfull from 'screenfull' import hamburger from './hamburger' import logo from './logo' // import { mapState } from 'vuex' export default { data() { return {} }, computed: { // ...mapState({ // isCollapse: (state) => state.app.isCollapse, // }), }, //引入組件 components: { hamburger, logo, }, // 方法 methods: { openUrl(url) { window.open(url) }, loginOut() { this.$confirm('確認退出嗎?', '提示', { type: 'warning', }) .then(() => { this.$store.commit('logout') }) .catch(() => {}) }, toggleFull() { if (!screenfull.isEnabled) { this.$message({ type: 'warning', message: 'you browser can not work', }) return false } screenfull.toggle() }, }, //未掛載DOM,不能訪問ref為空數組 //可在這結束loading,還做一些初始化,實現函數自執行, //可以對data數據進行操作,可進行一些請求,請求不易過多,避免白屏時間太長。 created() {}, //可在這發起后端請求,拿回數據,配合路由鉤子做一些事情;可對DOM 進行操作 mounted() {}, } </script> <style lang="scss" scoped> .header { padding-left: 0px !important; height: 60px; line-height: 60px; width: 100%; background: #4b5f6e; color: #fff; .heardNavBar { float: left; background: #4b5f6e; padding: 0px 0px; height: 60px; line-height: 60px; font-size: 28px; cursor: pointer; } .userinfo { text-align: right; padding-right: 24px; float: right; padding: 0 10px; .userinfo-inner { font-size: 20px; cursor: pointer; color: #fff; img { width: 40px; height: 40px; border-radius: 10px; margin: 10px 0px 10px 10px; float: right; } } } } </style>
頭部中引用的相關組件代碼如下
折疊導航欄 hamburger 下的 index.vue 代碼:
<template> <div @click="toggleCollapse"> <svg :class="{ 'is-active': !isCollapse }" class="hamburger" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="64" height="64"> <path d="M408 442h580c4.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 8h580c4.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" /> </svg> </div> </template> <script> import { mapState } from 'vuex' export default { name: 'Hamburger', computed: { ...mapState({ isCollapse: (state) => state.app.isCollapse, }), }, methods: { //折疊導航欄 toggleCollapse: function () { this.$store.commit('toggleCollapse') }, }, } </script> <style scoped> .hamburger { padding-left: 13px; padding-right: 13px; text-align: center; width: 34px; height: 60px; line-height: 60px; float: left; cursor: pointer; } .is-active { transform: rotate(180deg); } </style>
折疊導航欄 logo 下的 index.vue 代碼:
<!-- --> <template> <div class="logo" :class="isCollapse ? 'logo-collapse-width' : 'logo-width'"> <img v-if="isCollapse" src="@assets/logo6065.png" @click="$router.push('/')" /> <img v-else src="@assets/logo.png" @click="$router.push('/')" /> </div> </template> <script> import { mapState } from 'vuex' export default { data() { return {} }, computed: { ...mapState({ isCollapse: (state) => state.app.isCollapse, }), }, } </script> <style lang="scss" scoped> .logo { float: left; height: 60px; padding: 0; margin: 0; } .logo-width { width: 230px; } .logo-collapse-width { width: 65px; } </style>
側邊欄下的 index.vue代碼:
<!-- aside --> <template> <div class="aside-container" :class="isCollapse ? 'aside-collapse-width' : 'aside-width'"> <!--導航菜單 default-active="1-1"--> <el-menu class="el-menu-vertical-demo" :class="isCollapse ? 'aside-collapse-width' : 'aside-width'" :collapse-transition="false" :unique-opened="true" :collapse="isCollapse"> <el-submenu index="1"> <template slot="title"> <i class="el-icon-setting"></i> <span slot="title">系統管理</span> </template> <el-menu-item index="1-1" @click="$router.push('usermanage')">用戶管理</el-menu-item> <el-menu-item index="1-2" @click="$router.push('menumanage')">菜單管理</el-menu-item> </el-submenu> <el-menu-item index="2" disabled> <i class="el-icon-magic-stick"></i> <span slot="title">導航一</span> </el-menu-item> <el-menu-item index="3" disabled> <i class="el-icon-reading"></i> <span slot="title">導航二</span> </el-menu-item> </el-menu> </div> </template> <script> import { mapState } from 'vuex' export default { data() { return {} }, //$store.getters.isCollapse computed: { ...mapState({ isCollapse: (state) => state.app.isCollapse, }), mainTabs: { get() { return this.$store.state.app.mainTabs }, set(val) { this.$store.commit('updateMainTabs', val) }, }, mainTabsActiveName: { get() { return this.$store.state.app.mainTabsActiveName }, set(val) { this.$store.commit('updateMainTabsActiveName', val) }, }, }, watch: { $route: 'handleRoute', }, created() { console.log(this.$route) this.handleRoute(this.$route) }, methods: { // 路由操作處理 handleRoute(route) { // tab標簽頁選中, 如果不存在則先添加 var tab = this.mainTabs.filter((item) => item.name === route.name)[0] if (!tab) { tab = { name: route.name, title: route.meta.title, icon: route.meta.icon, } this.mainTabs = this.mainTabs.concat(tab) } this.mainTabsActiveName = tab.name }, }, } </script> <style lang="scss" scoped> .aside-container { position: fixed; top: 0px; left: 0; bottom: 0; z-index: 1020; .el-menu { position: absolute; top: 60px; bottom: 0px; text-align: left; } } .aside-width { width: 230px; } .aside-collapse-width { width: 65px; } </style>
內容模塊下的 index.vue代碼:
<!-- --> <template> <div class="main-container clear" :class="isCollapse ? 'position-collapse-left' : 'position-left'"> <!-- 標簽頁 --> <el-tabs class="tabs" :class="isCollapse ? 'position-collapse-left' : 'position-left'" v-model="mainTabsActiveName" :closable="true" type="card" @tab-click="selectedTabHandle" @tab-remove="removeTabHandle"> <el-dropdown class="tabs-tools" :show-timeout="0" trigger="hover"> <div > <i class="el-icon-arrow-down"></i> </div> <el-dropdown-menu slot="dropdown"> <el-dropdown-item @click.native="tabsCloseCurrentHandle">關閉當前標簽</el-dropdown-item> <el-dropdown-item @click.native="tabsCloseOtherHandle">關閉其它標簽</el-dropdown-item> <el-dropdown-item @click.native="tabsCloseAllHandle">關閉全部標簽</el-dropdown-item> <el-dropdown-item @click.native="tabsRefreshCurrentHandle">刷新當前標簽</el-dropdown-item> </el-dropdown-menu> </el-dropdown> <el-tab-pane v-for="item in mainTabs" :key="item.name" :label="item.title" :name="item.name"> <span slot="label"> <i :class="item.icon"></i> {{ item.title }} </span> </el-tab-pane> </el-tabs> <!-- 主內容區域 --> <div class="main-content"> <keep-alive> <transition name="fade" mode="out-in"> <router-view></router-view> </transition> </keep-alive> </div> </div> </template> <script> import { mapState } from 'vuex' export default { data() { return {} }, computed: { ...mapState({ isCollapse: (state) => state.app.isCollapse, }), mainTabs: { get() { return this.$store.state.app.mainTabs }, set(val) { this.$store.commit('updateMainTabs', val) }, }, mainTabsActiveName: { get() { return this.$store.state.app.mainTabsActiveName }, set(val) { this.$store.commit('updateMainTabsActiveName', val) }, }, }, methods: { // tabs, 選中tab selectedTabHandle(tab) { tab = this.mainTabs.filter((item) => item.name === tab.name) if (tab.length >= 1) { this.$router.push({ name: tab[0].name }) } }, // tabs, 刪除tab removeTabHandle(tabName) { // 當只有首頁時,不允許關掉。 若是其它頁面可關掉后,push 首頁進去 if (this.mainTabs.length == 1 && this.mainTabs[0].name == 'index') { return } this.mainTabs = this.mainTabs.filter((item) => item.name !== tabName) if (this.mainTabs.length >= 1) { // 當前選中tab被刪除 if (tabName === this.mainTabsActiveName) { this.$router.push({ name: this.mainTabs[this.mainTabs.length - 1].name }, () => { this.mainTabsActiveName = this.$route.name }) } } else { this.$router.push('/') } }, // tabs, 關閉當前 tabsCloseCurrentHandle() { this.removeTabHandle(this.mainTabsActiveName) }, // tabs, 關閉其它 tabsCloseOtherHandle() { this.mainTabs = this.mainTabs.filter((item) => item.name === this.mainTabsActiveName) }, // tabs, 關閉全部 tabsCloseAllHandle() { this.mainTabs = [] this.$router.push('/') }, // tabs, 刷新當前 tabsRefreshCurrentHandle() { var tempTabName = this.mainTabsActiveName this.removeTabHandle(tempTabName) this.$nextTick(() => { this.$router.push({ name: tempTabName }) }) }, }, } </script> <style lang="scss" scoped> .main-container { padding: 0 5px 5px; position: absolute; top: 60px; left: 1px; right: 1px; bottom: 0px; .tabs { position: fixed; top: 60px; right: 50px; padding-left: 0px; padding-right: 2px; z-index: 1020; height: 40px; line-height: 40px; font-size: 14px; background: rgb(255, 253, 255); border-color: rgba(200, 206, 206, 0.5); // border-left-width: 1px; // border-left-style: solid; border-bottom-width: 1px; border-bottom-style: solid; } .tabs-tools { position: fixed; top: 60px; right: 0; z-index: 1020; height: 40px; // padding: 0 10px; font-size: 14px; line-height: 40px; cursor: pointer; border-color: rgba(200, 206, 206, 0.5); border-left-width: 1px; border-left-style: solid; border-bottom-width: 1px; border-bottom-style: solid; background: rgba(255, 255, 255, 1); } .tabs-tools:hover { background: rgba(200, 206, 206, 1); } .main-content { position: absolute; top: 45px; left: 5px; right: 5px; bottom: 5px; padding: 5px; // background: rgba(209, 212, 212, 0.5); } } .position-left { left: 230px; } .position-collapse-left { left: 65px; } </style>
狀態管理中添加 app 模塊
代碼如下:
export default { state: { // 是否折疊導航欄 isCollapse: false, // 訪問頁集合 mainTabs: [], // 當前訪問頁名 mainTabsActiveName: '', }, getters: { isCollapse: (state) => { return state.isCollapse }, }, mutations: { toggleCollapse(state) { state.isCollapse = !state.isCollapse }, updateMainTabs(state, tabs) { state.mainTabs = tabs }, updateMainTabsActiveName(state, name) { state.mainTabsActiveName = name }, }, actions: {}, }
關于利用Vue如何實現組件封裝就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。