vue項目實戰:項目布局和公共文件夾的確定


1.布局文件 

<!-- * @Description: 布局容器組件 vue-intro + intro.js 新手引導頁功能 home文件 * @Version: 2.0 * @Autor: lhl * @Date: 2020-06-11 17:54:29 * @LastEditors: lhl * @LastEditTime: 2020-08-20 16:54:29 --> 
<!--  -->
<template>
  <div class="layout-box">
    <el-container>
      <el-header>
        <topHeader />
      </el-header>
      <el-container>
        <el-aside width="220px">
          <el-scrollbar class="page-component__scroll">
            <siderBar />
          </el-scrollbar>
        </el-aside>
        <el-main>
          <div class="right-view" ref="rightViewBox">
            <!-- <Breadcrumb ref="bread"/> -->
            <transition name="fade-transform" mode="out-in">
              <keep-alive :include="keepAliveList">
                <router-view></router-view>
              </keep-alive>
            </transition>
          </div>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
// router-view 的 key 或者用路由鈎子 再或者用監聽路由變化 // 場景:由於 Vue 會復用相同組件, 即 /detail/1 => /detail/2 或者 /detail?id=1 => /detail?id=2 這類鏈接跳轉時, 將不在執行created, mounted之類的鈎子 // <router-view :key="$route.fullPath"></router-view> // 這樣組件的 created 和 mounted 就都會執行
import topHeader from "./topHeader"; import siderBar from "./siderBar"; import Breadcrumb from '../Breadcrumb/index' import { mapActions, mapGetters, mapMutations } from "vuex"; // 引導
import Driver from 'driver.js' // import driver.js
import 'driver.js/dist/driver.min.css' // import driver.js css
import steps from '@/common/steps' export default { components: { topHeader, siderBar, Breadcrumb }, data() { //這里存放數據
    return { keepAliveList: ['baiduMapTest'] // 緩存的組件
 } }, methods: { ...mapMutations(["setContentBoxHeight", "setBtnPermitCode"]), // 系統引導
 guide() { const driver = new Driver() driver.defineSteps(steps) driver.start() }, // 獲取按鈕code碼
 getBtnCodeList(){ this.$http.user.btnList().then(res => { console.log(res) if(res.returnResult === 200){ this.setBtnPermitCode(res.returnData.buttonList) } }) } }, computed:{ ...mapGetters(['getcontentBoxHeight']) }, created() { this.getBtnCodeList() }, mounted() { this.guide(); //第二種方法
      if (window.performance.navigation.type == 1) { console.log("頁面被刷新") } else { console.log("首次被加載") } window.addEventListener("resize", () => { if (this.$refs.rightViewBox && this.$refs.rightViewBox.clientHeight) { this.setContentBoxHeight(this.$refs.rightViewBox.clientHeight); // console.log(this.$refs.rightViewBox.clientHeight, "rightViewBox");
 } }) if (this.$refs.rightViewBox.clientHeight) { this.setContentBoxHeight(this.$refs.rightViewBox.clientHeight); } } }; </script>
<style lang='scss' scoped> //@import url(); 引入公共css類 .layout-box { height: 100%; min-width: 1200px; .el-aside { position: absolute; top: 60px; bottom: 0; background: #3db4f8; .el-menu{ border-right: none;
    } } .el-main { position: absolute; left: 220px; right: 0; top: 60px; bottom: 0; padding: 10px; background: #eee; .right-view{ padding: 20px; background: #fff; min-height: 100%;
    } } } </style>
<!-- * @Description: 側邊欄組件 * @Version: 2.0 * @Autor: lhl * @Date: 2020-06-11 17:54:54 * @LastEditors: lhl * @LastEditTime: 2020-07-17 14:22:49 --> 

<!--  -->
<template>
  <div class="sider-content-box">
    <el-menu class="el-menu-vertical-demo" background-color="#3DB4F8" text-color="#fff" active-text-color="#fff" :collapse-transition="false" router >
      <!-- 一級菜單 -->
      <template v-for="(item,index) in menuData">
        <el-submenu v-if="item.children && item.children.length" :index="item.menuUrl" :key="item.menuUrl"
        >
          <template slot="title">
            <i :class="item.icon"></i>
            <span>{{item.name}}</span>
          </template>
          <!-- 二級菜單 -->
          <template v-for="(itemChild,vIndex) in item.children">
            <el-submenu v-if="itemChild.children && itemChild.children.length" :index="itemChild.menuUrl" :key="vIndex"
            >
              <template slot="title">
                <i :class="itemChild.icon"></i>
                <span>{{itemChild.name}}</span>
              </template>
              <!-- 三級菜單 -->
              <el-menu-item v-for="itemChild_Child in itemChild.children" :index="itemChild_Child.menuUrl" :key="itemChild_Child.menuUrl"
              >
                <i :class="itemChild_Child.icon"></i>
                <span slot="title">{{itemChild_Child.name}}</span>
              </el-menu-item>
            </el-submenu>
            <el-menu-item v-else :index="itemChild.menuUrl" :key="itemChild.vIndex">
              <i :class="itemChild.icon"></i>
              <span slot="title">{{itemChild.name}}</span>
            </el-menu-item>
          </template>
        </el-submenu>
        <el-menu-item v-else :index="item.menuUrl" :key="index">
          <i :class="item.icon"></i>
          <span slot="title">{{item.name}}</span>
        </el-menu-item>
      </template>
    </el-menu>
  </div>
</template>

<script> import { menuData } from '@/common/constant' export default { components: {}, data() { //這里存放數據
    return { menuData }; }, computed: {}, watch: {}, methods: {}, created() {}, mounted() {} }; </script>
<style lang='scss' scoped> //@import url(); 引入公共css類 </style>
<!-- * @Description: 頭部組件 * @Version: 2.0 * @Autor: lhl * @Date: 2020-06-12 09:12:02 * @LastEditors: lhl * @LastEditTime: 2020-08-04 17:33:36 --> 
<!--  -->
<template>
  <div class="header-content-box">
    <div class="logo" id="logo">
      <img src="@/assets/logo.png" alt />
    </div>
    <div id="title">vue測試管理系統</div>
    <div class="top-info">
      <div class="user-avatar">
        <img src="@/assets/logo.png" alt />
      </div>
      <div class="user-down" id="user">
        <el-dropdown trigger="click" @command="handleCommand">
          <span class="el-dropdown-link"> {{getUserInfo.userName || '默認用戶'}} <i class="el-icon-arrow-down el-icon--right"></i>
          </span>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item command="baseInfo">基本資料</el-dropdown-item>
            <el-dropdown-item command="changePassword">修改密碼</el-dropdown-item>
            <el-dropdown-item divided command="loginOut">退出登錄</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
      </div>
    </div>
    <el-dialog title="用戶基本資料" :visible.sync="dialogVisibleInfo" width="50%">
      <div class="user-info">
        <p>id:{{getUserInfo.id}}</p>
        <p>用戶名:{{getUserInfo.userName}}</p>
        <p>賬號:{{getUserInfo.domainAccount}}</p>
        <p>所在公司:{{getUserInfo.organizationName}}</p>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisibleInfo = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisibleInfo = false">確 定</el-button>
      </span>
    </el-dialog>

    <el-dialog title="修改密碼" :visible.sync="dialogVisibleChangePwd" width="50%">
      <el-form ref="ruleForm" :model="ruleForm" :rules="resetRules" class="login-form" label-width="80px" label-position="left"
      >
        <el-form-item label="密碼" prop="passwd">
          <el-input type="password" v-model="ruleForm.passwd" placeholder="請輸入密碼" autocomplete="off" show-password ></el-input>
        </el-form-item>
        <el-form-item label="確認密碼" prop="checkPass">
          <el-input type="password" v-model="ruleForm.checkPass" placeholder="請輸入確認密碼" autocomplete="off" show-password ></el-input>
        </el-form-item>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button @click="resetForm('ruleForm')">取 消</el-button>
        <el-button type="primary" @click="submitForm('ruleForm')">確 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script> import { mapMutations, mapGetters } from "vuex"; export default { data() { var validatePass = (rule, value, callback) => { if (value === "") { callback(new Error("請輸入密碼")); } else { if (this.ruleForm.checkPass !== "") { this.$refs.ruleForm.validateField("checkPass"); } callback(); } }; var validatePass2 = (rule, value, callback) => { if (value === "") { callback(new Error("請再次輸入密碼")); } else if (value !== this.ruleForm.passwd) { callback(new Error("兩次輸入密碼不一致!")); } else { callback(); } }; //這里存放數據
    return { dialogVisibleInfo: false, // 用戶信息
 dialogVisibleChangePwd: false, // 修改用戶密碼
 ruleForm: { passwd: "", checkPass: "", }, resetRules: { passwd: [{ validator: validatePass, trigger: "blur" }], checkPass: [{ validator: validatePass2, trigger: "blur" }], }, }; }, computed: { ...mapGetters(["getUserInfo"]), }, created() {}, methods: { ...mapMutations(["loginOut"]), handleCommand(command) { console.log(command); if (command === "baseInfo") { this.dialogVisibleInfo = true; } else if (command === "changePassword") { this.dialogVisibleChangePwd = true; } else if (command === "loginOut") { this.$confirm("您確定要退出嗎?", "退出管理平台", { confirmButtonText: "確定", cancelButtonText: "取消", }) .then(() => { this.loginOut(); this.$router.push(`/login?redirect=${this.$route.fullPath}`);
 }) .catch(() => {}); } }, submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { // 調用重置密碼的接口
 alert("重置密碼成功!"); this.dialogVisibleChangePwd = false; } else { // console.log("error submit!!");
          return false; } }); }, resetForm(formName) { this.dialogVisibleChangePwd = false; this.$refs[formName].resetFields(); }, }, }; </script>
<style lang='scss' scoped> //@import url(); 引入公共css類 .header-content-box { height: 60px; display: flex; justify-content: space-between; align-items: center; background: url("~@/assets/img/bg.png"); .logo { img { width: 40px; height: 40px;
    } } .top-info { display: flex; justify-content: center; align-items: center; .user-avatar { border-radius: 50%; img { width: 40px; height: 40px; border-radius: 50%;
      } } } } </style>

2.公共樣式

// reset.scss @import './transition.scss'; @import './public.scss'; @import './elementreset.scss'; *{ margin: 0; padding: 0; list-style: none;
}
/** 清除內外邊距 **/ body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 結構元素 */ dl, dt, dd, ul, ol, li,/* list elements 列表元素 */ pre, /* text formatting elements 文本格式元素 */ form, fieldset, legend, button, input, textarea, /* form elements 表單元素 */ th, td /* table elements 表格元素 */ { margin: 0; padding: 0;
} body,#app{ height: 100%; -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
} html{ height:100%;
} body{ height:100%; margin:0px; padding:0px;
} address, cite, dfn, em, var ,i{ font-style: normal; 
}

/* for ie6 */ fieldset, img { border: 0; } 
/* img :讓鏈接里的 img 無邊框 */ button, input, select, textarea { font-size: 100%;} 
/* 使得表單元素在 ie 下能繼承字體大小 *//* 注:optgroup 無法扶正 */ /** 重置表格元素 **/ table { border-collapse: collapse; border-spacing: 0; } label { font-weight: 700;
} html *{ font-size: 14px; box-sizing: border-box;
} *, *:before, *:after { box-sizing: inherit;
} // a:focus, // a:active { // outline: none; // } // a, // a:focus, // a:hover { // cursor: pointer; // text-decoration: none; // } div:focus { outline: none;
} .fr { float: right;
} .fl { float: left;
} .clearfix { &:after { visibility: hidden; display: block; font-size: 0; content: " "; clear: both; height: 0;
  } } .md{ display: inline-block; vertical-align: middle;
}


/*去掉type為number的箭頭*/ input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { -webkit-appearance: none;
} input[type="number"] { -moz-appearance: textfield;
} // Dialog 對話框居中顯示 .dialog-box-center{ text-align: center; &:after { content: ""; display: inline-block; height: 100%; width: 0; vertical-align: middle;
  } .el-dialog{ text-align: left; display: inline-block; margin: 0 !important; vertical-align: middle; min-width: 800px;
  } }
// transition.scss /*fade*/ .fade-enter-active, .fade-leave-active { transition: opacity 0.3s;
} .fade-enter, .fade-leave-active { opacity: 0;
}

/*fade-transform*/ .fade-transform-leave-active, .fade-transform-enter-active { transition: all .8s;
} .fade-transform-enter { opacity: 0; transform: translateX(-30px);
} .fade-transform-leave-to { opacity: 0; transform: translateX(30px);
}
// public.scss .pd10{ padding: 10px;
} .ptb10{ padding: 10px 0;
} .mt10{ margin-top: 10px;
} .md { display: inline-block; vertical-align: middle;
} // 進度條顏色 #nprogress .bar { background: red !important; //自定義顏色 } .flex-column { display: flex; justify-content: center; flex-direction: column;
}


/*滾動條樣式*/ .page-component__scroll { height: 100%; .el-scrollbar__wrap { overflow-x: auto;
  } } /*滾動條顏色*/ .scroll-bar-color { .el-scrollbar__thumb { background-color: rgba(118, 118, 119, 0.8);
  } }
// elementreset.scss // 分頁樣式 .el-pagination { text-align: right; margin-top: 10px;
} // element ui表頭換行 .el-table .cell { white-space: pre-line;
} // tooltip樣式更改 固定寬高換行顯示 .el-tooltip__popper { max-width: 400px; line-height: 180%;
} // 重置表單樣式 element ui 下拉、輸入、級聯、日期 .reset-form { .el-input, .el-select, .el-cascader, .el-range-editor { width: 100% !important;
  } .el-pagination { .el-input { width: 50px !important;
    } .el-select { .el-input { width: 100px !important;
      } width: 100px !important; } } } .el-table { .el-date-editor.el-input, .el-date-editor.el-input__inner { width: 100% !important;
  } } // to fixed https://github.com/ElemeFE/element/issues/2461 // Dialog內select tree等組件在點擊箭頭時有虛晃 .el-dialog { transform: none; left: 0; position: relative; margin: 0 auto;
} // 當前行選中顏色高亮 .el-table--striped .el-table__body tr.el-table__row--striped.current-row td, .el-table__body tr.current-row>td { background-color: #ffec8b;
} .el-loading-mask { background-color: rgba(0, 0, 0, .3);
} // 菜單樣式 /* 非折疊的豎直菜單處理方式和上方的水平菜單一樣,只不過需要將horizontal改為vertical Element-UI中,在沒有折疊的菜單中,無論是水平還是豎直菜單,子菜單是放在菜單欄所在的div中的, 只是將display屬性設置為了none。 而在折疊菜單中,雖然菜單項也是放在頁面上,但不在是放在菜單欄所在的div中,而是放在了頁面底部的單獨div中, 類屬性值是el-menu--popup,因為是單獨的div,所以在處理彈出菜單時就比較方便,直接處理el-submenu__title 和el-menu-item就可以,而不必區分是幾級菜單項(如果不同級別菜單項要分別處理,需要使用“>”等操作分別處理) */
/*處理豎直菜單收齊后的彈出菜單中的子菜單 */ .el-menu--vertical .el-menu--popup .el-submenu__title { height: 40px; line-height: 40px;
} .el-menu--vertical .el-menu--popup .el-menu-item { height: 40px; line-height: 40px;
} .el-menu--vertical .el-menu--popup .el-icon-arrow-right:before { color: #fff;
}

3.面包屑組件

<!-- * @Description: 全局面包屑組件 Breadcrumb/index.vue * @Version: 2.0 * @Autor: lhl * @Date: 2020-08-04 17:51:48 * @LastEditors: lhl * @LastEditTime: 2020-08-20 16:57:07 -->
<template>
  <div class="breadcrumb-box">
    <!-- separator-class="el-icon-arrow-right" 圖標分隔符 class -->
    <el-breadcrumb separator="/">
      <el-breadcrumb-item v-for="item in breadList" :to="{path: item.path }" :key="item.name"
      >{{item.meta.title}}</el-breadcrumb-item>
    </el-breadcrumb>
  </div>
</template>

<script> export default { created() { this.getBreadcrumb(); }, data() { return { breadList: [], }; }, watch: { $route() { this.getBreadcrumb(); }, }, methods: { getBreadcrumb() { let matched = this.$route.matched.filter((item) => item.name); // console.log(matched,'matched')
      this.breadList = matched; }, }, }; </script>
<style lang='scss' scoped> //@import url(); 引入公共css類 .breadcrumb-box{ padding: 10px 0; background: #fff; border-bottom: 1px solid #333;
}
</style>

  以上代碼本人項目實測!!!真實可靠,請勿隨意轉載~轉載請注明出處~~~謝謝合作!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM