Один и тот же компонент Vue дважды на одной странице дублирует представление компонента

#javascript #vue.js #vuejs2 #vue-component

#javascript #vue.js #vuejs2 #vue-компонент

Вопрос:

Итак, я создаю приложение для просмотра потоков локальных IP-камер. У меня есть компонент, который передает потоки MJPEG по сети, а затем отображает их в компоненте MJPG.vue. Это работает просто отлично, как я и ожидал.

Проблема, с которой я сталкиваюсь, заключается в том, что, оказавшись внутри MJPG.vue, пользователь может щелкнуть потоковое изображение, чтобы перейти во вторичный режим «воспроизведения», который позволит им получить доступ к записанным данным. Поэтому мне нужно по существу повторно использовать тот же компонент MJPG.vue в представлении воспроизведения. Второй экземпляр компонента MJPG.vue ведет себя некорректно и в какой-то момент является точной копией первого экземпляра. Если я приостанавливаю воспроизведение первого компонента, второй экземпляр компонента приостанавливается. Если я приостанавливаю второй экземпляр, первый в фоновом режиме приостанавливается.

Вот что сбивает с толку. ЕСЛИ я вручную жестко запрограммирую ДРУГОЙ поток камеры во втором экземпляре компонента, оба этих компонента будут транслироваться независимо друг от друга и работать должным образом. Похоже, что Vue повторно использует один и тот же экземпляр дважды вместо того, чтобы каждый экземпляр компонента был своим.

MJPG.vue

 <template>
<img ref="img" :src="img.src" style="border:1px solid white" height=500 width=500 />
</template>

<script>
export default {
  props: {
    camera: {
      type: Object,
      required: true
    },
    aspectRatio: {
      type: Number
    }
  },
  computed: {
    isPlay() {
      return this.$store.state.DVR.isPlay;
    },
    .......
  },
  watch: {
    isPlay(n) {
      n ? this.play() : this.pause();
    },
    img(n, o) {
      if (o.src !== '') {
        // Old img has a real blob url, revoke it to clean up memory.
        URL.revokeObjectURL(o.src); // Must be done for garbage collection, or else memory leaks will form.
      }
      if (n.error === 204) {
        // Image didnt get sent back from the API/Error or problem with image?
        this.errorCount  ;
      } else {
        this.errorCount = 0;
        this.setImgSize();
        this.imageBuffer.src = n.src; // Buffer image is so we can determine the real size of the frame received.
      }
    },
    layoutChanged() {
      this.$nextTick(function() {
        this.getWrapperSize();
        this.setImgSize();
      });
    },
    errorCount() {
      // There seems to be some problems with the stream, it could be down. We need to calculate how long to keep checking for images.
      if (this.errorCount * this.framerate >= this.timeout * 1000) {
        this.pause();
        this.streamDown();
      }
    }
  },
  data() {
    return {
      isLoading: true, // If the stream is loading or not.
      display: false, // Used in v-if to show the img to the user.
      img: '', // The src attribute of the image blob(blob:url) the user will see.
      timeout: 15, // Seconds until stream connection error timeout.
      errorCount: 0, // Stream error counter.
      isDown: false, // If the stream is believed to be down.
      backgroundWorker: null, // Background worker that handles the setTimeout lag issues.
      backgroundWorkerGW: null, // Background worker that handles the setTimeout lag issues.
      imageBuffer: new Image(), // Buffer image to collect received image sizes.
      imgHeight: 0, // Height of the image the user will see.
      imgWidth: 0, // Width of the image the user will see.
      imgRatio: null, // Then aspect ratio of the imageBuffer, used to calculate image size for its container.
      wrapperHeight: 0, // Wrapper div height.
      wrapperWidth: 0, // Wrapper div width.
      showOverflowOnActual: false, // Should the scrollbars be displayed on the image? Used for Actual image size setting.
      framerate: 0 // The framerate that the API is getting new images.
    };
  },
  mounted() {
      // Do some stream setup here...
  },
  methods: {
      // Streaming functions here...
  }
</script>

<style scoped>
.....
</style>
  

Комментарии:

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

2. @Ohgod Почему любая ссылка на $ store внутри компонента вызовет это дублирование наблюдаемости во всех экземплярах этого же компонента?

3. ДА. Все они просматривают одну и ту же переменную. Рассмотрите возможность использования уникальной переменной в хранилище для каждого DVR.

4. @Ohgod Почему так в MJPG.vue я удалил все ссылки на Vuex ($ store) и его поведение по-прежнему остается тем же.