脚本宝典收集整理的这篇文章主要介绍了

基于vue模块化开发后台系统——权限控制

脚本宝典小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助你少写一行代码,多一份安全和惬意。
<p><code></p> <p>文章目录如下:<br /><a href="http://demo.bnuephjx.com/test-vue-admin.github.io" rel="nofollow noreferrer" target="_blank">项目效果预览地址</a><br /><a href="https://github.com/bnuephjx/test-vue-admin" rel="nofollow noreferrer" target="_blank">项目开源代码</a><br /><a href="https://segmentfault.com/a/1190000014070629">基于vue模块化开发后台系统——准备工作</a><br /><a href="https://segmentfault.com/a/1190000014085486" target="_blank">基于vue模块化开发后台系统——构建项目</a><br /><a href="https://segmentfault.com/a/1190000014413761">基于vue模块化开发后台系统——权限控制</a></p> <h2 id="articleHeader0"><strong>前言</strong></h2> <p>在我们构建项目之后,现在开始撸代码了!非常抱歉拖了那么久,最近麻烦事情比较多,现在是终于空闲那么一点点了!在写这篇权限控制的时候,想了很久,不知道该如何下手才能更好的表达出来,感觉代码有点绕,可能是自己对于vue不是很熟悉吧,开文已经说了,这个项目是练手项目,有不足之处欢迎指出来。</p> <p>先看效果图,看看是不是你要的。<br /><span class="img-wrap"><img data-src="/img/bV8Dhc?w=1350&amp;h=479" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="图片描述" title="图片描述" style="cursor: pointer;"></span></p> <p>假设后台界面是这样<br /><span class="img-wrap"><img data-src="/img/bV8CWD?w=89&amp;h=231" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="图片描述" title="图片描述" style="cursor: pointer;"></span></p> <p><strong>在这里值得注意的是:</strong><code>在未登录的时候,本项目的控制逻辑是只能显示登录这个页面,输入其它链接也是不会跳转的!</code>效果如下:<br /><span class="img-wrap"><img data-src="/img/bV8C1t?w=863&amp;h=539" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="图片描述" title="图片描述" style="cursor: pointer;"></span></p> <blockquote><p>按照我个人理解逻辑就是在登录之后根据用户信息得知对应的权限,实际上就是控制用户对应的路由,从而在界面上显示出。</p></blockquote> <p>例如拿上边的图来说:<br />1.假设<code>admin</code>是超级管理员,那么得到的就是所有的路由,界面显示<code>(概况,组件,权限)</code><br />2.<code>normal</code>是普通管理员,只能看见部分,界面显示<code>(概况,组件)</code></p> <p>大概的逻辑就是这样,在获取权限之前,肯定要先登录,不然怎么知道你是谁呢?你能干嘛呢?</p> <h2 id="articleHeader1"><strong>登录</strong></h2> <p>只追求功能实现的,可以先随便弄两个输入框加上一个确定按钮,给确定按钮绑定click事件。有强迫症的我,还是给美化了下,然后在提交之前进行表单验证,效果如下:<code>(账号是随机生成的)</code><br /><span class="img-wrap"><img data-src="/img/bV8C2p?w=322&amp;h=249" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="图片描述" title="图片描述" style="cursor: pointer;"></span></p> <p>验证完成,实现登录之后,我们进行用户信息保存操作。</p> <h2 id="articleHeader2"><strong>获取用户信息</strong></h2> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="this.$http.post('/login', _data).then((response) => {<br /> // 保存用户信息(StoreUser/setUser)<br /> this.$store.dispatch('StoreUser/setUser', response.data).then(() => {</p> <p> });<br /> });" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs coffeescript"><code><span class="hljs-keyword"><a href="http://www.js-code.com/tag/this" title="浏览关于“this”的文章" target="_blank" class="tag_link">this</a></span>.$http.post(<span class="hljs-string">'/login'</span>, _data).<span class="hljs-keyword">then</span>(<span class="hljs-function"><span class="hljs-params">(response)</span> =&gt;</span> { <span class="hljs-regexp">//</span> 保存用户信息(StoreUser/setUser) <span class="hljs-keyword">this</span>.$store.dispatch(<span class="hljs-string">'StoreUser/setUser'</span>, response.data).<span class="hljs-keyword">then</span>(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> { }); });</code></pre> <p>登录成功后,服务端会返回客户的信息,用了<strong><code>VUEX</code></strong>这个状态管理工具,优先保存在一个用户的状态信息,因为有可能在多处会用到这个信息,例如个人中心等等页面。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="const state={ 'isLogin':false }; const mutations = { 'SET_USER':function(state,userData){ state = _.assign(state,userData); Cookie.set('accountData', state); }, 'REMOVE_USER':function(state){ state = _.assign(state,{ 'isLogin':false }); Cookie.remove('accountData'); } }; const actions = { 'setUser':function({commit},userData){ commit('SET_USER',userData); }, 'removeUser':function({commit}){ commit('REMOVE_USER'); } };" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs actionscript"><code><span class="hljs-keyword"><a href="http://www.js-code.com/tag/const" title="浏览关于“const”的文章" target="_blank" class="tag_link">const</a></span> state={ <span class="hljs-string">'isLogin'</span>:<span class="hljs-literal">false</span> }; <span class="hljs-keyword">const</span> mutations = { <span class="hljs-string">'SET_USER'</span>:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(state,userData)</span></span>{ state = _.assign(state,userData); Cookie.set(<span class="hljs-string">'accountData'</span>, state); }, <span class="hljs-string">'REMOVE_USER'</span>:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(state)</span></span>{ state = _.assign(state,{ <span class="hljs-string">'isLogin'</span>:<span class="hljs-literal">false</span> }); Cookie.remove(<span class="hljs-string">'accountData'</span>); } }; <span class="hljs-keyword">const</span> actions = { <span class="hljs-string">'setUser'</span>:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">({commit},userData)</span></span>{ commit(<span class="hljs-string">'SET_USER'</span>,userData); }, <span class="hljs-string">'removeUser'</span>:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">({commit})</span></span>{ commit(<span class="hljs-string">'REMOVE_USER'</span>); } };</code></pre> <p>再将这个用户信息保存Cookie中,用做会话处理,这样下次打开页面或者刷新页面的时候能记住用户的登录状态。这里使用了<a href="https://www.npmjs.com/package/js-cookie" rel="nofollow noreferrer" target="_blank">js-cookie</a>这个工具。</p> <h2 id="articleHeader3"><strong>生成权限路由表</strong></h2> <p>获取用户信息,就能知道这个用户的权限范围了,然后我们根据这个权限生成对应的路由表</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text=" this.$store.dispatch('StoreAddRoutes/getRoutes',_roles).then(() => {<br /> // 根据_roles权限生成可访问的路由表<br /> // 动态添加可访问路由表<br /> this.$router.addRoutes(this.$store.getters.addRoutes);<br /> // 黑科技<br /> window.location.replace('/');<br /> });" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code> <span class="hljs-keyword">this</span>.$store.dispatch(<span class="hljs-string">'StoreAddRoutes/getRoutes'</span>,_roles).then(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> { <span class="hljs-comment">// 根据_roles权限生成可访问的路由表</span> <span class="hljs-comment">// 动态添加可访问路由表</span> <span class="hljs-keyword">this</span>.$router.addRoutes(<span class="hljs-keyword">this</span>.$store.getters.addRoutes); <span class="hljs-comment">// 黑科技</span> <span class="hljs-built_in">window</span>.location.replace(<span class="hljs-string">'/'</span>); });</code></pre> <p><code>StoreAddRoutes/getRoutes</code>这个方法是如何呢?</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="const state = { 'addRoutes': [] }; const actions = { 'getRoutes':function({commit},roles){ if (_.indexOf(roles, 'admin') !== -1) { commit('SET_ROUTERS',adminRoutes()); } else { commit('SET_ROUTERS',normalRoues()); } } };" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs actionscript"><code><span class="hljs-keyword">const</span> state = { <span class="hljs-string">'addRoutes'</span>: [] }; <span class="hljs-keyword">const</span> actions = { <span class="hljs-string">'getRoutes'</span>:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">({commit},roles)</span></span>{ <span class="hljs-keyword">if</span> (_.indexOf(roles, <span class="hljs-string">'admin'</span>) !== <span class="hljs-number">-1</span>) { commit(<span class="hljs-string">'SET_ROUTERS'</span>,adminRoutes()); } <span class="hljs-keyword">else</span> { commit(<span class="hljs-string">'SET_ROUTERS'</span>,normalRoues()); } } };</code></pre> <p>通过<code>StoreAddRoutes/getRoutes</code>返回的路由信息<code><a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.$store.getters.addRoutes</code>,主要是用了vue2.2.0以后新增了<strong><code>router.addRoutes</code></strong>的方法进行动态添加,<code>注意addRoutes()这个方法添加是<a href="http://www.js-code.com/tag/%e6%95%b0%e7%bb%84" title="数组" target="_blank">数组</a>!</code></p> <p>重点是这句:<strong><code><a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.$router.addRoutes(this.$store.getters.addRoutes);</code></strong></p> <div class="google-auto-placed ap_container" style="text-align: center; width: 100%; height: auto; clear: none;"><ins data-ad-format="auto" class="adsbygoogle adsbygoogle-noablate" data-ad-client="ca-pub-6330872677300335" data-adsbygoogle-status="done" style="display: block; margin: auto; background-color: transparent;"><ins id="aswift_4_expand" style="display: inline-table; border: none; height: 0px; margin: 0px; padding: 0px; position: relative; visibility: visible; width: 697px; background-color: transparent;"><ins id="aswift_4_anchor" style="display: block; border: none; height: 0px; margin: 0px; padding: 0px; position: relative; visibility: visible; width: 697px; background-color: transparent; overflow: hidden; opacity: 0;"><iframe width="697" height="175" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" onload="var i=this.id,s=window.google_iframe_oncopy,H=s&amp;&amp;s.handlers,h=H&amp;&amp;H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&amp;&amp;d&amp;&amp;(!d.body||!d.body.firstChild)){if(h.call){setTimeout(h,0)}else if(h.match){try{h=s.upd(h,i)}catch(e){}w.location.replace(h)}}" id="aswift_4" name="aswift_4" style="left:0;position:absolute;top:0;border:0px;width:697px;height:175px;"></iframe></ins></ins></ins></div> <p>在<code>actions</code>中,我们根据权限分了<code>adminRoutes</code>和<code>normalRoutes</code>这两个路由表,分别对应<code>超级管理员</code>和<code>普通管路员</code></p> <h2 id="articleHeader4"><strong>整体路由表</strong></h2> <p>从上面获取可以看出由权限分出的两个路由表,那么这两个<code>adminRoutes</code>和<code>normalRoutes</code>是怎么来的呢?</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="/** * [AdminRouter 超级管理员] * @type {Array} */ export function adminRoutes() { layoutObj.children = layoutObj.children.concat([ RoleRouter ]); return [commonRoutes(),layoutObj]; } /** * [NormalRouer 普通用户] * @type {Array} */ export function normalRoues() { return [commonRoutes(),layoutObj]; }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs javascript"><code><span class="hljs-comment">/** * [AdminRouter 超级管理员] * @type {<a href="http://www.js-code.com/tag/array" title="浏览关于“Array”的文章" target="_blank" class="tag_link">Array</a>} */</span> <span class="hljs-keyword"><a href="http://www.js-code.com/tag/export" title="浏览关于“export”的文章" target="_blank" class="tag_link">export</a></span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">adminRoutes</span>(<span class="hljs-params"></span>) </span>{ layoutObj.children = layoutObj.children.concat([ RoleRouter ]); <span class="hljs-keyword">return</span> [commonRoutes(),layoutObj]; } <span class="hljs-comment">/** * [NormalRouer 普通用户] * @type {Array} */</span> <span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">normalRoues</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">return</span> [commonRoutes(),layoutObj]; }</code></pre> <p>其中<code>commonRoutes()</code>是公共页面,例如登录,404等页面</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="/** * 公共路由 * @type {Array} */ export function commonRoutes() { return LoginRouter; }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs javascript"><code><span class="hljs-comment">/** * 公共路由 * @type {Array} */</span> <span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">commonRoutes</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">return</span> LoginRouter; }</code></pre> <p>而<code>layoutObj</code>这个就是整个布局信息,包括:侧边栏<code>SideBar</code>,右边帮助<code>Help</code>,底部<code>Footer</code>和中间内容<code>Comtainer</code></p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="import LoginRouter from '@/pages/login/router.js'; import HomeRouter from '@/pages/home/router.js'; import RoleRouter from '@/pages/role/router.js'; import ModuleRouter from '@/pages/module/router.js'; const Comtainer = resolve => require(['@/components/layout/layout'],resolve);<br /> const SideBar = resolve => require(['@/components/layout/sidebar'],resolve);<br /> const Help = resolve => require(['@/components/layout/help'],resolve);<br /> const Footer = resolve => require(['@/components/layout/footer'],resolve);</p> <p>let layoutObj = {<br /> 'path': '/',<br /> 'name': 'layout',<br /> 'components': {<br /> 'default' : Comtainer,<br /> 'sidebar' : SideBar,<br /> 'help' : Help,<br /> 'appFooter': Footer<br /> },<br /> 'redirect': '/index',<br /> 'children': [<br /> HomeRouter,<br /> ModuleRouter<br /> ]<br /> };" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword">import</span> LoginRouter <span class="hljs-keyword">from</span> <span class="hljs-string">'@/pages/login/router.js'</span>; <span class="hljs-keyword">import</span> HomeRouter <span class="hljs-keyword">from</span> <span class="hljs-string">'@/pages/home/router.js'</span>; <span class="hljs-keyword">import</span> RoleRouter <span class="hljs-keyword">from</span> <span class="hljs-string">'@/pages/role/router.js'</span>; <span class="hljs-keyword">import</span> ModuleRouter <span class="hljs-keyword">from</span> <span class="hljs-string">'@/pages/module/router.js'</span>; <span class="hljs-keyword">const</span> Comtainer = <span class="hljs-function"><span class="hljs-params">resolve</span> =&gt;</span> <span class="hljs-built_in">require</span>([<span class="hljs-string">'@/components/layout/layout'</span>],resolve); <span class="hljs-keyword">const</span> SideBar = <span class="hljs-function"><span class="hljs-params">resolve</span> =&gt;</span> <span class="hljs-built_in">require</span>([<span class="hljs-string">'@/components/layout/sidebar'</span>],resolve); <span class="hljs-keyword">const</span> Help = <span class="hljs-function"><span class="hljs-params">resolve</span> =&gt;</span> <span class="hljs-built_in">require</span>([<span class="hljs-string">'@/components/layout/help'</span>],resolve); <span class="hljs-keyword">const</span> Footer = <span class="hljs-function"><span class="hljs-params">resolve</span> =&gt;</span> <span class="hljs-built_in">require</span>([<span class="hljs-string">'@/components/layout/footer'</span>],resolve); <span class="hljs-keyword"><a href="http://www.js-code.com/tag/let" title="浏览关于“let”的文章" target="_blank" class="tag_link">let</a></span> layoutObj = { <span class="hljs-string">'path'</span>: <span class="hljs-string">'/'</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'layout'</span>, <span class="hljs-string">'components'</span>: { <span class="hljs-string">'default'</span> : Comtainer, <span class="hljs-string">'sidebar'</span> : SideBar, <span class="hljs-string">'help'</span> : Help, <span class="hljs-string">'appFooter'</span>: Footer }, <span class="hljs-string">'redirect'</span>: <span class="hljs-string">'/index'</span>, <span class="hljs-string">'children'</span>: [ HomeRouter, ModuleRouter ] };</code></pre> <p>看完整个路由表的信息,这样就能很容易通过不同的权限,放置不同的页面路由,从而进行权限控制。</p> <blockquote><p>注意到上边我提到的黑科技没?<br />在动态添加完路由表之后,进行页面首页跳转。而不是使用this.$router.push()这个方法跳转?因为如果使用这个方法,会一直警告有重复路由的警告,看了源码大概是因为addRoutes()这个方法,框架并没有提供删除路由的方法,添加了就一直会存在浏览器中,因此用黑科技,将页面刷新。</p></blockquote> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="// 黑科技 window.location.replace('/');" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-comment">// 黑科技</span> <span class="hljs-built_in">window</span>.location.replace(<span class="hljs-string">'/'</span>);</code></pre> <h2 id="articleHeader5"><strong>路由拦截</strong></h2> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="router.beforeEach((to, from, next) => {<br /> if (Cookie.getJSON('accountData') &amp;&amp; Cookie.getJSON('accountData').isLogin) { // 判断是否有cookie<br /> next();//当有用户权限的时候,说明所有可访问路由已生成 如访问没权限的全面会自动进入登录页面<br /> } else if (to.path === '/login') {<br /> next();<br /> } else {<br /> next('/login'); //当有用户权限的时候,说明所有可访问路由已生成 如访问没权限的全面会自动进入404页面<br /> }<br /> });" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs ruby"><code>router.beforeEach((to, from, <span class="hljs-keyword">next</span>) =&gt; { <span class="hljs-keyword">if</span> (Cookie.getJSON(<span class="hljs-string">'accountData'</span>) &amp;&amp; Cookie.getJSON(<span class="hljs-string">'accountData'</span>).isLogin) { <span class="hljs-regexp">//</span> 判断是否有cookie <span class="hljs-keyword">next</span>();<span class="hljs-regexp">//</span>当有用户权限的时候,说明所有可访问路由已生成 如访问没权限的全面会自动进入登录页面 } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (to.path === <span class="hljs-string">'/login'</span>) { <span class="hljs-keyword">next</span>(); } <span class="hljs-keyword">else</span> { <span class="hljs-keyword">next</span>(<span class="hljs-string">'/login'</span>); <span class="hljs-regexp">//</span>当有用户权限的时候,说明所有可访问路由已生成 如访问没权限的全面会自动进入<span class="hljs-number">404</span>页面 } });</code></pre> <p>拦截器是为了防止用户直接输入地址进行跳转,因为你都没登录,怎么可能就让你进行访问呢!!<br />当cookie存在用户信息的时候,说明是登录状态,可以进行正常访问,如果不是登录状态,那么只能跳转到登录状态。</p> <h2 id="articleHeader6"><strong>文章</strong></h2> <p><a href="http://demo.bnuephjx.com/test-vue-admin.github.io" rel="nofollow noreferrer" target="_blank">项目效果预览地址</a><br /><a href="https://github.com/bnuephjx/test-vue-admin" rel="nofollow noreferrer" target="_blank">项目开源代码</a><br /><a href="https://segmentfault.com/a/1190000014070629">基于vue模块化开发后台系统——准备工作</a><br /><a href="https://segmentfault.com/a/1190000014085486" target="_blank">基于vue模块化开发后台系统——构建项目</a><br /><a href="https://segmentfault.com/a/1190000014413761">基于vue模块化开发后台系统——权限控制</a></p> <p></code></p>

总结

以上是脚本宝典为你收集整理的

基于vue模块化开发后台系统——权限控制

全部内容,希望文章能够帮你解决

基于vue模块化开发后台系统——权限控制

所遇到的程序开发问题,欢迎加入QQ群277859234一起讨论学习。如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典网站推荐给程序员好友。 本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。

80%的人都看过