一個vue項目
前言
- 基於vue-cli3
- 麻雀雖小,五臟六腑俱全
- Vue常用屬性與方法
- 集成vue-router、vuex、axios及element-ui等插件
- 自定義指令、全局過濾器
- 封裝全局使用.svg圖標的組件
- 源碼
預覽
封裝Icon組件
src/components/IconSvg.vue
<template>
<svg class="svg-icon" aria-hidden="true">
<use :xlink:href="iconName"></use>
</svg>
</template>
<script>
export default {
props: {
iconClass: {
type: String,
required: true
}
},
computed: {
iconName () {
return `#icon-${this.iconClass}`
}
}
}
</script>
<style lang="less" scoped>
.svg-icon {
width: 1em;
height: 1em;
fill: currentColor;
overflow: hidden;
vertical-align: -0.15em;
}
</style>
src/icons/index.js
import Vue from 'vue'
import IconSvg from '@/components/IconSvg'
const requireAll = requireContext => requireContext.keys().map(requireContext)
// 引入相對路徑svg文件夾下所有.svg文件
const req = require.context('./svg', false, /\.svg$/)
requireAll(req)
Vue.component('icon-svg', IconSvg)
在vue.config.js配置svg-sprite-loader
const path = require('path')
module.exports = {
chainWebpack: config => {
// svg-config
const svgRule = config.module.rule('svg')
svgRule.uses.clear()
svgRule.exclude.add(/node_modules/)
svgRule
.test(/\.svg$/)
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
// 修改images loader 添加svg處理
const imagesRule = config.module.rule('images')
imagesRule.exclude.add(path.resolve('src/icons')) // 必須
imagesRule
.test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
}
}
在main.js引入 import './icons'
使用組件
<icon-svg iconClass='edit'></icon-svg>
自定義指令
src/directive/waves/index.js
export default {
bind: (el, binding) => {
// 此處內容較多 詳情參見源碼
}
}
在main.js注冊所有自定義指令
import Vue from 'vue'
import directives from '../src/directive'
// 指令
for (const key of Object.keys(directives)) {
Vue.directive(key, directives[key])
}
定義全局過濾器
定義和注冊與自定義指令類似,詳情參見源碼
路由
import Vue from 'vue'
import Router from 'vue-router'
import NProgress from 'nprogress' // 頁面加載進度條
import 'nprogress/nprogress.css'
Vue.use(Router)
const constantRoutes = [
{
path: '/404',
component: () => import('@/views/ErrorPage')
},
{
path: '*',
redirect: '/404'
},
{
path: '/login',
name: '登錄',
component: () => import('@/views/Login')
},
{
path: '/',
name: '首頁',
icon: 'home',
component: () => import('@/views/Home')
}
]
export const asyncRoutes = [
...constantRoutes,
{
path: '/svgIcon',
name: 'svg圖標',
icon: '',
component: () => import('@/views/IconView')
},
{
path: '/computedAndWatch',
name: '計算與偵聽',
icon: '',
component: () => import('@/views/ComputedWatch')
},
{
path: '/directives',
name: '自定義指令',
icon: '',
component: () => import('@/views/MyDirective')
},
{
path: '/filters',
name: '過濾器',
icon: '',
component: () => import('@/views/MyFilter')
},
{
path: '/vuex',
name: 'Vuex',
icon: '',
component: () => import('@/views/VuexView')
}
]
const router = new Router({
routes: asyncRoutes
})
// 導航首位,可在此做路由權限過濾
router.beforeEach((to, form, next) => {
NProgress.start()
next()
})
router.afterEach(() => {
NProgress.done()
})
export default router
vuex基本結構
src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 1,
user: window.localStorage.getItem('user') || '',
token: window.localStorage.getItem('token') || ''
},
getters: {
// 類似computed屬性
double: state => {
return state.count * 2
},
isAuth: state => !!state.token
},
mutations: {
increment (state) {
state.count++
},
login (state, payload) {
const { userName, token } = payload
state.user = userName
state.token = token
window.localStorage.setItem('user', userName)
window.localStorage.setItem('token', token)
},
logout (state) {
state.user = ''
state.token = ''
window.localStorage.removeItem('user')
window.localStorage.removeItem('token')
}
},
actions: {
// 異步函數
login ({ commit }, payload) {
commit('login', payload)
},
logout ({ commit }) {
commit('logout')
}
}
})
export default store
組建內使用store
// 使用輔助函數
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
computed: {
...mapGetters([
'isAuth'
])
},
data () {
},
methods: {
...mapActions([
'login',
'logout'
]),
handleLogin () {
this.login({...loginMsg})
},
handleLogout () {
this.logout()
}
}
}
</script>