循序渐进VUE+Element 前端应用开发(1)— 开发环境的准备工作
1、前后端的分离和Web API 优先路线设计
引入了前后端分离的VUE + Element 的开发方式,那么前后端的边界则非常清晰,前端可以在通过网络获取对应的JSON就可以构建前端的应用了。 在前端处理中,主要就是利用Vuex模式中的Store对象里实现对Action和Mutation的请求处理,获取数据后,实现对State状态中的数据进行更新。如果仅仅是当前页面的数据处理,甚至可以不需要存储State信息,直接获取到返回的数据,直接更新到界面视图上即可。
vuex 核心 & 数据响应式原理
vuex 使用总结(详解)
vue的双向绑定原理及实现
2、Axios网络请求处理
在我们进一步处理前,我们需要知道Vuex里面的一些对象概念和他们之间的关系。
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。关于Vuex的相关State、Getter、Mutation、Action、Module之间的差异和联系,详细可以参考下:https://vuex.vuejs.org/zh/
在开始发起网络请求之前,我们需要了解axios 这个东西,axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范。在这里我们只需要知道它是非常强大的网络请求处理库,且得到广泛应用即可,列举几个代码案例进行了解。
POST请求
循序渐进VUE+Element 前端应用开发(3)— 动态菜单和路由的关联处理
1、菜单和路由的处理过程
由于Vue前端还需要引入路由这个概念: 1.路由是我们前端可以访问到的对应路径集合, 2.路由定义了常规菜单说没有的很多复杂信息,但是往往这些是我们不能随意修改的,因此我们做法是 1.以本地配置好的路由列表为基准,而菜单我们采用在后台配置方式, 2.前端通过接口动态获取菜单列表,通过菜单的名称和路由名称的对应关系,我们以菜单集合为对照, 3.然后过滤本地所有静态路由的列表, 4.然后获得用户可以访问的路由列表, 5.设置动态路由给前端,从而实现了界面根据用户角色/权限的不同,而变化用户的菜单界面和可访问路由集合。
菜单路由处理的大概的操作过程如下所示
前端界面的动态菜单、本地路由、菜单导航和可访问路由的几个概念如下所示。
在前端界面处理中,我们通过Element界面组件的方式展示动态菜单信息,并结合菜单和路由的关系,实现菜单跳转到对应视图的处理过程。
2、菜单和路由列表
根据前面的介绍,我们定义了一些从服务端返回的动态菜单信息,这些菜单信息是一个JSON对象集合,如下界面所示。 而Vue前端需要初始化定义前端页面的所有路由,这些包括路由页面的Layout等信息。
我们可以在一个JS文件里面定义好对应前端所有的路由信息,如下所示
// 定义本系统的所有路由,具体路由呈现经过菜单数据过滤
export const asyncRoutes = {
'dashboard': {
path: '/dashboard',
component: Layout,
children: [{
path: 'dashboard',
name: 'dashboard',
component: () => import('@/views/dashboard/index')
}]
},
'product': {
path: '/product',
component: Layout,
children: [{
path: '/product',
name: 'product',
component: () => import('@/views/Product/index')
}]
},
.............................. //省略部分
'icon': {
path: '/icon',
component: Layout,
children: [{
path: '/icon',
name: 'icon',
component: () => import('@/views/icons/index')
}]
},
'external-link': {
path: 'http://www.iqidi.com',
name: 'external-link'
}
}
这里的路由不需要嵌套,因为菜单展示才需要定义嵌套关系。
另外,由于系统在未登录请求后端动态菜单前,我们系统也需要正常运行起来,那么就需要预设一些基础的路由信息,如登录界面、重定向页面、首页链接等这些路由信息,因此我们可以分开两个路由对象,用来分开管理这些信息。
对路由的管理,一个需要默认创建路由的处理、重置路由的处理,以及动态设置新的路由处理,我们封装几个函数来处理这些操作。
const createRouter = () => new Router({
// mode: 'history', // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
const router = createRouter()
// 重置路由
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
户在经过登录界面处理后,就会通过对应的Action获取动态路由信息(注意,这里是先获取动态菜单,然后过滤本地路由,即为动态路由信息),获得动态路由后,就设置前端所能访问的路由集合即可,如下代码所示。
有了这些新的路由允许,前端系统的菜单才能够正常运转起来,否则即使界面展示了菜单,也不能访问特定的视图页面而跳到了404页面,因为路由没有。
3、登录的过程处理
前面大概介绍了路由的处理过程,其实我们路由信息,应该需要从登录界面开始讲起。
以登录界面为例,在用户登录处理后,需要先验证用户的账号密码,成功后继续请求该用户对应的动态菜单集合,并通过路由切换到对应的页面或者首页。
在Store/Modules/user.js模块里面,定义了对应的登陆处理Action,如下所示
我们这里忽略用户登录的检验和处理token的过程,主要关注动态菜单请求并设置路由的过程。
在我们需要拦截路由到达前的处理中,我们定义对应的路由信息请求逻辑,如下所示。
router.beforeEach(async(to, from, next) => {
在处理菜单路由的对应模块里面,我们定义了一个状态用来承载这些重要信息,如下定义State所示。
const state = {
menuItems: [],
routes: [],
addRoutes: [],
asyncRoutes: asyncRoutes
}
// 定义了路由和菜单的Mutation
const mutations = {
SET_ROUTES: (state, routes) => {
// var list = convertRoute(routes)
routes.push({ path: '*', redirect: '/404', hidden: true }) // 此为默认错误路由
state.addRoutes = routes
state.routes = [].concat(routes)// constantRoutes.concat(routes)
},
SET_MENUS: (state, menus) => {
state.menuItems = menus
}
}
// 定义了生成动态路由的Action处理
const actions = {
generateRoutes({ commit }, roles) {
return new Promise(resolve => {
getMenus().then(res => {
const menus = res.data || [] // 统一通过接口获取菜单信息
const routes = []
menus.forEach(item => {
filterRoutes(routes, item)
})
console.log(routes)// 打印路由
commit('SET_ROUTES', routes)
commit('SET_MENUS', menus)
resolve(routes)
});
})
}
}
最后返回对应的JS定义模块类信息即可。
export default {
namespaced: true,
state,
mutations,
actions
}
在前端界面处理中,我们通过Element界面组件的方式展示动态菜单信息,并结合菜单和路由的关系,实现菜单跳转到对应视图的处理过程。
我们来看看界面生成的动态菜单效果。**
**
我们创建了一些操作数据的API类文件,每个API名称对应一个业务的集中处理,包括特定业务的列表请求、单个请求、增加、删除、修改等等都可以封装在一个API类里面。
然后在对应的业务API访问类,如product.js 里面定义我们的请求逻辑,主要就是利用简单封装axios的request辅助类来实现数据的请求。
下一步就是在src/views/product目录里面定义我们的视图文件,这个也就是页面文件,其中包含了常规VUE的几个部分,包括
其中在里面的是界面元素部分,可以添加我们相关的界面组件等内容,如element的界面组件在里面。 其中
其中
其中我们主要涉及到内容包括: data,用于定义整个页面的modal对象或属性, method,用于定义各种处理方法 computed,用于定义一些计算的树形 created,用于我们在元素创建,但是没有挂载的时候 mounted,完成页面挂载的时候