从 Chrome 扩展访问 Vue 组件方法

Accessing Vue component methods from Chrome Extension

我正在为特定页面构建 chrome 扩展程序:https://www.vidangel.com/

我不拥有该页面,但检查它后,我发现它是基于 Vue 构建的。我需要读取该页面多次使用的特定信息,可通过名为“getActiveTags”的方法访问该信息(以防有人费心查看捆绑文件 https://www.vidangel.com/js/app.25e52655.js)。它是 Vue 组件之一中的方法:

<template>
      <div class="lineup-barvisual">
        <div class="lineup-barvisual-panel">
          <div class="lineup-barvisual-title">You'll see</div>
          <svg>
            <defs>
              <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
                <stop class="stop-start" offset="0%" />
                <stop class="stop-end" offset="100%" />
              </linearGradient>
            </defs>
            <rect class="backdrop"></rect>
            <g v-if="tag_set && lineup">
              <rect class="cuts" v-for="tag in getActiveAudioTags()" :key="tag.id" :x="tagLeft(tag)" :width="tagWidth(tag)"/>
            </g>
          </svg>
        </div>
        <div class="lineup-barvisual-panel">
          <div class="lineup-barvisual-title">You'll hear</div>
          <svg>
            <rect class="backdrop"></rect>
            <g v-if="tag_set && lineup">
              <rect class="cuts" v-for="tag in getActiveTags()" :key="tag.id" :x="tagLeft(tag)" :width="tagWidth(tag)" />
            </g>
          </svg>
        </div>
      </div>
    </template>
    
    <script>
      import api from 'services/api'
      export default {
        props: ['tag_set', 'lineup'],
        methods: {
          tagLeft(tag) {
            return ((tag.start_approx / this.lineup.work.duration) * 100) + '%'
          },
          tagWidth(tag) {
            return Math.max((((tag.end_approx - tag.start_approx) / this.lineup.work.duration) * 100), 0.075) + '%'
          },
          getActiveTags() {
            return this.tag_set.tags.filter(tag => this.lineup.isTagOn(tag))
          },
          getActiveAudioTags() {
            return this.getActiveTags().filter(tag => tag.type === 'audiovisual')
          },
          paint() {
            this.$forceUpdate()
          }
        },
        watch:{
          'lineup.id'(id, old_id) {
            api.hub.$off(`model.lineup.${old_id}.touched`, this.paint)
            if (id) api.hub.$on(`model.lineup.${id}.touched`, this.paint)
          }
        },
        beforeDestroy() {
          if (this.lineup) {
            api.hub.$off(`model.lineup.${this.lineup.id}.touched`, this.paint)
          }
        }
      }
    </script>

我不知道这些 'tag_set' 和 'lineup' 道具是从哪里来的(我没有很好的 Vue 知识),但它们似乎与此有关:

从 'services/api'

导入 api
let TagSet = api.defineResource({
  name: 'TagSet',
  endpoint: 'tag-sets',
  relations: {
    belongsTo: {
      CatalogItem: {
        localField: 'work',
        localKey: 'work_id'
      }
    },
    hasMany: {
      Tag: {
        localField: 'tags',
        foreignKey: 'tag_set_id'
      }
    }
  },
  methods: {
    tags_count() {
      return this.tags.length
    },
    tags_active(lineup) {
      return this.tags.filter(t => lineup.refmap[t.ref_id])
    },
    tags_active_count(lineup) {
      return this.tags_active(lineup).length
    }
  },
  watchChanges: false
})

api.defineResource({
  name: 'Tag',
  relations: {
    belongsTo: {
      TagCategory: {
        localField: 'category',
        localKey: 'category_id'
      }
    }
  }
})

export default TagSet

虽然我不知道这是怎么回事。我想标签集信息存储在某种 redux 对象中,因为它可以从多个组件访问。

我目前使用的解决方案是使用 declarativeNetRequest 覆盖捆绑文件,并稍微修改脚本,其中在 getActiveTags 方法中包含一小段代码,用于创建或更新 DOM,它的 InnerText 是 getActiveTags:

的 return 值的精简版本
    getActiveTags: function () {
        var t = this;
        let tags = this.tag_set.tags.filter(e => t.lineup.isTagOn(e));
        let tagsMap = tags.map(tag => ({begin: tag.begin, end: tag.end}));
        let elemento = document.getElementById('lista-tags');
        if (!elemento) {
          elemento = document.createElement('span');
          elemento.id = 'lista-tags';
          elemento.style = 'display: none';
          document.body.appendChild(elemento);
        }
        elemento.innerText = JSON.stringify(tagsMap);
        return tags;

我已尝试将“getActiveTags”方法添加到全局 window 对象,该对象可以在开发工具上访问,但无法从扩展代码访问,即使在 contentScript 中也是如此(我不知道不知道为什么)。但即使该解决方案更好,它仍然存在问题,因为我必须保留一份包含这些修改的捆绑包副本,因此用户可能会看到该页面的过时版本,以防原始页面进行修改。

所以我真正想要的是一种从 window 对象访问的方法,即原始脚本定义的 vue 组件的方法,而不必覆盖 bundle。有没有办法做到这一点?我将如何找到 vue 组件? (我已经尝试了很长时间在开发工具上检查 window 对象,但没有找到 vue 组件。)谢谢。

想了半天终于明白了。您可以通过元素的 .__vue__ 对象访问 vue 组件方法。所以,就我而言,我必须这样做:

document.querySelector('.lineup-barvisual').__vue__.getActiveTags()