まず、先行レビュー
こんにちはこんにちは、誰もが、この幸せな日に、張はあなたがすべての作業が活況を呈しことができることを願います!今日は、コミュニティの設立のちょうど最初の日で、私はまた、今日はデイ、自己満足この大きなお祝いできることを願っています!
この2日間の休日、それは多くのことを学んだ触れる、私はこれは昨日の取引は、今日のボタンレベルの権限は、グループ・プログラムと、私は記事を書いた小さなパートナー、恐怖と不安のアイデアがあるコミットされて認めます私はもちろん、完全に私のコミュニティのために、私はすべての後にペニーを取得していない、関係なく最高の状態で、そこにあるどのくらいのトラフィック、良い数字を見てそうではない、私はいつも泥棒の知識のが怖いと言うでしょう。
自宅に近い、6ヶ月前に覚えている(2019年2月27日)私のVUEプロジェクトIIの時間:Blog.Adminが正式にオープン(https://github.com/anjoy8/Blog.Admin)、特権の簡単な背景をやるつもりでしたシステム、私はいくつかの共通の特徴は、もちろん、一部の人は醜いと言うと思いますが、一部の人々は混乱を言うが、一部の人は、自分のプロジェクトや企業で使用するだけでなく、私の努力は支払うことなく、完璧時Blog.Coreプログラムに沿って、いくつかの主要な機能で想定される、遅延機能が長時間保留に実装されていないがある-つまり、によって特権レベルの設定ボタン:
2、別の配慮を、彼らはボタンをしたい、私はそれをしなかった理由は、2つの配慮、一つは、私は、あなたのデータの悪用の恐れのスーパー管理者のアクセスを、聞かせて見て他人の権利に影響を及ぼさなかったので、そこにあるました暴力がこぼれ、それがデータを削除することができ、真のテストテストアカウントがあるかどうかを確認します。そして、私はそれがミックスにこの権限を追加してみましょう、考え始め、それは、削除ボタンが表示されていない削除が、長い時間のために考慮する権限がありません、少し知識がポイントに貼付され、結合方法を動的なイベントを考えていません私の次の記事では、グループ管理@キュウリと@Kawhiによる解決策のアイデアとソリューションを提供するために、一昨日の話輝く、そして最終的にこの機能を達成する、重要ではありません理解していません。
貢献著者:@ キュウリと@ Kawhi。
エフェクトプレビュー:現在のみ「のを防止するために、私の大きな変化、ロール管理」ページでは、すべての後半に置き換え、この機能が追加されます。
オンライン住所:http://vueadmin.neters.club
Githubのブランチ:メインブランチ。
ヒント:現在、私はまだ管理者権限を開いていないので、あなたは完全な効果を確認したい場合は、ローカル、自己設定ビューをダウンロードすることができます。
以下は二つの部分、知識+ステップの手順の焦点に分け、正式な交渉を開始し、その下に、なぜ、パートIIIラインに直接手が、気にしないときの手順を見て - ハイライトの知識、簡単に話します。
第二に、詳細設計の段階
1、バックエンドの微調整、保存ボタン情報
私はしませんフロントエンドまたはバックエンド業務、私は楽屋権限システムだ、覚えて、ナビゲーションバーの左側には、いわゆる自動化を自動化してきた何のジュニアパートナーはありません知っているにかかわらず増加にどのくらいの権威、完全にデータベースにすでに存在しません。 、目的を達成するために設定する必要があり、それは、私は、デザインのアイデアのおかげで非常に不合理な感じが、今では変更することは簡単ですして、メニューボタンの左側に置くと、テーブルにこねたので、これを私たちは、ほとんどただ、二つの小さな点があるとすることができるボタン情報を出す必要があり、何も変更しないでください。
1、Permission.csメニューテーブルのFunc新しいフィールド、イベントに対応する現在のボタンを格納するために使用される方法。
2、/許可/ GetNavigationBarインタフェース、それは再帰的なメニューに合うことができるように、偽==制限IsButtonを削除します。
// するvar rolePermissionMoudles =(_permissionServices.Queryを待つ(D => pids.Contains(d.Id)&& d.IsButton ==偽))のOrderBy(C => c.OrderSort)。 VaRの rolePermissionMoudles =(待機 _permissionServices.Query(D => pids.Contains(d.Id)))のOrderBy(C => c.OrderSort)。3は、RecursionHelper.csに、フロントエンドのツリーに乗るに戻り、IsButton属性データベースのデータを追加します。
だから我々は、データが一緒にフロントに戻ると組み合わせたメニューボタンのデータを入れて、あなたはで見ることができます:
ここでは、最初の部分-バックエンドデータは、あなたがよりクールになりたい場合は、私は罰金ではないことを理解しなければならない場合には、その上、このようなスタイルのボタン、または他のプロパティとして、フィールドを増やすなどしてできる以上、当然のことながら、完了です彼は言いました。
我々はBlog.Adminプロジェクトは、VSCodeを開いて、私たちVueのプロジェクトを修正してくださいと言うようになった、以下から開始します。
2、背景の著作権管理を変更し、[追加]ボタンイベント
このステップでは、それはCRUDに設立され、当社のフィールドのFuncページでは、特定のコードが自分に変わるように見えるの上で、非常に簡単です。
3、コントロール「ボタン」ではなく「メニューは、」競合を表示します
:私達はちょうど私たちがチェックするために、メニューが競合を示していない必要があるこの時間は、ここで私はちょうど場所の変更を言うだろうと、メニューボタンのデータが一緒にオープンと組み合わせて、トップに来ます
1は、理解するためのコードで特定の外観を表示しないデータボタンを可能にSidebar.vueコンポーネントを変更し、それは非常に簡単です。
2、変更 \のsrc \ルータ動的ルーティングのindex.js注射を、ボタンデータを濾別。
ここに、私たちの第二部-準備作業に行わには、それから、それはこの設計ツールバーのこの論文のハイライトの最優先事項であり、その具体的操作方法を、私はあなたがそれを一時停止することを願って、この時、データもボタンがあり、つまり、思考の私の方法によると、最初の考える心の中で、ダウン見てはいけない、どのようにそれの共通のコンポーネントを設計するには?5分、それを考えてみましょう......
5分後、あなたはそれについて考えていると仮定すると、私は正式な声明を開始しました。
4.デザインツールバーコンポーネント--Toolbar.vue
それはそれは抽象化されている必要があり、自動化されたアセンブリを作成したい場合は、最初のステップは、コードの束を書くために、各ページに類似していないコンポーネントを作成することです。
実際に、我々は設定する必要があり、また持っている必要があり、前方に配置するだけではなく、ボタンなど他の<input />検索ボックスなど、ツールバーに配置する必要があります。
他の人も見るために時間の要素を参照するようにあなたは、表示または非表示にすることができない、ロードまたはロードされません確認してください。
要約すると、私のデザインは、ボタン、すべてのレンダリングは私たちのショーを与え、トップと呼ばの形態である、これは私が手動で、あなたも自分のフィールドの設定を追加することができます削除、追加の色です。
まず我々は、アセンブリを作成SRC \コンポーネント\ ツールバー次のように.vue、具体的なコードは次のとおりです。
<template> <el-col v-if="buttonList.length>0" :span="24" class="toolbar" style="padding-bottom: 0px;"> <el-form :inline="true" @submit.native.prevent> <el-form-item> <el-input v-model="searchVal" placeholder="请输入内容"></el-input> </el-form-item> <!-- 这个就是当前页面内,所有的btn列表 --> <el-form-item v-for="item in buttonList"> <!-- 这里触发点击事件 --> <el-button type="primary" @click="callFunc(item)">{{item.name}}</el-button> </el-form-item> </el-form> </el-col> </template> <script> export default { name: "Toolbar", data() { return { searchVal: "" //双向绑定搜索内容 }; }, props: ["buttonList"], //接受父组件传值 methods: { callFunc(item) { item.search = this.searchVal; this.$emit("callFunction", item); //将值传给父组件 } } }; </script>
相信每个人都能看的懂,只是字面意思能看得懂,其中的核心知识点就是 List for渲染,父给子传值,子给父传值,我下文会重点讲到,其中 buttonList 数组的格式,很简单,你可以自己后端封装一下,我这里就偷懒了,直接使用的菜单的数据结果,就是上边我 localstorage.routes 中的结构,毕竟我把按钮和菜单共有一套嘛。
那现在我们设计好了子组件——工具栏,接下来就要设计父组件了,传递数据和接受子组件广播了。
5、将按钮事件绑定到组件上
刚刚我们说到了 ,在 Toolbar.vue 中,核心的内容,就是把动态的事件方法给推送到一个个父组件上,这里是以 Role.vue 页面举例的,所有用到了 $emit("callFunction", item) 方法,这个如果你开发vue的话,肯定都知道这个的,这个父子通讯实例中,使用很多,具体的我在之前的文中中,也讲到了,你可以看看,这里不细说,说白了一句话,就是子组件执行父组件方法。二十║Vue基础终篇:传值+组件+项目说明。其实到这个地方,我也想到了,但是问题来了:你可以先看看 emit 的用法,使用 emit 一般都是传递数据,但是如果传递 function 的话,肯定也是一个 name 的字符串,那父组件接受到这个 function name 的时候,很容易当成一个 data,如果强行执行,他们又不在一个对象里,因为有闭包,如何让页面执行这个 function 呢?我思考了很久(说明自己学的不到家)。
这个就是这两个月来困扰我的地方,前边的思路和后边的 Table 隔离我都想到了,只是这里我没有想到,看来还是需要一些高级前端的朋友哟,前天听到了一个 apply 方法后,我豁然开朗,原来可以这样,那下边我就详细的说一说,如何父组件执行事件:
在 src\views\User\Roles.vue 页面呢,修改我们的工具栏使用:
这种引用组件,在data中,定义 buttonList ,就不说,重点还是要理解 @callFunction 这个必须要和子组件的 $emit 中的方法名一致。然后我们定义 callFunction,用来动态执行一个个事件:
callFunction(item) {//这个 item 就是我们的 permission.cs 数据 this.filters = { name: item.search };//这里是把子组件中的 search 内容,也接受过来 this[item.Func].apply(this, item);//核心就是要执行 apply 方法 },
是不是很简单,难点就在于,.apply()这个方法,下文会说到。这个 this ,就是当然父组件的内容,就是我们执行可以在子组件来调用父组件的方法了
这里再说下
6、父组件获取 ButtonList 数据
上边我们也说到了,我们把 button 和 菜单揉在一起了,所以我们很简单操作一下之前的数据就行,做一下筛选:
// 在 mounted 钩子中,调用 router let routers = window.localStorage.router ? JSON.parse(window.localStorage.router) : []; this.getButtonList(routers); // 定义方法,目的我为了递归 getButtonList(routers) { let _this = this; routers.forEach(element => { let path = this.$route.path.toLowerCase(); if (element.path && element.path.toLowerCase() == path) { _this.buttonList = element.children; return; } else if (element.children) { _this.getButtonList(element.children); } }); }
OK,数据准备完毕。
7、修改 Table 组件,将工具栏与 Table 逻辑隔离
到了这里就是最后一步了,我们把之前的 tabel 右侧 “操作栏” 删掉,统一放到顶部,然后绑定数据,就可以加载出来了,
现在我们把操作栏给取消了,但是我们如何获取 scope.row 呢?是不是很麻烦,要修改很多呢,其实不是的。
8、Table 改为单选,通过点击,选择某行
这个功能特别简单,思路就是通过单击某一行,来获取这个 table 的 row,这个 element 官网写的很详细,我就简单的说一下吧:
//触发事件,获取到这个row selectCurrentRow(val) { this.currentRow = val; }, <!--列表--> <el-table :data="users" highlight-current-row v-loading="listLoading" @current-change="selectCurrentRow" style="width: 100%;" >
然后只需要简单的修改一下我们的 edit 和 delete 方法即可,因为我们已经拿到了这个 row:
搞定啦!是不是很简单,几乎没有修改什么,感觉之前设计的方案还可以吧,至少扩展还是很不错的!
到了这里,我们的动态按钮权限功能,就已经完全做完了,一个八个步骤,大家动手起来,搞一搞吧。
三、重点知识解析
1、组件 ——子传父 & 父传子
这块内容呢,其实我们都已经讲过很多遍了,父传子很简单,只需要定一个自定属性即可,然后子组件接受,比如上文中的:
<toolbar :buttonList="buttonList" @callFunction="callFunction"></toolbar> name: "Toolbar", data() { return { searchVal: "" //双向绑定搜索内容 }; }, props: ["buttonList"], //接受父组件传值
比较复杂的就是 子传父 了,重点还是要了解一些 $emit 这个api,二十║Vue基础终篇:传值+组件+项目说明 我这篇文章写的还算是详细,如果还是不懂,咱们再一对一讨论吧。
2、动态事件绑定—— apply
这个apply 有点儿想 call 回调函数,首先,每个函数都包含两个非继承而来的方法:.apply()和 .call()。这两个方法的用途都是在特定的作用域中调用函数,实际等于设置函数体内this对象的值。
这两个方法接收的参数可以分为两个部分,
第一部分是在其中运行函数的作用域,如果就在当前函数体中运行,就可以直接使用this值,如果在window作用域中使用,可以传入window值,这样,可以实现扩充作用域;
第二部分是参数组,在apply中可以传入Array实例,也可以是arguments对象;在call中,传递给函数的参数必须逐个列举;如果没有参数,这个部分可以省略。
首先我们来看看网上apply()方法的定义:
1. apply()方法能劫持另外一个对象的方法,继承另外一个对象的属性
2.Function.apply(obj,args)方法能接收两个参数
3.obj:这个对象将代替Function类里this对象
4.args:这个是数组,它将作为参数传给Function(args–>arguments)
举个例子,如下所示:
function sum(num1,num2){ return num1+num2; } //两个数相等就相加,不相等就相乘 function mul(num1,num2){ if(num1 != num2){ return num1*num2; }else{ return sum.apply(this,arguments); //可以为 sum.apply(this,[num1,num2])或sum.call(this,num1,num2); } } console.log(mul(5,6)); //30 console.log(mul(6,6)); //12
说句简单的,我认为就是在其他地方,去调用某一个方法,很重要的一个点,就是 this 这个到底指向什么,自己可以好好调调。
3、动态路由过滤—— addRoutes
这个在上边的步骤里我没有说到,是因为我们把 按钮 给放出来以后,在动态菜单路由的时候,会出现重复的问题,所以我们就需要坐下过滤,注意这个不是错误,是警告,意思就是我们把一些重复的东西添加到路由里了,路由会忽略掉,只不过给大家一个 warm 而已。
所以呢,我做了一个过滤,封装了下 route.addRoutes——在 src\router\index.js 中,我们过滤下重复路由,还是递归:
router.$addRoutes = (params) => { var f = item => { if (item['children']) { item['children'] = item['children'].filter(f); return true; } else if (item['IsButton']) { return item['IsButton']===false; } else { return true; } } var paramsFilt = params.filter(f); router.addRoutes(paramsFilt) }
然后咋其他的地方,将 router.addRoutes 统一都换成 router.$addRoutes 。但是这个目前还有一些小问题,我会后期继续优化。
四、Github && Gitee
Core: https://github.com/anjoy8/Blog.Core
Vue: https://github.com/anjoy8/Blog.Admin