网上开源的前端框架都写得很好,但是功能比较庞杂,于是着手搭建了一套自己的模板:
1.路由配置
首先我们要通过路由配置整体的页面结构(Home、About、Login)
代码语言:javascript复制Vue.use(VueRouter);
const routes = [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue'),
},
{
path: '/login',
name: 'Login',
component: () => import('../views/Login.vue'),
},
];
const router = new VueRouter({
routes,
});
同时我们需要对路由做一定的控制,比如未登录时只允许访问登录页,以及对页面跳转做一些样式上的优化。
代码语言:javascript复制router.beforeEach((to, from, next) => {
// 虚拟进度条,采用 NProgress 组件
NProgress.start();
let token = cookies.get('token');
// 如果没有 token 则跳到登录页
if (!token) {
if (to.fullPath !== '/login') {
next({ path: '/login' });
} else {
next();
}
return NProgress.done();
} else {
// 如果有 token 访问登录页则跳到首页;刷新时自动获取角色信息保存在 vuex 中
if (!store.state.role) {
const role = GET_ROLE();
store.commit('setState', role);
}
if (to.fullPath === '/login') {
next({ path: '/' });
} else {
next();
}
NProgress.done();
}
});
2.Vuex 全局状态管理
在路由配置中我们将角色信息存储在了 Vuex 中,Vuex 的配置如下:
代码语言:javascript复制import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
// 角色信息
role: '',
},
mutations: {
setState(state, role) {
state.role = role;
},
},
actions: {},
modules: {},
});
在页面中我们可以通过 mapState 访问 store 中的数据
代码语言:javascript复制import { mapState } from 'vuex';
computed: mapState(['role']),
<h3>我是:{{ role }}</h3>
3.组件库选用 Element-ui
组件库的选用纯看个人喜好
代码语言:javascript复制import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
4.自定义过滤器
自定义时间过滤器,在 main.js 全局注册时间过滤器,传入模板字符串解析为对应格式
代码语言:javascript复制// 定义时间过滤器
Vue.filter('dateFormat', function (originDate, pattern) {
// 根据给定的时间字符串,得到特定的时间
var dt = new Date(originDate);
var y = dt.getFullYear();
var m = (dt.getMonth() 1).toString().padStart(2, '0');
var d = dt.getDate().toString().padStart(2, '0');
var hh = dt.getHours().toString().padStart(2, '0');
var mm = dt.getMinutes().toString().padStart(2, '0');
var ss = dt.getSeconds().toString().padStart(2, '0');
return eval('`' pattern '`');
});
在页面中使用
代码语言:javascript复制<h3>当前时间:{{ time | dateFormat('${y}-${m}') }}</h3>
5.自定义指令
在 main.js 中注册全局指令
代码语言:javascript复制// 权限指令
Vue.directive('perm', {
// 绑定元素插入父节点时触发
inserted: (el, binding) => {
const hasPermission = (roleArr) => {
return roleArr.includes(store.state.role);
};
if (!hasPermission(binding.value)) {
// 如果不满足条件,则移除当前绑定节点
el.parentNode.removeChild(el);
}
},
});
在页面中使用,当角色为 admin 时,第一行不显示
代码语言:javascript复制<h3>学生可以看到: 我是<span v-perm="['student']">{{ role }}</span></h3>
<h3>大家可以看到: 我是<span v-perm="['student', 'admin']">{{ role }}</span></h3>
6. svg 封装
新建 SvgIcon.vue 文件
代码语言:javascript复制<template>
<svg :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
// svg图标名称
name: {
default: '',
},
// 自定义样式
className: {
type: String,
default: '',
},
},
computed: {
iconName() {
return `#icon-${this.name}`;
},
svgClass() {
return ['svg-icon', this.className ? this.className : ''];
},
},
};
</script>
<style scoped>
.svg-icon {
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
全局注册该组件
代码语言:javascript复制Vue.component('SvgIcon', SvgIcon);
这样我们就可以通过 SvgIcon 访问内存中存在的 svg 图标了,我们还需要做的就是将 svg 文件加载到内存中,
代码语言:javascript复制svg-sprite-loader 的官方解释是:一个用于创建 svg 雪碧图的 Webpack 加载器。这个加载器现在已经被 JetBrains 公司收录和维护了。通俗的讲:svg-sprite-loader 会把你引入的 svg 塞到一个个 symbol 中,合成一个大的 svg,最后将这个大的 svg 放入 body 中。symbol 的 id 如果不特别指定,就是你的文件名。
chainWebpack(config) {
// 配置路径别名
config.resolve.alias.set('components', resolve('src/components'));
// 已有配置排除掉svg
config.module.rule('svg').exclude.add(resolve('src/svg'));
// 添加svg-sprite-loader
config.module
.rule('icons')
.test(/.svg$/) // 设置test
.include.add(resolve('src/svg')) // 加入include
.end() // add完上下文进入数组,使用end回退
.use('svg-sprite-loader') // 添加loader
.loader('svg-sprite-loader') // 切换上下文到loader
.options({ symbolId: 'icon-[name]' })
.end();
},
// main.js -- 将 svg 文件引入内存中
import '@/svg/icons';
// icons.js
const req = require.context('../svg', false, /.svg$/);
req.keys().map(req);
这样就可以通过 name 属性访问 svg 了
代码语言:javascript复制<SvgIcon name="404" className="icon-style" />
7.axois 封装
axios 建议只做简单封装即可
代码语言:javascript复制import axios from 'axios';
import cookies from '@/utils/js-cookie';
// 创建请求实例
function createRequest() {
const request = axios.create({
baseURL: '/api',
timeout: 10000,
});
request.interceptors.request.use((config) => {
// 自动携带 token
const token = cookies.get('token');
config.headers.token = token;
return config;
});
return request;
}
export const request = createRequest();
// api.js
import { request } from './service';
export function GET_BOOK_LIST() {
return request({
url: '/catalog/book/',
method: 'get',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
params: {
type: 'book',
},
});
}