이 시리즈 기사는 단계별 튜토리얼이 아닙니다. 주로 핵심 아이디어를 소개하고 핵심 코드를 설명합니다. 친구들은 GitHub에서 전체 코드를 별표 표시하고 복제하여 공부할 수 있습니다. 그리고 원래는 프로젝트를 실행해서 친구들이 볼 수 있도록 온라인에 올릴 생각이었는데, 서버를 사기 전에 돈을 아끼기 위해 메모리가 512M에 불과했고, 두 개의 애플리케이션을 실행할 수 없었습니다(이미 V Tribe가 있습니다). 오픈 소스 프로젝트 실행 중)이므로 아래 스크린샷만 볼 수 있습니다. GitHub에 배포 튜토리얼이 있으므로 전체 효과를 확인할 수도 있습니다.
프로젝트 주소: https://github.com/lenve/vhr
이전 글에서는 기본적으로 서버 측 문제를 해결하고 프런트 엔드 요청을 캡슐화했습니다. 주로 로그인과 구성 요소의 동적 로딩에 대해 설명합니다.
이 기사는 이 시리즈의 다섯 번째 기사입니다. 이 기사를 더 잘 이해하려면 이전 기사를 먼저 읽어 보는 것이 좋습니다.
1 SpringBoot+Vue는 프런트엔드와 백엔드를 분리하고 Spring Security를 사용합니다. 권한 문제를 완벽하게 처리하기 위해 (1)
2.SpringBoot+Vue는 프런트엔드와 백엔드를 분리하고 SpringSecurity를 사용하여 권한 문제를 완벽하게 처리합니다. (2)
3.SpringSecurity의 비밀번호 솔팅 및 SpringBoot의 통합 예외 처리
4.axios 요청 캡슐화 통합 예외 처리
사용자가 성공적으로 로그인한 후에는 현재 사용자의 로그인 정보를 나중에 사용할 수 있도록 로컬에 저장해야 합니다. 구체적인 구현은 다음과 같습니다.
로그인 작업이 성공적으로 수행된 후 커밋 작업을 통해 데이터가 스토어에 제출됩니다.
<span style="font-size: 14px;">this.postRequest('/login', {<br> username: this.loginForm.username,<br> password: this.loginForm.password<br>}).then(resp=> {<br> if (resp && resp.status == 200) {<br> var data = resp.data;<br> _this.$store.commit('login', data.msg);<br> var path = _this.$route.query.redirect;<br> _this.$router.replace({path: path == '/' || path == undefined ? '/home' : path});<br> }<br>});<br></span>
스토어의 핵심 코드는 다음과 같습니다.
<span style="font-size: 14px;">export default new Vuex.Store({<br> state: {<br> user: {<br> name: window.localStorage.getItem('user' || '[]') == null ? '未登录' : JSON.parse(window.localStorage.getItem('user' || '[]')).name,<br> userface: window.localStorage.getItem('user' || '[]') == null ? '' : JSON.parse(window.localStorage.getItem('user' || '[]')).userface<br> }<br> },<br> mutations: {<br> login(state, user){<br> state.user = user;<br> window.localStorage.setItem('user', JSON.stringify(user));<br> },<br> logout(state){<br> window.localStorage.removeItem('user');<br> }<br> }<br>});<br></span>
문제를 줄이기 위해 사용자가 성공적으로 로그인한 후의 데이터는 localStorage에 저장됩니다(사용자가 로그인한 후 데이터 손실을 방지하기 위해). F5를 눌러 새로고침), 문자열 형식으로 저장한 다음 검색 시 json으로 변환합니다. 사용자가 로그아웃하면 localStorage의 데이터를 지웁니다.
권한 관리 모듈에서는 이것이 프런트 엔드의 핵심으로 간주됩니다.
사용자는 성공적으로 로그인한 후 홈 페이지에 들어가기 전에 서버에 요청을 보내 현재 메뉴 정보와 구성 요소 정보를 가져옵니다. 해당 리소스는 json 문자열을 반환합니다. 다음 형식:
<span style="font-size: 14px;">[<br> {<br> "id": 2,<br> "path": "/home",<br> "component": "Home",<br> "name": "员工资料",<br> "iconCls": "fa fa-user-circle-o",<br> "children": [<br> {<br> "id": null,<br> "path": "/emp/basic",<br> "component": "EmpBasic",<br> "name": "基本资料",<br> "iconCls": null,<br> "children": [],<br> "meta": {<br> "keepAlive": false,<br> "requireAuth": true<br> }<br> },<br> {<br> "id": null,<br> "path": "/emp/adv",<br> "component": "EmpAdv",<br> "name": "高级资料",<br> "iconCls": null,<br> "children": [],<br> "meta": {<br> "keepAlive": false,<br> "requireAuth": true<br> }<br> }<br> ],<br> "meta": {<br> "keepAlive": false,<br> "requireAuth": true<br> }<br> }<br>]<br></span>
이 문자열을 얻은 후 프런트 엔드는 두 가지 작업을 수행합니다. 1. 현재 경로에 json을 동적으로 추가합니다. 2. 데이터를 스토어에 저장한 다음 각 페이지는 데이터를 기반으로 메뉴를 렌더링합니다. 가게에서.
핵심 아이디어는 어렵지 않습니다. 구현 단계를 살펴보겠습니다.
이것은 매우 중요합니다.
왜 이렇게 어려운지 물어보는 친구들도 있는데, 로그인 성공 후 바로 요청하면 안되나요? 예, 로그인 성공 후 메뉴 리소스를 요청할 수 있습니다. 요청을 받은 후 다음 번 사용을 위해 스토어에 저장하지만, 사용자가 성공한 후 특정 하위 항목을 클릭하면 또 다른 문제가 발생합니다. 로그인 후 페이지에 진입 후 F5를 눌러 새로고침을 하면 이때는 GG인데, F5를 새로고침하면 스토어의 데이터가 사라지고, 로그인시 메뉴 리소스를 한 번만 요청했기 때문입니다. 이 문제를 해결하기 위한 두 가지 아이디어가 있습니다. 1. 메뉴 리소스를 저장소에 저장하지 말고, F5를 새로 고친 후에도 데이터가 그대로 유지되도록 localStorage에 저장합니다. 2. 마운트된 메서드에서 직접; 각 페이지에서 메뉴 리소스 로드로 이동하세요.
메뉴 리소스는 매우 민감하기 때문에 로컬에 저장하지 않는 것이 가장 좋기 때문에 옵션 1은 포기하지만, 옵션 2는 작업량이 좀 많아서 단순화하는 방법을 채택했습니다. 경로에 내비게이션 가드를 사용하는 것입니다.
내 구체적인 구현은 다음과 같습니다. 먼저 저장소에 빈 배열인 경로 배열을 만든 다음 다음과 같이 경로 전역 가드를 켭니다.
<span style="font-size: 14px;">router.beforeEach((to, from, next)=> {<br> if (to.name == 'Login') {<br> next();<br> return;<br> }<br> var name = store.state.user.name;<br> if (name == '未登录') {<br> if (to.meta.requireAuth || to.name == null) {<br> next({path: '/', query: {redirect: to.path}})<br> } else {<br> next();<br> }<br> } else {<br> initMenu(router, store);<br> next();<br> }<br> }<br>)<br></span>
여기 코드는 매우 짧습니다. 간단히 설명하겠습니다.
1. 이동하려는 페이지가 로그인 페이지인 경우 이에 대해 말할 것도 없고 바로 이동하세요.
2.如果不是登录页面的话,我先从store中获取当前的登录状态,如果未登录,则通过路由中meta属性的requireAuth属性判断要去的页面是否需要登录,如果需要登录,则跳回登录页面,同时将要去的页面的path作为参数传给登录页面,以便在登录成功之后跳转到目标页面,如果不需要登录,则直接过(事实上,本项目中只有Login页面不需要登录);如果已经登录了,则先初始化菜单,再跳转。
初始化菜单的操作如下:
<span style="font-size: 14px;">export const initMenu = (router, store)=> {<br> if (store.state.routes.length > 0) {<br> return;<br> }<br> getRequest("/config/sysmenu").then(resp=> {<br> if (resp && resp.status == 200) {<br> var fmtRoutes = formatRoutes(resp.data);<br> router.addRoutes(fmtRoutes);<br> store.commit('initMenu', fmtRoutes);<br> }<br> })<br>}<br>export const formatRoutes = (routes)=> {<br> let fmRoutes = [];<br> routes.forEach(router=> {<br> let {<br> path,<br> component,<br> name,<br> meta,<br> iconCls,<br> children<br> } = router;<br> if (children && children instanceof Array) {<br> children = formatRoutes(children);<br> }<br> let fmRouter = {<br> path: path,<br> component(resolve){<br> if (component.startsWith("Home")) {<br> require(['../components/' + component + '.vue'], resolve)<br> } else if (component.startsWith("Emp")) {<br> require(['../components/emp/' + component + '.vue'], resolve)<br> } else if (component.startsWith("Per")) {<br> require(['../components/personnel/' + component + '.vue'], resolve)<br> } else if (component.startsWith("Sal")) {<br> require(['../components/salary/' + component + '.vue'], resolve)<br> } else if (component.startsWith("Sta")) {<br> require(['../components/statistics/' + component + '.vue'], resolve)<br> } else if (component.startsWith("Sys")) {<br> require(['../components/system/' + component + '.vue'], resolve)<br> }<br> },<br> name: name,<br> iconCls: iconCls,<br> meta: meta,<br> children: children<br> };<br> fmRoutes.push(fmRouter);<br> })<br> return fmRoutes;<br>}<br></span>
在初始化菜单中,首先判断store中的数据是否存在,如果存在,说明这次跳转是正常的跳转,而不是用户按F5或者直接在地址栏输入某个地址进入的。否则就去加载菜单。拿到菜单之后,首先通过formatRoutes方法将服务器返回的json转为router需要的格式,这里主要是转component,因为服务端返回的component是一个字符串,而router中需要的却是一个组件,因此我们在formatRoutes方法中动态的加载需要的组件即可。数据格式准备成功之后,一方面将数据存到store中,另一方面利用路由中的addRoutes方法将之动态添加到路由中。
最后,在Home页中,从store中获取菜单json,渲染成菜单即可,相关代码可以在<span style="font-size: 14px;">Home.vue</span>
中查看,不赘述。
OK,如此之后,不同用户登录成功之后就可以看到不同的菜单了。
相关推荐:
위 내용은 권한 관리 모듈에서 Vue 구성 요소 인스턴스를 동적으로 로드하는 방법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!