利用vue組件中的render函數抽離組件中的可複用邏輯

需求(一個簡單的栗子):

在涉及到權限控制的應用中,常常遇到這樣的需求:根據用戶角色判斷某個組件(例如某個刪除按鈕、標籤頁)是否須要顯示。最直接的解決方法就是利用v-if或者v-show對這種組件挨個判斷。vue

例如:

<template>
<div>
    <button v-if='user.type === "admin"'>管理員纔可見的按鈕</button>
    <button v-if='user.type === "user"'>普通用戶纔可見的按鈕</button>
</div>
</template>
<script>
import { useState } from 'vuex';

export default {
    computed: {
        ...useState(['user'])   //存儲的user信息
    }
}
</script>
複製代碼

但若是項目中遇到大量這樣的組件時,每一個組件文件都須要編寫獲取用戶信息、判斷用戶角色的重複代碼,怎麼才能把這些代碼優雅地抽離複用呢?

初步解決方案:

編寫已封裝好業務邏輯的組件,好比組件ButtonForAdmin:vuex

<template>
<button v-if='user.type === "admin"'>管理員纔可見的按鈕</button>
</template>
<script>
import { useState } from 'vuex';

export default {
    computed: {
        ...useState(['user'])   //存儲的user信息
    }
}
</script>
複製代碼

這種方法能夠必定程度上減輕代碼重複度,缺點是當項目中每有一個不一樣的組件須要實現該需求時都要封裝一遍。bash

進一步抽離:

爲了讓每一個不一樣的組件均可以複用一個邏輯,能夠使用slot機制並使用傳參的方式統一判斷用戶角色:ui

<template>
<div>
    <slot v-if='roles.indexOf(user.type) !== -1'></slot>
</div>
</template>
<script>
import { useState } from 'vuex';

export default {
    props: {
        roles: {
            type: Array,    //在哪些用戶角色時可見
            default() {
                return [];
            }
        }
    },
    computed: {
        ...useState(['user'])   //存儲的user信息
    }
}
</script>
複製代碼

這個方法能夠經過slot機制對任何傳入組件並經過傳入的參數統一判斷是否須要顯示,但此方法依然優缺點:因爲slot不能做爲組件根元素,使用該組件會比原來多增長一個DOM元素,並影響原來的樣式。this

使用render方法劫持渲染內容

<script>
import { useState } from 'vuex';

export default {、
    name: 'role-limit',
    props: {
        roles: {
            type: Array,    //在哪些用戶角色時可見
            default() {
                return [];
            }
        }
    },
    computed: {
        ...useState(['user'])   //存儲的user信息
    },
    render() {
        const slot = this.$slots.default;
        if (roles.indexOf(this.user.type) !== -1) {
            return slot;
        }
        return null;    //不渲染內容
    }
}
</script>
複製代碼

使用Vue.Component()註冊爲全局組件後,可在項目中隨意經過用戶角色控制某個組件的顯示:spa

<template>
<div>
    <role-limit :roles='["admin"]'>
        <button>管理員纔可見的按鈕</button>
    </role-limit>
    <role-limit :roles='["user"]'>
        <button>普通用戶纔可見的按鈕</button>
    </role-limit>
</div>
</template>
複製代碼
相關文章
相關標籤/搜索