<p><code></p> <h3 id="articleHeader0">索引</h3> <ul> <li><a href="#">概述</a></li> <li><a href="#">基于指令</a></li> <li><a href="#">基于组件</a></li> <li><a href="#">权限的定义</a></li> </ul> <h3 id="articleHeader1">概述</h3> <p>关于动态路由的相关处理,请参考本人的另一篇文章<a href="https://segmentfault.com/a/1190000013883117">vue.js前后端分离后台,该如何根据用户权限处理前端显示和后台接口访问</a>,本文作为上一篇的续作<br />有时候仅处理菜单,是不够的,很多情况下,有读的权限,但无写的权限的时候,就需要更灵活的控制。也就是这篇文章的由来。</p> <p>大概有两种方式可以使用:</p> <ol> <li>指令</li> <li>组件</li> </ol> <h3 id="articleHeader2">基于指令</h3> <p>关于指令的使用,网上的文章比较多了,主要是操作<a href="http://www.js-code.com/tag/dom" title="DOM" target="_blank">DOM</a>,把没有权限的元素从已渲染的画面里面删除。这里只是简单的出个示范,具体可以参考自己的授权系统开发:</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 Vue from 'vue' // import Store from '../store/' const directives = { role: { // 指令的定义 (TBD:有没有before'inserted'这样的钩子函数用?) inserted: (el, binding, vnode) => {<br /> // 权限<br /> if (binding.value &amp;&amp; [处理权限的判定]) {<br /> el.parentElement.removeChild(el)<br /> }<br /> }<br /> }<br /> }</p> <p>Object.keys(directives).forEach(key => {<br /> Vue.directive(key, directives[key])<br /> })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="javascript"><span class="hljs-keyword">import</span> <a href="http://www.js-code.com/tag/vue" title="浏览关于“Vue”的文章" target="_blank" class="tag_link">Vue</a> <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span> <span class="hljs-comment">// import Store from '../store/'</span> <span class="hljs-keyword"><a href="http://www.js-code.com/tag/const" title="浏览关于“const”的文章" target="_blank" class="tag_link">const</a></span> directives = { <span class="hljs-attr">role</span>: { <span class="hljs-comment">// 指令的定义 (TBD:有没有before'inserted'这样的钩子函数用?)</span> inserted: <span class="hljs-function">(<span class="hljs-params">el, binding, v<a href="http://www.js-code.com/tag/node" title="浏览关于“node”的文章" target="_blank" class="tag_link">node</a></span>) =&gt;</span> { <span class="hljs-comment">// 权限</span> <span class="hljs-keyword">if</span> (binding.value &amp;&amp; [处理权限的判定]) { el.parentElement.removeChild(el) } } } } <span class="hljs-built_in">Object</span>.keys(directives).forEach(<span class="hljs-function"><span class="hljs-params">key</span> =&gt;</span> { Vue.directive(key, directives[key]) })</code></pre> <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="<el-button type=&quot;success&quot; icon=&quot;el-icon-document&quot; size=&quot;small&quot; v-role=&quot;xxx-upload&quot; @click=&quot;$router.push({name: 'music-album-multi-upload'})&quot;>上传<br /> </el-button>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html"><span class="hljs-tag">&lt;<span class="hljs-name">el-button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"success"</span> <span class="hljs-attr">icon</span>=<span class="hljs-string">"el-icon-document"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"small"</span> <span class="hljs-attr">v-role</span>=<span class="hljs-string">"xxx-upload"</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"$router.push({name: 'music-album-multi-upload'})"</span>&gt;</span>上传 <span class="hljs-tag">&lt;/<span class="hljs-name">el-button</span>&gt;</span></code></pre> <h3 id="articleHeader3">基于组件</h3> <p>不确定对于vue组件,有没有全局的<a href="http://www.js-code.com/tag/%e7%94%9f%e5%91%bd%e5%91%a8%e6%9c%9f%e9%92%a9%e5%ad%90" title="生命周期钩子" target="_blank">生命周期钩子</a>,如果有的话,处理起来就更方便了。<br />下面就以普通的组件形式来说明下处理过程:</p> <p>写一个全局的组件,注册为<code>v-sec</code>,其中参数code为访问当前画面segment的授权码。</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="<template></p> <div> <slot v-if=&quot;permitted&quot;></slot> </div> <p></template></p> <p><script> import vuet from '@/vuet/'</p> <p> <a href="http://www.js-code.com/tag/export" title="export" target="_blank">export</a> default { name: &quot;sec&quot;, props: { code: { type: String, required: true, default: 'text' }, }, data() { return { permitted: false } }, beforeCreate() { <a href="http://www.js-code.com/tag/let" title="let" target="_blank">let</a> userSelf = vuet.getModule('user-self') if (userSelf /* &amp;&amp; userSelf.secCodes &amp;&amp; userSelf.secCodes.contains(<a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.code) */) { <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.$nextTick(function () { <a href="http://www.js-code.com/tag/this" title="浏览关于“this”的文章" target="_blank" class="tag_link">this</a>.permitted = true }) } } } </script><br /> " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs xml"><code><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name"><a href="http://www.js-code.com/tag/div" title="浏览关于“div”的文章" target="_blank" class="tag_link">div</a></span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> <span class="hljs-attr">v-if</span>=<span class="hljs-string">"permitted"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">slot</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"> <span class="hljs-keyword">import</span> vuet <span class="hljs-keyword">from</span> <span class="hljs-string">'@/vuet/'</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-keyword">default</span> { <span class="hljs-attr">name</span>: <span class="hljs-string">"sec"</span>, <span class="hljs-attr">props</span>: { <span class="hljs-attr">code</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">default</span>: <span class="hljs-string">'text'</span> }, }, data() { <span class="hljs-keyword">return</span> { <span class="hljs-attr">permitted</span>: <span class="hljs-literal">false</span> } }, beforeCreate() { <span class="hljs-keyword"><a href="http://www.js-code.com/tag/let" title="浏览关于“let”的文章" target="_blank" class="tag_link">let</a></span> userSelf = vuet.getModule(<span class="hljs-string">'user-self'</span>) <span class="hljs-keyword">if</span> (userSelf <span class="hljs-comment">/* &amp;&amp; userSelf.secCodes &amp;&amp; userSelf.secCodes.contains(this.code) */</span>) { <span class="hljs-keyword">this</span>.$nextTick(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">this</span>.permitted = <span class="hljs-literal">true</span> }) } } } </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> </code></pre> <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="<v-sec code=&quot;xxx-add&quot;><br /> <el-button type=&quot;success&quot; icon=&quot;el-icon-document&quot; size=&quot;small&quot; @click=&quot;$router.push('/sys/module/add')&quot;>添加<br /> </el-button><br /> </v-sec>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs xml"><code><span class="hljs-tag">&lt;<span class="hljs-name">v-sec</span> <span class="hljs-attr">code</span>=<span class="hljs-string">"xxx-add"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">el-button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"success"</span> <span class="hljs-attr">icon</span>=<span class="hljs-string">"el-icon-document"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"small"</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"$router.push('/sys/module/add')"</span>&gt;</span>添加 <span class="hljs-tag">&lt;/<span class="hljs-name">el-button</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">v-sec</span>&gt;</span></code></pre> <p>与指令的那种方式在使用方面差不多,如果组件的这种方式能避免内嵌的组件被渲染,那效果会比指令的那种好一些。</p> <p>接下来,在项目只可能就两种方式分别做实验。</p> <h3 id="articleHeader4">权限的定义</h3> <h4>画面</h4> <p>一般通过导航+动态路由能控制住的,像画面和菜单。<br />然后配合路由的全局函数<code>router.beforeEach</code>基本上比较好实现。<br />为了配合动态路由,需要指定以下几个字段</p> <ul> <li>路径,用于画面跳转,</li> <li>组件名/文件地址,用于路由生成,指向实际的vue文件(我们可以约定-代替路径分隔符:common-main=/src/pages/common/main.vue)</li> <li>画面名,用于显示,导航或Title等地方需要</li> <li>icon,有一些样式库里有这个,作为可选项</li> <li>show_nav,是否显示在导航中,有一些画面需要参数的话,不能够直接从导航进入,可区分开</li> </ul> <h4>页面片段</h4> <p>基本上标记个名字,与画面关联起来以便于管理就可以了。<br />然后配置后台管理系统,可以通过先通过后台录入画面及画面片段,然后用程序生成对应的vue文件及部分代码。这样子开发效率是不是高一些?</p> <ul> <li>画面ID</li> <li>片段编码,不直接使用DB的ID自增,以避免在不同的系统间数据迁移时的问题。</li> <li>片段名,在授权画面展示以方便管理</li> </ul> <h4>授权</h4> <p>授权时,把画面和画面片段与角色关联即可,然后用户在登录后获取到角色,再从内存/DB/缓存中把角色对应的画面和菜单等权限查出,合并到一起返回给vue。vue拿到数据后,缓存到localstorage以避免画面的刷新(f5/浏览器刷新)后出现404的问题,这一点在上一篇里面已经说明过了。</p> <p></code></p>

本文固定链接: http://www.js-code.com/vue-js/vue-js_27004.html