Vuejs - проблема при удалении компонента с помощью директив и при выполнении подключенного / созданного события.

Я хотел, чтобы моя директива работала как v-if, поскольку в моей директиве я должен проверять права доступа и уничтожать элемент, если у него нет доступа.

Вот мой код

Vue.directive('access',  {
    inserted: function(el, binding, vnode){

        //check access

        if(hasAccess){
           vnode.elm.parentElement.removeChild(vnode.elm);
        }
    },

});

vue файл

<my-component v-access='{param: 'param'}'>

Проблема в том, что я применяю эту директиву к компоненту, она удаляет компонент, но не выполняет функции, вызываемые ловушкой created / connected.

В компоненте (my-component) есть функции в хуке mount / created. Выполнение этих функций завершено, и я не хочу, чтобы эти функции выполнялись. Есть ли способ остановить выполнение смонтированных / созданных событий?


person user3910487    schedule 05.06.2020    source источник
comment
не могли бы вы обернуть код в смонтированный и созданный в блоке if, чтобы, если ваше условие не выполняется, код не выполняется, пока компонент уничтожен   -  person Ayudh    schedule 05.06.2020
comment
Вы не должны использовать для этого директивы. Директивы не могут вообще предотвратить создание компонента (v-if не является настоящей директивой).   -  person Decade Moon    schedule 05.06.2020
comment
Очень полезная информация. michaelnthiessen.com/force-re-render Я столкнулся с той же проблемой, и даже forceUpdate не помог ' не решить мою проблему. В моем случае помогла стратегия смены ключей)   -  person akim lyubchenko    schedule 05.06.2020
comment
@DecadeMoon, хорошо, мне нужно сделать что-то глобальное, что я могу применить ко всем компонентам во всем приложении. У тебя есть идеи, как я могу это сделать?   -  person user3910487    schedule 05.06.2020


Ответы (1)


Невозможно воспроизвести поведение v-if в пользовательской директиве. Директивы не могут контролировать рендеринг vnodes, они влияют только на элемент DOM, к которому он прикреплен. (v-if особенный, на самом деле это не директива, а вместо этого генерирует код условного рендеринга при компиляции шаблона.)

Хотя я бы по возможности избегал делать какие-либо из следующих предложений, я все равно их предоставлю, поскольку это близко к тому, что вы хотите сделать.

1. Расширьте прототип Vue, чтобы добавить глобальный метод.

Вам определенно нужно использовать v-if для условного рендеринга. Итак, все, что нам нужно сделать, это придумать глобальный вспомогательный метод, который вычисляет права доступа.

Vue.prototype.$access = function (param) {
  // Calculate access however you need to
  // ("this" is the component instance you are calling the function on)
  return ...
}

Теперь в ваших шаблонах вы можете сделать это:

<my-component v-if="$access({ param: 'param' })">

2. Определите глобальный метод в корневом компоненте.

Это в основном то же самое, что и # 1, за исключением того, что вместо того, чтобы загрязнять прототип Vue мусором, вы определяете метод только в корневом экземпляре:

new Vue({
  el: '#app',
  render: h => h(App),
  methods: {
    access(param) {
      return ...
    }
  }
})

Теперь в ваших шаблонах вы можете сделать это:

<my-component v-if="$root.access({ param: 'param' })">

Теперь яснее, где определяется метод.

3. Используйте глобальный миксин

Возможно, это не идеально, но вы можете исследовать жизнеспособность , если это того стоит. глобальный миксин.

4. Используйте настраиваемый компонент.

Вы можете создать собственный компонент (в идеале функциональный, но это не обязательно), который может рассчитывать доступ для определенных регионов в вашем шаблоне:

Vue.component('access', {
  functional: true,
  props: ['param'],
  render(h, ctx) {
    // Calculate access using props as input
    const access = calculateAccess(ctx.props.param)

    // Pass the access to the default scoped slot
    return ctx.scopedSlots.default(access)
  }
})

В своих шаблонах вы можете сделать это:

<access :param="param" v-slot="access">
  <!-- You can use `access` anywhere in this section -->
  <div>
    <my-component v-if="access"></my-component>
  </div>
</access>

Поскольку <access> является функциональным компонентом, на самом деле он не будет отображать собственный экземпляр компонента. Думайте об этом больше как о функции, чем о компоненте.

Немного избыточно для вашей ситуации, но тем не менее интересно, если у вас когда-либо будет более сложный сценарий.

person Decade Moon    schedule 06.06.2020
comment
Большое спасибо за все эти решения, это действительно помогает. :) - person user3910487; 08.06.2020