用Element-UI
作了兩個後臺,時間長了有點視覺勞累,挑來挑去,入選了某東的AT-UI
,搭建了一個雛形的後臺骨架,下面記錄一下使用方法(此時應附地址:官網傳送門)。javascript
本人是在vue2.0
的基礎上搭建,因此,謹記:先搭建好初步的項目文件,再來看下面的介紹。css
npm install at-ui
npm install at-ui-style
複製代碼
是的,它須要安裝兩個,而Element
只須要安裝一個,AT-UI
的css依賴文件也須要安裝, 而後在main.js
中引入就能夠了。html
import AtComponents from 'at-ui'
import 'at-ui-style' // 引入組件樣式
Vue.use(AtComponents)
Vue.config.productionTip = false
複製代碼
它封裝的組件,嵌套不是不少,有的也是直接在原dom元素上直接添加class的方式,因此從控制檯也不難找到其樣式的。前端
因爲AT-UI只是基本封裝,好比,日期選擇器datePicker、樹形組件tree等就沒有,因此有的控件就須要自行安裝,推薦一個vue組件網站:vueExamples。搭建時所需插件及使用方法,會在後面寫到。vue
頁面文件建好,本人習慣以下圖:java
view
目錄以文件夾分類svg
目錄放入svg圖標,圖標去阿里矢量庫
、fontawesome
等網站找就行了。mock
,在static
目錄下新建一個data.js
,把json數據扔進去就好,記得export
出來哦。npm i vue-svg-icon -D
複製代碼
在main.js
中引入vue-svg-icon
。jquery
import Icon from 'vue-svg-icon/Icon.vue';
Vue.component('icon', Icon);
複製代碼
不用管爲何有個Icon.vue路徑
,插件封裝的時候,經過它導出的。 而後就是目錄圖中的svg文件夾了,注意它的位置,和assets
並列,新建一個search.svg
, 放入找好的svg
代碼:webpack
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" id="icon-search" width="100%" height="100%"><path d="M124.884 109.812L94.256 79.166c-.357-.357-.757-.629-1.129-.914a50.366 50.366 0 0 0 8.186-27.59C101.327 22.689 78.656 0 50.67 0 22.685 0 0 22.688 0 50.663c0 27.989 22.685 50.663 50.656 50.663 10.186 0 19.643-3.03 27.6-8.201.286.385.557.771.9 1.114l30.628 30.632a10.633 10.633 0 0 0 7.543 3.129c2.728 0 5.457-1.043 7.543-3.115 4.171-4.157 4.171-10.915.014-15.073M50.671 85.338C31.557 85.338 16 69.78 16 50.663c0-19.102 15.557-34.661 34.67-34.661 19.115 0 34.657 15.559 34.657 34.675 0 19.102-15.557 34.661-34.656 34.661"></path></svg>
複製代碼
而後在使用的地方直接用就行了。git
<icon name="search" scale="18"></icon>
複製代碼
從理論上講,vue框架理應不須要jquery的,可是爲了處理某些特殊的地方,仍是引一下吧(除非確實不須要)。github
cnpm install jquery -S
複製代碼
main.js
import $ from 'jquery'
複製代碼
webpack.base.conf.js
var webpack = require('webpack') //最上面並列添加
module.exports = {
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'jquery':'jquery' //添加該項
}
},
plugins:[ //添加一個plugin是webpack.ProvidePlugin,寫到resolve並列的位置
new webpack.ProvidePlugin({
$: 'jquery',
jquery: 'jquery'
})
],
}
複製代碼
重啓以後,使用方法和原jquery同樣。
npm i less less-loader --save
npm i sass-resources-loader
複製代碼
//build/utils.js
function lessResourceLoader() { // 增長全局使用less函數
var loaders = [
cssLoader,
'less-loader',
{
loader: 'sass-resources-loader',
options: {
resources: [
path.resolve(__dirname, '../src/assets/css/common.less'), //定義全局變量的文件路徑
]
}
}
];
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
return {
css: generateLoaders(),
postcss: generateLoaders(),
// less: generateLoaders('less'),//原配置
less: lessResourceLoader(), //更改後的配置
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
複製代碼
注意:lessResourceLoader()
要和generateLoaders()
同級!
而後就能夠在src/assets/css/common.less
文件裏寫全局less了。
npm install vue-datepicker-local
複製代碼
<template>
<vue-datepicker-local v-model="time" />
</template>
<script> import VueDatepickerLocal from 'vue-datepicker-local' export default { components: { VueDatepickerLocal }, data () { return { time: new Date() } } } </script>
複製代碼
具體使用查看詳細文檔:github傳送門
先給一個默認的路由配置:
import Vue from 'vue'
import Router from 'vue-router'
import login from '@/view/login/login.vue';
import notFound from '@/view/404/404.vue';
import layout from '@/view/layout/layout.vue';
Vue.use(Router)
const router = new Router({
routes: [{
path: '/login',
name: '登陸',
component: login,
},{
path: '/',
name: '',
component: layout,
children:[{
path:'404',
name:'404',
component:notFound
}]
}, {
path: '*',
redirect: '/404'
}]
})
export default router;
複製代碼
因爲是使用動態路由,因此就須要動態引入的寫法:
src/components/
新建一個leftSlider.vuerouter.js
保持一致,也是下面的格式:{
path: '/',
name: '',
component: layout,
children:[{
path:跳轉路徑,
name:路由名稱,
component:組件
}]
}
複製代碼
因此,模擬一個json數據使用就好,後期換成接口讀取就好了。
左側菜單封裝以下:
<template>
<at-menu :activeName="$route.name" inline-collapsed router theme="dark">
<template v-for="(item,index) in routeList">
<!--有子路由-->
<at-submenu v-if="item.children.length>1" :key="index" >
<template slot="title">
<i class="icon icon-life-buoy"></i>
{{item.name}}
</template>
<at-menu-item v-for="(it,inde) in item.children" :key="inde" :to="it.path" >
{{it.name}}
</at-menu-item>
</at-submenu>
<!--無子路由-->
<at-menu-item :to="item.children[0].path" v-else :key="index">
<i class="icon icon-life-buoy"></i>
{{item.children[0].name}}
</at-menu-item>
</template>
</at-menu>
</template>
<script> export default { computed: { routeList() { return this.$store.state.global.routes }, }, mounted(){ this.openedSubmenu() }, watch: { '$route' (to, from) { this.openedSubmenu() } }, methods:{ openedSubmenu(){ let list = this.$store.state.global.routes; for(var key in list){ for(var jey in list[key].children){ if(list[key].children[jey].name == this.$route.name){ $(".at-menu.at-menu--dark.at-menu--inline>li:eq("+key+")") .addClass('at-menu__submenu--active at-menu__submenu--opened') .children('ul').show(); $(".at-menu.at-menu--dark.at-menu--inline>li:eq("+key+")").siblings() .removeClass('at-menu__submenu--active at-menu__submenu--opened') .children('ul').hide(); return; } } } }, } } </script>
<style lang="less" scoped> .at-menu.at-menu--dark.at-menu--inline { width: 240px; position: fixed; height: 100%; transition: width .28s; top: 0; bottom: 0; left: 0; overflow: hidden; } </style>
複製代碼
這邊不想用jquery的,可是AT-UI
有一個坑,就是opened
屬性不能夠動態展開收起,沒辦法,想要這個效果,因此用了jquery控制它的類名模擬這個效果。
注意一點,路由引入只是數據引入,然而組件是須要引入文件而不是單純的數據的, 因此:src/utils
新建lazyload.js
和leftSliderRoute.js
。
//lazyload.js
export default (folder,name) => () => import(`@/view/${folder}/${name}.vue`)
//leftSliderRoute.js
import lazyload from './lazyload.js';
export default (routes, data) => {
generaMenu(routes, data)
}
function generaMenu(routers, data) {
if (data) {
data.forEach((item) => {
let menu = Object.assign({}, item);
let folder = componentFromFolder(menu.component);
menu.component = lazyload(folder, menu.component)
if (item.children) {
menu.children = []
generaMenu(menu.children, item.children)
}
routers.push(menu)
})
}
}
function componentFromFolder(val) {
switch (val) {
case 'agentList':
case 'agency':
case 'agency2':
case 'agency3':
return 'agencyManage';
case 'agentApply':
case 'customList':
return 'customManage';
case 'financeOverview':
case 'withdrawApply':
case 'withdrawCancel':
case 'withdrawSuccess':
return 'financeManage';
case 'home':
return 'home';
case 'layout':
return 'layout'
}
}
複製代碼
經過文件匹配文件夾,而後import
進來組件就好。記得在登陸的時候調用一下:
import leftSliderRoute from "@/utils/leftSliderRoute.js";
var rou = [];
export default {
data() {
return {
username: '',
password: '',
}
},
methods: {
login() {
if (!this.username) {
this.$Message.error("請輸入帳號");
return;
}
if (!this.password) {
this.$Message.error("請輸入密碼");
return;
}
window.sessionStorage.setItem('routeList', JSON.stringify(routes));
this.$store.commit('addRouteList',routes);//寫到vuex裏
leftSliderRoute(rou,routes);
this.$router.addRoutes(rou);
this.$router.push('/home');
this.$Message.success('登陸成功');
}
}
}
複製代碼
而後須要注意一點,路由是在登陸以後從vuex裏拿的,可是用戶刷新頁面,不可能再讀取接口而後再塞進vuex裏,因此得存到緩存中,防止用戶刷新,改造main.js
:
import store from './store';
import leftSliderRoute from './utils/leftSliderRoute.js';
let routeList = JSON.parse(window.sessionStorage.getItem('routeList'));
if (routeList) {
//這裏是防止用戶手動刷新頁面,整個app要從新加載,動態新增的路由,會消失,因此咱們從新add一次
let routes = [];
leftSliderRoute(routes, routeList);
router.addRoutes(routes);
store.commit('addRouteList', routes);
} else {
router.push('/login');
}
複製代碼
至此,動態引入路由就完成了。
其實這個東西仍是依賴路由那個data,由於要讀取children
,仍是內部的,要麼改造數據,要麼就老老實實寫:
//main.js
router.beforeEach((to, from, next) => {
//麪包屑導航開始
let arr = [{
name: '首頁',
path: '/home'
}];
to.matched.map(item => {
item.path != '/home' && item.path && arr.push({
name: item.name,
path: item.path
})
})
store.commit('setBread', arr) //寫進vuex
next()
//導航結束
})
複製代碼
而後使用就行了。
<at-breadcrumb>
<at-breadcrumb-item :to="index == breadList.length-1 ?'':item.path" v-for="(item,index) in breadList" :key="index">{{item.name}}</at-breadcrumb-item>
</at-breadcrumb>
複製代碼
不少時候框架內部的樣式不符合使用,因此須要這樣:
.operate {
min-width: 100px;
display: flex;
align-items: center;
/deep/ input {
font-size: 13px;
border: none;
border-bottom: 1px solid #d9d9d9;
border-radius: 0;
margin: 0 8px;
}
}
複製代碼
使用/deep/
能夠修改組件自帶樣式,可是必定要上一層必定要有class
。
在有table
的組件裏,查詢是必不可少的,常常會有清空查詢條件的操做,有兩個方法:
JSON.parse(JSON.stringify(data))
的格式Object.assign({},data)
的格式兩個都是經過深拷貝,在created
的時候賦值一個默認數據,做爲備用,在清空的時候賦值就行了。
要注意:每次賦值都應該是深拷貝。
<template>
<div class="withdrawApply">
<div class="searchForm">
<form class="row at-row" ref="searchForm">
<at-select v-model="form.select" class="col-md-2" size="large" clearable placeholder="地區">
<at-option value="1">深圳</at-option>
</at-select>
<at-input class="col-md-3" v-model="form.keyword" placeholder="關鍵字" ></at-input>
<vue-datepicker-local class="col-md-3" placeholder="開始日期" v-model="form.beginTime" clearable format="YYYY-MM-DD HH:mm:ss"/>
<vue-datepicker-local class="col-md-3" placeholder="結束日期" v-model="form.endTime" clearable format="YYYY-MM-DD HH:mm:ss"/>
<at-button class="col-md-1" type="primary" @click="$Message('查詢')">查詢</at-button>
<at-button class="col-md-1" type="warning" @click="clearForm">清空</at-button>
</form>
</div>
<at-table :columns="[{title:'id',key:'id'},{title:'提現金額',key:'a'},{title:'申請時間',key:'b'},{title:'機構名稱',key:'c'},{title:'申請人',key:'d'}, {title:'銀行卡號',key:'e'},{title:'分行',key:'f'}, {title:'狀態', render:(h, params) => { return h('span',{},filterState(params.item)) }}, {title:'操做', render: (h, params) => { return h('div', [ h('AtButton', { props: { size: 'smaller', type:'error' }, style, on: { click: this.refuse } }, '拒絕'), h('AtButton', { props, style, on: { click: this.checkPay } }, '線下打款') ]) }}]" :data="data" border pagination :page-size="8"></at-table>
</div>
</template>
<script> import tableData from '../../../static/tableData.js'; //表格數據存放 import VueDatepickerLocal from 'vue-datepicker-local' import {mapState} from 'vuex'; export default { components:{ VueDatepickerLocal }, data() { return { data:tableData, defaultForm:null,//用來保留空表單 form:{ select:'', keyword:'', begTime:'', endTime:'' }, } }, computed:{ //寫了一個默認屬性配置,懶得一次一次寫,就扔vuex了 ...mapState({ props:state=>state.table.props, style:state=>state.table.style }) }, created(){ //賦值默認 this.defaultForm = Object.assign({},this.form); }, methods: { filterState(val){ //類型變換使用 return val ? 'return 2':'return 1' }, clearForm(){ this.form = Object.assign({},this.defaultForm); }, refuse(){ this.$Modal.confirm({ title: '提示', content: '是否拒絕?', cancelText:'取消', okText:'肯定', }).then(() => { this.$Message.success('拒絕成功') }).catch(() => { }) }, checkPay(){ this.$Modal.confirm({ title: '提示', content: '您確認審覈打款麼', cancelText:'取消', okText:'肯定', }).then(() => { this.$Message.success('打款成功') }).catch(() => { }) } } } </script>
複製代碼
放出來一個組件,應該沒什麼問題了。
layout
組件吧:<!--嗯,承重牆就長這個樣子。-->
<template>
<div class="layout">
<leftSlider></leftSlider>
<div class="layout-container">
<headerTop></headerTop>
<router-view class="main"></router-view>
</div>
</div>
</template>
<script> import headerTop from '@/components/header.vue'; import leftSlider from '@/components/leftSlider.vue'; export default { components: { leftSlider, headerTop, } } </script>
複製代碼
function fullScreen() {
console.log(123)
var el = document.documentElement;
var rfs = el.requestFullScreen || el.webkitRequestFullScreen ||
el.mozRequestFullScreen || el.msRequestFullScreen;
if (typeof rfs != "undefined" && rfs) {
rfs.call(el);
} else if (typeof window.ActiveXObject != "undefined") {
//for IE,這裏其實就是模擬了按下鍵盤的F11,使瀏覽器全屏
var wscript = new ActiveXObject("WScript.Shell");
if (wscript != null) {
wscript.SendKeys("{F11}");
}
}
}
function exitFullScreen() {
console.log(456)
var el = document;
var cfs = el.cancelFullScreen || el.webkitCancelFullScreen ||
el.mozCancelFullScreen || el.exitFullScreen;
if (typeof cfs != "undefined" && cfs) {
cfs.call(el);
} else if (typeof window.ActiveXObject != "undefined") {
//for IE,這裏和fullScreen相同,模擬按下F11鍵退出全屏
var wscript = new ActiveXObject("WScript.Shell");
if (wscript != null) {
wscript.SendKeys("{F11}");
}
}
}
複製代碼
Failed to mount component: template or render function not defined.
不妨能夠看看報錯指南1.經常使用過濾,用來前端搜索
searchInputEvent() {
let result = this.searchInput ?
this.querySearchArr.filter(item => {
return (item.name.toLowerCase().indexOf(this.searchInput.toLowerCase()) > -1)
}) : this.searchData;
this.searchData = result;
}
複製代碼
差很少一個後臺也就這麼多東西了,其餘的就是按業務需求來改。17年出的框架,可是18年也就更新了一次……🤨,整體感受AT-UI
東西很少,不過體驗還不錯。