奇葩需求
需要用Chrome插件将数据赋值给当前页面的表单里,美其名曰帮客户自动填入
头脑风暴
本来是想获取一下当前表单元素,然后一个一个给它赋值,但是input的值好赋啊,其他下拉选择的咋搞
关键是这个当前页面是别人家的,不是我们自己的!!
在控制台倒腾半天,发现人家页面是用Vue写的,UI组件用的elementUI,那form上就会有个Vue的实例,那直接操作这个实例就好了!
尝试一下
立刻就能看到效果!!
在Chrome插件里面尝试一下
// content.js
let vueInstance = window.document.querySelectorAll('.el-form')[0].__vue__;
console.log('Vue instance:', vueInstance);
结果
🤣笑死,在Chrome插件的content.js里面根本找不到__vue__
当前页面的window和Chrome插件的content.js里面的window根本不是一个
换成在background.js也一样找不到o(╥﹏╥)o
ChatGPT提供了2种思路
不得不说ChatGPT还是牛的
- 思路一
// In content.js
let vueInstance = document.querySelector('#app').__vue__;
window.postMessage({ type: 'VUE_INSTANCE', data: vueInstance }, '*');
// In the web page
window.addEventListener('message', (event) => {
if (event.source !== window || event.data.type !== 'VUE_INSTANCE') {
return;
}
let vueInstance = event.data.data;
console.log('Vue instance:', vueInstance);
});
- 思路二
// In content.js
let script = document.createElement('script');
script.textContent = `
window.vueInstance = document.querySelector('#app').__vue__;
`;
document.documentElement.appendChild(script);
script.remove();
console.log('Vue instance:', window.vueInstance);
// In the web page
console.log('Vue instance:', window.vueInstance);
- 思路三
// In content.js
chrome.runtime.sendMessage({ type: 'GET_VUE_INSTANCE' }, (vueInstance) => {
console.log('Vue instance:', vueInstance);
});
// In the background page
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'GET_VUE_INSTANCE') {
let vueInstance = document.querySelector('#app').__vue__;
sendResponse(vueInstance);
}
});
以上思路一我没有办法,因为当前页面是别人的,所以直接pass,思路二和三我试了也是毫无反应!!!
最终解决办法
我基于上面的思路2,就是直接在Chrome插件的content.js里面去注入一段js脚本,在这个js里面去执行,d=但是我不remove,看看能不能找到vue的实例,
const obj = {jobName:'关注一下石马上coding谢谢'}
let script = document.createElement('script');
script.textContent = `
const formData = ${JSON.stringify(obj)};
console.log('%c [ formData ]-27', 'font-size:13px; background:pink; color:#bf2c9f;', formData)
window.vueInstance = window.document.querySelectorAll('.el-form')[0].__vue__;
// window.vueInstance.model['jobName'] = '关注一下石马上coding谢谢';
for (let key in formData) {
if(window.vueInstance.model.hasOwnProperty(key)) {
console.log('hasOwnProperty',key)
window.vueInstance.model[key] = formData[key]
} else {
console.log('no Property================>',key)
}
}
`;
document.documentElement.appendChild(script);
结果竟然成功了O(∩_∩)O哈哈~
总结
- content.js在与网页分离的环境中运行,无法直接访问网页的JavaScript对象,包括Vue实例
- 可以参考上面ChatGPT的3个思路,我的最终解决办法是根据第2个思路来的,灵活变通了一下,不过也要看具体需求具体分析。