一个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>