vuejs中类似于v-if的自定义指令

Posted

技术标签:

【中文标题】vuejs中类似于v-if的自定义指令【英文标题】:A custom directive similar to v-if in vuejs 【发布时间】:2017-08-17 15:44:45 【问题描述】:

我正在 vue 中编写自定义指令。

我希望它像v-if 一样工作,但它内部会有一点逻辑。让我用一个例子来解释:

<button v-permission="PermissionFoo">Do Foo</button>

它会检查权限并显示或隐藏组件。

目前我正在通过 CSS 样式执行此操作:

var processPermissionDirective = function (el, binding, vnode) 
    if (SOME_LOGIC_HERE) 
        el.style.display = el._display;
    
    else 
        el.style.display = 'none';
    


export default 
    bind: function (el, binding, vnode) 
        el._display = el.style.display;
        processPermissionDirective(el, binding, vnode);
    ,
    update: function (el, binding, vnode) 
        processPermissionDirective(el, binding, vnode);
    

但我不希望这个元素留在文档中。所以我正在寻找 CSS 以外的另一种方式,因为它也必须像 v-if 那样从 DOM 中删除。

【问题讨论】:

【参考方案1】:

尝试使用这个技巧:

Vue.directive('permission', (el, binding, vnode) => 
  if (!isUserGranted(binding.value)) 
    // replace htmlElement with comment node
    const comment = document.createComment(' ');
    Object.defineProperty(comment, 'setAttribute', 
      value: () => undefined,
    );
    vnode.elm = comment;
    vnode.text = ' ';
    vnode.isComment = true;
    vnode.context = undefined;
    vnode.tag = undefined;
    vnode.data.directives = undefined;

    if (vnode.componentInstance) 
      vnode.componentInstance.$el = comment;
    

    if (el.parentNode) 
      el.parentNode.replaceChild(comment, el);
    
  
);

UPD 05-19-2017:我的最新代码。我定义了setAttribute() 并检查vnode.componentInstance 以防止在同时使用html 元素和Vue 组件时出现js 错误。

【讨论】:

这是一个很好的答案,但它会在控制台中显示'Cannot set property '$el' of undefined'。 当我删除 vnode.componentInstance.$el = comment; 时效果很好因为在我的情况下 componentInstance 是未定义的。谢谢 其他人遇到过这样的问题,即当组件数据随之更改时会创建一个空的 html 标记? 在使用 vue-test-utils 时,假设您正在寻找类似于 v-if 的功能,这不会通过任何单元测试 el.parentElement 始终为空。然而,当检查它不是......这使得这不可行

以上是关于vuejs中类似于v-if的自定义指令的主要内容,如果未能解决你的问题,请参考以下文章

Vue2:自定义指令,如 v-if

什么是vue.js中的自定义指令?

vue2.0和vue3.0中自定义指令(directive)的区别

vue中自定义指令

十自定义指令与ESLint代码检查工具使用

怎么写一个全局的自定义指令