从 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()
我正在为特定页面构建 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'
导入 apilet 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()