做完這個demo后,我體會到,Vue組件化,webpack, Vue-router等,并不是很難學習,你需要的只是拿起斧頭的勇氣 在做demo的過程中,我遇到一個問題,就是vue-router懶加載一直實現(xiàn)不了,糾結了半天。后來回到原點,去vue-route官網(wǎng)看文檔,發(fā)現(xiàn)是因為syntax-dynamic-import插件沒有安裝 。
所以說:你以為的bug, 實際上是你沒看透文檔
初次學習這個教程,你不需要有任何擔憂某些東西不會,你也不需要寫任何代碼。因為基本上所有代碼都是從element官網(wǎng)上拷貝的,你所做的只是把他們組裝在一起罷了。
在線預覽 倉庫地址:https://github.com/wangduandu...
效果圖:
 使用到的技術:
- Vue
- Vue-router
- Element-ui
- webpack
- Normalize.css
- vue-awesome
- babel
1 vue-cli 安裝模板
? vue-el-dashboard git:(master) vue init webpack
? Generate project in current directory? Yes
? Project name vue-el-dashboard
? Project description A Vue.js project
? Author wangdd <wangdd@welljoint.com>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Setup unit tests No
? Setup e2e tests with Nightwatch? No
vue-cli · Generated "vue-el-dashboard".
To get started:
npm install
npm run dev
Documentation can be found at https://vuejs-templates./webpack
2 安裝依賴并運行
? vue-el-dashboard git:(master) ? cnpm i
? Installed 44 packages
? Linked 680 latest versions
? npm run dev
瀏覽器打開如下頁面 :

3 安裝初始化頁面布局
安裝并使用Element UI
cnpm i element-ui -S
修改 /src/main.js 為:
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import App from './App'
Vue.config.productionTip = false
Vue.use(ElementUI)
/* eslint-disable no-new */
new Vue({
el: '#app',
template: '<App/>',
components: { App }
})
我需要的布局是這種:

在 Element 上復制對應的代碼, 并粘貼到 /src/App.vue文件中:
<template>
<div id="app">
<el-container>
<el-header>Header</el-header>
<el-container>
<el-aside width="200px">Aside</el-aside>
<el-main>Main</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style>
</style>
不出意外的話,你可以在瀏覽器上看到如下布局:

現(xiàn)在,布局就這么成了。
4 安裝側邊菜單欄
我需要側邊欄是下圖右邊的自定義顏色的那種菜單

在components文件夾下新建NavMenu.vue
<template>
<el-row class="tac">
<el-col :span="12">
<h5>默認顏色</h5>
<el-menu default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose">
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span>導航一</span>
</template>
<el-menu-item-group>
<template slot="title">分組一</template>
<el-menu-item index="1-1">選項1</el-menu-item>
<el-menu-item index="1-2">選項2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分組2">
<el-menu-item index="1-3">選項3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">選項4</template>
<el-menu-item index="1-4-1">選項1</el-menu-item>
</el-submenu>
</el-submenu>
<el-menu-item index="2">
<i class="el-icon-menu"></i>
<span slot="title">導航二</span>
</el-menu-item>
<el-menu-item index="3">
<i class="el-icon-setting"></i>
<span slot="title">導航三</span>
</el-menu-item>
</el-menu>
</el-col>
<el-col :span="12">
<h5>自定義顏色</h5>
<el-menu default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b">
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span>導航一</span>
</template>
<el-menu-item-group>
<template slot="title">分組一</template>
<el-menu-item index="1-1">選項1</el-menu-item>
<el-menu-item index="1-2">選項2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分組2">
<el-menu-item index="1-3">選項3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">選項4</template>
<el-menu-item index="1-4-1">選項1</el-menu-item>
</el-submenu>
</el-submenu>
<el-menu-item index="2">
<i class="el-icon-menu"></i>
<span slot="title">導航二</span>
</el-menu-item>
<el-menu-item index="3">
<i class="el-icon-setting"></i>
<span slot="title">導航三</span>
</el-menu-item>
</el-menu>
</el-col>
</el-row>
</template>
<script>
export default {
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
}
}
}
</script>
然后將NavMenu組件導入到App.vue中, 修改App.vue:
<template>
<div id="app">
<el-container>
<el-header>Header</el-header>
<el-container>
<el-aside width="200px">
<navmenu></navmenu>
</el-aside>
<el-main>Main</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import NavMenu from '@/components/NavMenu'
export default {
name: 'app',
components: {
'navmenu': NavMenu
}
}
</script>
<style>
</style>
這里要解釋一下這條語句, 該語句中的@ , 符號是什么意思?
import NavMenu from '@/components/NavMenu'
在build/webpack.base.conf.js中有如下代碼, alias就是起別名,@符號就是代表src路徑, 所以@/components/NavMenu就是src/components/NavMenu 。 這樣webpack就知道如何引入文件了。這樣做的好處是不必到處去寫src 了。
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
現(xiàn)在打開瀏覽器,應該可以看到如下界面:

可以看到菜單已經引入進來了,但是是兩個菜單,下面我們需要修改一下,只要右邊的菜單,并刪除一些多余的元素。 修改NavMenu.vue文件。
<template>
<el-row class="tac">
<el-col :span="24">
<el-menu default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
unique-opened
router
background-color="#545c64" text-color="#fff" active-text-color="#ffd04b">
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span>導航一</span>
</template>
<el-menu-item-group>
<el-menu-item index="1-1">選項1</el-menu-item>
<el-menu-item index="1-2">選項2</el-menu-item>
<el-menu-item index="1-3">選項3</el-menu-item>
<el-menu-item index="1-4">選項4</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-location"></i>
<span>導航二</span>
</template>
<el-menu-item-group>
<el-menu-item index="2-1">選項1</el-menu-item>
<el-menu-item index="2-2">選項2</el-menu-item>
<el-menu-item index="2-3">選項3</el-menu-item>
<el-menu-item index="2-4">選項4</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-col>
</el-row>
</template>
<script>
export default {
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath)
},
handleClose(key, keyPath) {
console.log(key, keyPath)
}
}
}
</script>
現(xiàn)在打開瀏覽器看看:

點擊展開菜單看看:

5 側邊菜單欄進階
我們需要的功能:
- 每次只能展開一個一級菜單
- 每次點擊一個二級菜單可以自動改變路由,跳轉到對應的組件
- 由于菜單在路由中也會使用,所以最好抽象出來,做成一個配置文件
第1點和第二點比較好搞,Element上已經有配置文檔:
- unique-opened: 是否只保持一個子菜單的展開
- router: 是否使用 vue-router 的模式,啟用該模式會在激活導航時以 index 作為 path 進行路由跳轉

修改NavMenu.vue
<template>
<el-row class="tac">
<el-col :span="24">
<el-menu default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
unique-opened
router
background-color="#545c64" text-color="#fff" active-text-color="#ffd04b">
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span>導航一</span>
</template>
<el-menu-item-group>
<el-menu-item index="1-1">選項1</el-menu-item>
<el-menu-item index="1-2">選項2</el-menu-item>
<el-menu-item index="1-3">選項3</el-menu-item>
<el-menu-item index="1-4">選項4</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-location"></i>
<span>導航二</span>
</template>
<el-menu-item-group>
<el-menu-item index="2-1">選項1</el-menu-item>
<el-menu-item index="2-2">選項2</el-menu-item>
<el-menu-item index="2-3">選項3</el-menu-item>
<el-menu-item index="2-4">選項4</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-col>
</el-row>
</template>
<script>
export default {
methods: {
handleOpen (key, keyPath) {
console.log(key, keyPath)
},
handleClose (key, keyPath) {
console.log(key, keyPath)
}
}
}
</script>
打開瀏覽器,點擊一個二級菜單看看,你會發(fā)現(xiàn),效果并不像預期那樣,而且控制臺還向你扔出一個bug:

添加一個暫時的路由: 修改main.js
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import App from './App'
import router from './router'
Vue.config.productionTip = false
Vue.use(ElementUI)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
打開瀏覽器,點擊一個二級菜單,這時候沒有報錯,瀏覽器的路徑也變了, 變成http://localhost:8080/#/1-3

每次增加一個菜單都要寫點html是不能忍的,能用js的,就別用html 。
在src目錄下創(chuàng)建一個config目錄,目錄下創(chuàng)建一個menu-config.js 文件: 外層的數(shù)組代表一級菜單,內層sub數(shù)組代表二級菜單。
module.exports = [{
name: '基礎',
id: 'basic',
sub: [{
name: 'Layout 布局',
componentName: 'BasicLayout'
}, {
name: 'Container 布局容器',
componentName: 'BasicContainer'
}]
}, {
name: 'Form',
id: 'form',
sub: [{
name: 'Radio 單選框',
componentName: 'FormRadio'
}, {
name: 'Checkbox 多選框',
componentName: 'FormCheckbox'
}]
}]
在NavMenu.vue中引入這個文件,并使用v-for 循環(huán)去渲染這個菜單:
<template>
<el-row class="tac">
<el-col :span="24">
<el-menu
class="el-menu-vertical-demo"
router
unique-opened
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<el-submenu v-for="item in menu" :index="item.id" :key="item.id">
<template slot="title">
<span v-text="item.name"></span>
</template>
<el-menu-item-group class="over-hide" v-for="sub in item.sub" :key="sub.componentName">
<el-menu-item :index="sub.componentName" v-text="sub.name">
</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-col>
</el-row>
</template>
<style scoped>
.over-hide{
overflow: hidden;
}
</style>
<script>
import menu from '@/config/menu-config'
export default {
data () {
return {
menu: menu
}
},
methods: {
handleOpen (key, keyPath) {
console.log(key, keyPath)
},
handleClose (key, keyPath) {
console.log(key, keyPath)
}
}
}
</script>
這里要說明一下,我給二級菜單加上了over-hide 類,二級菜單在展開時,有點溢出父元素了。 打開瀏覽器看看, 這時候菜單已經是根據(jù)配置文件渲染的了。

6 先加個頭部吧,禿頂太丑了
在componets文件夾下創(chuàng)建一個Header.vue, 并在App.vue中引入,
Header.vue
<template>
<el-row>
<el-col :span="24"
<div class="head-wrap">Element</div>
</el-col>
</el-row>
</template>
<style scoped>
.head-wrap{
}
</style>
App.vue
<template>
<div id="app">
<el-container>
<el-header class="header">
<vheader />
</el-header>
<el-container>
<el-aside width="200px">
<navmenu></navmenu>
</el-aside>
<el-main>Main
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import NavMenu from '@/components/NavMenu'
import Header from '@/components/Header'
export default {
name: 'app',
components: {
'navmenu': NavMenu,
'vheader': Header
}
}
</script>
<style>
.header {
background-color: #409EFF;
color: #fff;
line-height: 60px;
}
</style>
這時候打開瀏覽器看看, 是不是已經好看一點了。但是body有邊框,不好看啊!

再次美化
安裝Normalize.css, vue-awesome
cnpm i normalize.css -D
cnpm i vue-awesome -D
這里主要貼一下main.js的改動,其他的代碼就不貼了:
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import NormailizeCss from 'normalize.css'
import 'vue-awesome/icons'
import Icon from 'vue-awesome/components/Icon'
import App from './App'
import router from './router'
Vue.config.productionTip = false
Vue.use(ElementUI)
Vue.component('icon', Icon)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
看下效果, 圖標什么的都有了。

7 組件路由與懶加載
在components新增四個文件:
BasicContainer.vue
<template>
<div>
這是:Container 布局容器
</div>
</template>
BasicLayout.vue
<template>
<div>
這是:Layout 布局
</div>
</template>
FormCheckbox.vue
<template>
<div>
這是:Checkbox 多選框
</div>
</template>
FormRadio.vue
<template>
<div>
這是:Radio 單選框
</div>
</template>
修改route/index.js文件, 關于路由和懶加載就不在此贅述,任何文檔都沒有官方文檔說的好。
注意:如果您使用的是 Babel,你將需要添加 syntax-dynamic-import 插件,才能使 Babel 可以正確地解析語法。 也就是說,你要先安裝syntax-dynamic-import , 不然懶加載根本不行。
cnpm install --save-dev babel-plugin-syntax-dynamic-import
import Vue from 'vue'
import Router from 'vue-router'
import menus from '@/config/menu-config'
Vue.use(Router)
var routes = []
menus.forEach((item) => {
item.sub.forEach((sub) => {
routes.push({
path: `/${sub.componentName}`,
name: sub.componentName,
component: () => import(`@/components/${sub.componentName}`)
})
})
})
export default new Router({ routes })
另外App.vue文件需要加上 router-view
<el-main>
<router-view></router-view>
</el-main>
看看效果:點擊菜單,路徑跳轉,并且每次都是單獨去加載路由的文件。

8 github 部署
如果你想在github上部署,那么你要修改config/index.js的以下代碼, 不然有些文件因為路徑問題可能會找不到。
build: {
// Template for index.html
index: path.resolve(__dirname, '../docs/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../docs'),
assetsSubDirectory: 'static',
assetsPublicPath: '/vue-el-dashboard/',
掃碼訂閱我的微信公眾號:洞香春天 。每天一篇技術短文,讓知識不再高冷。
|